YUNHE ENMO (BEIJING) TECHNOLOGY CO.,LTD 从菜鸟到专家成 …

21
云和恩墨 成就所托 云和恩墨 成就所托 云和恩墨 成就所托 从菜鸟到专家成长系列之一 大梦初醒 云和恩墨(北京)信息技术有限公司 ACE:侯圣文、李轶楠、杨廷琨、张乐奕 邮箱:[email protected] YUNHE ENMO (BEIJING) TECHNOLOGY CO.,LTD

Transcript of YUNHE ENMO (BEIJING) TECHNOLOGY CO.,LTD 从菜鸟到专家成 …

Page 1: YUNHE ENMO (BEIJING) TECHNOLOGY CO.,LTD 从菜鸟到专家成 …

云和恩墨 成就所托 云和恩墨 成就所托 云和恩墨 成就所托

从菜鸟到专家成长系列之一 大梦初醒

云和恩墨(北京)信息技术有限公司

ACE:侯圣文、李轶楠、杨廷琨、张乐奕

邮箱:[email protected]

YUNHE ENMO (BEIJING) TECHNOLOGY CO.,LTD

Page 2: YUNHE ENMO (BEIJING) TECHNOLOGY CO.,LTD 从菜鸟到专家成 …

云和恩墨 成就所托 云和恩墨 成就所托

故事背景: 使用同步软件,把源端数据同步到目标端时,产生了报错。

Release 11.2.0.3.0

报 错:

ERROR at line 1:

ORA-01400: cannot insert NULL into ("TEST"."T_PROD"."TYPE")

人物角色: 甲方老总 ------ 杨廷琨 乙方主管 ------ 张乐奕 乙方驻场DBA ------ 李轶楠 恩墨学院院长 ------ 侯圣文

Page 3: YUNHE ENMO (BEIJING) TECHNOLOGY CO.,LTD 从菜鸟到专家成 …

云和恩墨 成就所托 云和恩墨 成就所托

行级锁 Oracle

事务

日志挖掘

小小DBA:哎呦,这个问题很简单了撒。一定是你那个Type字段不能为空值,可是你插入的数据是null,所以报错。您修改程序,或者把错误的数据删掉就可以了。 甲方老总:报错的原因是什么?为什么源数据库没有问题?

……

Page 4: YUNHE ENMO (BEIJING) TECHNOLOGY CO.,LTD 从菜鸟到专家成 …

云和恩墨 成就所托 云和恩墨 成就所托

行级锁 Oracle

事务

日志挖掘

SQL> select * from t_def;

ID NAME TYPE

---------- ------------------------------ --------

1 a

这不科学!

Page 5: YUNHE ENMO (BEIJING) TECHNOLOGY CO.,LTD 从菜鸟到专家成 …

云和恩墨 成就所托 云和恩墨 成就所托

行级锁 Oracle

事务

日志挖掘

SQL> select dump(type) from t_def;

DUMP(TYPE)

--------------------------------------------

NULL

SQL> select nvl(type, 'is null') from t_def;

NVL(TYPE

--------

is null

SQL> select * from t_def where type is null;

no rows selected

SQL> select * from t_def where type is not null;

ID NAME TYPE

---------- ------------------------------ --------

1 a

Page 6: YUNHE ENMO (BEIJING) TECHNOLOGY CO.,LTD 从菜鸟到专家成 …

云和恩墨 成就所托 云和恩墨 成就所托

第一个查询和第二个查询明确的告诉我们,TYPE列

的值不是NULL值 第三个查询和第四个查询又确切告之我们,TYPE列

是NULL值 到底TYPE列的值是NULL还是NOT NULL呢?

这是一个问题!

Page 7: YUNHE ENMO (BEIJING) TECHNOLOGY CO.,LTD 从菜鸟到专家成 …

云和恩墨 成就所托 云和恩墨 成就所托

查查数据到底是什么样的

看块结构,dump dump块

Page 8: YUNHE ENMO (BEIJING) TECHNOLOGY CO.,LTD 从菜鸟到专家成 …

云和恩墨 成就所托 云和恩墨 成就所托

行级锁 Oracle

事务

日志挖掘

案例分析

SQL> select dbms_rowid.rowid_relative_fno(rowid), dbms_rowid.rowid_block_number(rowid)

from t_def;

DBMS_ROWID.ROWID_RELATIVE_FNO(ROWID) DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)

------------------------------------ -----------------------------------

4 73109

SQL> alter system dump datafile 4 block 73109;

System altered.

Page 9: YUNHE ENMO (BEIJING) TECHNOLOGY CO.,LTD 从菜鸟到专家成 …

云和恩墨 成就所托 云和恩墨 成就所托

Block header dump: 0x0102a435

Object id on Block? Y

seg/obj: 0x145df csc: 0x00.23b6097 itc: 2 flg: E typ: 1 - DATA

brn: 0 bdba: 0x102a430 ver: 0x01 opc: 0

inc: 0 exflg: 0

Itl Xid Uba Flag Lck Scn/Fsc

0x01 0x0008.01b.00001afc 0x00c026de.11be.10 --U- 1 fsc 0x0000.023b6098

0x02 0x0000.000.00000000 0x00000000.0000.00 ---- 0 fsc 0x0000.00000000

bdba: 0x0102a435

data_block_dump,data header at 0x7fe7fdc97264

===============

……

block_row_dump:

tab 0, row 0, @0x1f90

tl: 8 fb: --H-FL-- lb: 0x1 cc: 2

col 0: [ 2] c1 02

col 1: [ 1] 61

end_of_block_dump

End dump data blocks tsn: 4 file#: 4 minblk 173109 maxblk 173109

Page 10: YUNHE ENMO (BEIJING) TECHNOLOGY CO.,LTD 从菜鸟到专家成 …

云和恩墨 成就所托 云和恩墨 成就所托

根据实际的存储得知,Type列确实为空。

可是,为什么用“select * from t_def where

type is null”查看,Oracle会告诉我们一个错

误的结果呢?

Page 11: YUNHE ENMO (BEIJING) TECHNOLOGY CO.,LTD 从菜鸟到专家成 …

云和恩墨 成就所托 云和恩墨 成就所托

行级锁 Oracle

事务

日志挖掘

SQL> set autot on exp

SQL> select * from t_def where type is null;

no rows selected

Execution Plan

----------------------------------------------------------

Plan hash value: 177263571

----------------------------------------------------------------------------

| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |

----------------------------------------------------------------------------

| 0 | SELECT STATEMENT | | 1 | 5 | 0 (0)| |

|* 1 | FILTER | | | | | |

| 2 | TABLE ACCESS FULL| T_DEF | 1 | 5 | 3 (0)| 00:00:01 |

----------------------------------------------------------------------------

Predicate Information (identified by operation id):

---------------------------------------------------

1 - filter(NULL IS NOT NULL)

Page 12: YUNHE ENMO (BEIJING) TECHNOLOGY CO.,LTD 从菜鸟到专家成 …

云和恩墨 成就所托 云和恩墨 成就所托

SQL> select * from t_def where type is not null;

ID NAME TYPE

---------- -------- --------

1 a

Execution Plan

----------------------------------------------------------

Plan hash value: 1057129282

---------------------------------------------------------------------------

| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |

---------------------------------------------------------------------------

| 0 | SELECT STATEMENT | | 1 | 5 | 3 (0)| 00:00:01 |

| 1 | TABLE ACCESS FULL| T_DEF | 1 | 5 | 3 (0)| 00:00:01 |

---------------------------------------------------------------------------

Page 13: YUNHE ENMO (BEIJING) TECHNOLOGY CO.,LTD 从菜鸟到专家成 …

云和恩墨 成就所托 云和恩墨 成就所托

由于表中的TYPE列具有非空约束(not null),导致CBO给出的执行计划返回了错误的结果。

当限定条件为:where type is null时,CBO认为此查询与约束相悖,自动添加了一个(null is not

null)的过滤,返回零行结果。

Page 14: YUNHE ENMO (BEIJING) TECHNOLOGY CO.,LTD 从菜鸟到专家成 …

云和恩墨 成就所托 云和恩墨 成就所托

Why:该列中

会有空值? How:数据怎么

绕过非空约束的?

Page 15: YUNHE ENMO (BEIJING) TECHNOLOGY CO.,LTD 从菜鸟到专家成 …

云和恩墨 成就所托 云和恩墨 成就所托

SQL> select dbms_metadata.get_ddl('TABLE', 'T_DEF') from dual;

DBMS_METADATA.GET_DDL('TABLE','T_DEF')

---------------------------------------------------------

CREATE TABLE "TEST"."T_DEF"

( "ID" NUMBER,

"NAME" VARCHAR2(8) DEFAULT 'a',

"TYPE" VARCHAR2(8) DEFAULT '' NOT NULL ENABLE

) SEGMENT CREATION IMMEDIATE

PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255

NOCOMPRESS LOGGING

STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS

2147483645

PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1

BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE

DEFAULT)

TABLESPACE "USERS"

查询表结构

Page 16: YUNHE ENMO (BEIJING) TECHNOLOGY CO.,LTD 从菜鸟到专家成 …

云和恩墨 成就所托 云和恩墨 成就所托

SQL> CREATE TABLE T_TEST (ID NUMBER, NAME VARCHAR2(30) DEFAULT '' NOT

NULL);

表已创建。

SQL> INSERT INTO T_TEST (ID) VALUES (1);

INSERT INTO T_TEST (ID) VALUES (1)

*

第 1 行出现错误:

ORA-01400: 无法将 NULL 插入 ("TEST"."T_TEST"."NAME")

测试:如果列上有非空约束,即使该列default是null值,也是无法插入null值的

Page 17: YUNHE ENMO (BEIJING) TECHNOLOGY CO.,LTD 从菜鸟到专家成 …

云和恩墨 成就所托 云和恩墨 成就所托

Page 18: YUNHE ENMO (BEIJING) TECHNOLOGY CO.,LTD 从菜鸟到专家成 …

云和恩墨 成就所托 云和恩墨 成就所托

Null

• Not Null约束

• CBO优化器

Oracle 11g新特性

• Default

•快速添加非空默认值

版本演进

• 10g---null is not null执行计划

• 11g

Page 19: YUNHE ENMO (BEIJING) TECHNOLOGY CO.,LTD 从菜鸟到专家成 …

云和恩墨 成就所托 云和恩墨 成就所托

快速添加非空默认值

SQL> create table t_def (id number, name varchar2(30) default '' not null);

Table created.

SQL> insert into t_def values (1, 'a');

1 row created.

SQL> alter table t_def add type varchar2(8) default '' not null;

Table altered.

SQL> select * from t_def;

ID NAME TYPE

---------- -------------------------------------------- --------

1 a

Oracle确实允许NOT NULL列的默认值为NULL,如果不指定默认值那么就相当于默认值为NULL,但是

对于11g新增的新特性而言,DEFAULT为NULL是要禁止的,否则就会导致现有记录的NOT NULL字段出

现NULL值。

Page 20: YUNHE ENMO (BEIJING) TECHNOLOGY CO.,LTD 从菜鸟到专家成 …

云和恩墨 成就所托 云和恩墨 成就所托

Weibo:@恩墨学院

网 站:http://www.enmoedu.com

Email:[email protected]

电 话:400-660-8755

13552144418

Page 21: YUNHE ENMO (BEIJING) TECHNOLOGY CO.,LTD 从菜鸟到专家成 …

云和恩墨 成就所托 云和恩墨 成就所托