`
itspace
  • 浏览: 978317 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Oracle如何高效抛出ora-00001错误

阅读更多
今天吃饭排队的时候,脑子突然闪出一个念头。设想一下以下场景:
在一张大表,可能有上亿条数据,在表中建立了主键或者唯一索引。当有会话插入数据违反唯一性约束时,Oracle是如何快速判断这个值已存在,而抛出ora-00001错误呢?
从性能上来讲,Oracle不太可能将这些数据存放在shared_pool或者其他内存区域中,假如放在内存区域中,必须先解决两个问题:
1、如果有上千个唯一约束表格,在内存中遍历上千表格的数据是不现实的,那性能问题怎么解决?
2、数据库刚启动时,Oracle绝大部分内存区域是空的,但实践证明,即使在数据启动不久,当业务有违反唯一性约束时,Oracle抛出ora-00001错误,依然迅速。
基于以上两点,我们可以反向推出Oracle肯定有另外的机制查找新更新或者插入的数据是否违反唯一性约束。
带着这些问题,进行如下实验:
1、首先创建测试表格
引用
SQL> create table t11 (id number,name varchar2(100));

Table created.


SQL> insert into t11  select rownum id,dbms_random.string('a',30) name from dual connect by level<=200000;

200000 rows created.

SQL> commit;

Commit complete.

增加唯一索引
引用
SQL> create unique index t11_idx on t11(id);

Index created

测试表格和索引的对象头如下:
引用
SQL> select HEADER_FILE,HEADER_BLOCK from dba_segments where SEGMENT_NAME='T11' and owner='ZHOUL';

HEADER_FILE HEADER_BLOCK
----------- ------------
         15        41867

SQL> select HEADER_FILE,HEADER_BLOCK from dba_segments where SEGMENT_NAME='T11_IDX' and owner='ZHOUL';

HEADER_FILE HEADER_BLOCK
----------- ------------
         15        51083

为观察结果,将buffer_cache清空
引用
SQL> alter system flush buffer_cache;

System altered.


采用10046进行跟踪

引用
SQL> ALTER SESSION SET EVENTS '10046 trace name context forever, level 12';

Session altered.

SQL> insert into t11 values(10,'test1');
insert into t11 values(10,'test1')
*
ERROR at line 1:
ORA-00001: unique constraint (ZHOUL.T11_IDX) violated


SQL> ALTER SESSION SET EVENTS '10046 trace name context off';

Session altered.




解析跟踪文件可以看到数据库执行的情况
引用
PARSING IN CURSOR #2 len=34 dep=0 uid=60 oct=2 lid=60 tim=1277628749310436 hv=3967311368 ad='277a7894'
insert into t11 values(10,'test1')
END OF STMT
PARSE #2:c=0,e=472,p=0,cr=0,cu=0,mis=1,r=0,dep=0,og=1,tim=1277628749310431
BINDS #2:
WAIT #2: nam='db file sequential read' ela= 20 file#=15 block#=41867 blocks=1 obj#=1213118 tim=1277628749310583
WAIT #2: nam='db file sequential read' ela= 9 file#=15 block#=41866 blocks=1 obj#=1213118 tim=1277628749310624
WAIT #2: nam='db file sequential read' ela= 8 file#=15 block#=43402 blocks=1 obj#=1213118 tim=1277628749310656
WAIT #2: nam='db file sequential read' ela= 8 file#=15 block#=43506 blocks=1 obj#=1213118 tim=1277628749310686
WAIT #2: nam='db file sequential read' ela= 10 file#=15 block#=51084 blocks=1 obj#=1213119 tim=1277628749310771
WAIT #2: nam='db file sequential read' ela= 9 file#=15 block#=51085 blocks=1 obj#=1213119 tim=1277628749310804


41867块为T11表格段头,从段头中获取二级位图地址:0x03c0a38a
引用
Start dump data blocks tsn: 8 file#: 15 minblk 41867 maxblk 41867
buffer tsn: 8 rdba: 0x03c0a38b (15/41867)
scn: 0x0a00.10b5061c seq: 0x01 flg: 0x04 tail: 0x061c2301
frmt: 0x02 chkval: 0xd4ae type: 0x23=PAGETABLE SEGMENT HEADER
Hex dump of block: st=0, typ_found=1
。。。
  Segment Type: 1 nl2: 1      blksz: 8192   fbsz: 0     
  L2 Array start offset:  0x00001434
  First Level 3 BMB:  0x00000000
  L2 Hint for inserts:  0x03c0a38a
  Last Level 1 BMB:  0x03c0c38c
  Last Level II BMB:  0x03c0a38a
  Last Level III BMB:  0x00000000
     Map Header:: next  0x00000000  #extents: 80   obj#: 1213118 flag: 0x10000000
。。。

41866块为T11表格的二级位图,从二级位图获取一级位图的地址:0x03c0a98a
引用
Start dump data blocks tsn: 8 file#: 15 minblk 41866 maxblk 41866
buffer tsn: 8 rdba: 0x03c0a38a (15/41866)
scn: 0x0a00.10b5056c seq: 0x02 flg: 0x04 tail: 0x056c2102
frmt: 0x02 chkval: 0xdf04 type: 0x21=SECOND LEVEL BITMAP BLOCK
Hex dump of block: st=0, typ_found=1
。。。
Dump of Second Level Bitmap Block
   number: 137     nfree: 120     ffree: 0      pdba:     0x03c0a38b
   Inc #: 0 Objd: 1213118
  opcode:0
xid:
  L1 Ranges :
  --------------------------------------------------------
   0x03c0a389  Free: 5 Inst: 1
   0x03c0a399  Free: 5 Inst: 1
   0x03c0a3a9  Free: 5 Inst: 1
   0x03c0a3b9  Free: 5 Inst: 1
   。。。
   0x03c0a98a  Free: 5 Inst: 1
   0x03c0aa09  Free: 5 Inst: 1
   0x03c0aa0a  Free: 5 Inst: 1
   。。。

  

43402块为一级位图,反映了T11数据块的分布情况,可以看到该三级位图块长度为64,表示管理着64个块
引用
Start dump data blocks tsn: 8 file#: 15 minblk 43402 maxblk 43402
buffer tsn: 8 rdba: 0x03c0a98a (15/43402)
scn: 0x0a00.10b50571 seq: 0x14 flg: 0x04 tail: 0x05712014
frmt: 0x02 chkval: 0x8e2e type: 0x20=FIRST LEVEL BITMAP BLOCK
Hex dump of block: st=0, typ_found=1
。。。
Dump of First Level Bitmap Block
--------------------------------
   nbits : 4 nranges: 1         parent dba:  0x03c0a38a   poffset: 31   
   unformatted: 0       total: 64        first useful block: 0     
   owning instance : 1
   instance ownership changed at 06/17/2011 14:20:49
   Last successful Search 06/17/2011 14:20:49
   Freeness Status:  nf1 1      nf2 1      nf3 0      nf4 5     

   Extent Map Block Offset: 4294967295
   First free datablock : 6     
   Bitmap block lock opcode 0
   Locker xid:     :  0x0000.000.00000000
   Inc #: 0 Objd: 1213118
  --------------------------------------------------------
  DBA Ranges :
  --------------------------------------------------------
   0x03c0a9c9  Length: 64     Offset: 0     
 
   0:FULL   1:FULL   2:FULL   3:FULL
   4:FULL   5:FULL   6:0-25% free   7:FULL
   8:FULL   9:FULL   10:FULL   11:FULL
   12:FULL   13:FULL   14:FULL   15:FULL
   16:FULL   17:FULL   18:FULL   19:FULL
   20:FULL   21:FULL   22:FULL   23:FULL
   24:FULL   25:FULL   26:FULL   27:FULL
   28:FULL   29:FULL   30:FULL   31:FULL
   32:FULL   33:FULL   34:FULL   35:FULL
   36:FULL   37:FULL   38:FULL   39:FULL
   40:FULL   41:25-50% free   42:FULL   43:FULL
   44:FULL   45:75-100% free   46:FULL   47:FULL
   48:FULL   49:75-100% free   50:FULL   51:FULL
   52:FULL   53:75-100% free   54:FULL   55:FULL
   56:FULL   57:75-100% free   58:FULL   59:FULL
   60:FULL   61:75-100% free   62:FULL   63:FULL
  --------------------------------------------------------
End dump data blocks tsn: 8 file#: 15 minblk 43402 maxblk 43402

  
43506块为T11表格的数据块,在数据文件的位置远离了上面的一级位图块43506-43402=104
引用
SQL> col owner for a10
SQL> col segment_name for a10
SQL> select owner,segment_name from dba_extents where file_id=15 and 43506 between block_id and BLOCK_ID+BLOCKS-1;

OWNER      SEGMENT_NA
---------- ----------
ZHOUL      T11

以下是dump文件显示,那Oracle从哪里获取该数据块的dba信息呢?这是个问题。
引用
Start dump data blocks tsn: 8 file#: 15 minblk 43506 maxblk 43506
buffer tsn: 8 rdba: 0x03c0a9f2 (15/43506)
scn: 0x0a00.10b5079a seq: 0x02 flg: 0x04 tail: 0x079a0602
frmt: 0x02 chkval: 0xe0de type: 0x06=trans data
Hex dump of block: st=0, typ_found=1
。。。
Block header dump:  0x03c0a9f2
Object id on Block? Y
seg/obj: 0x1282be  csc: 0xa00.10b50614  itc: 2  flg: E  typ: 1 - DATA
     brn: 0  bdba: 0x3c0a98a ver: 0x01 opc: 0
     inc: 0  exflg: 0

Itl           Xid                  Uba         Flag  Lck        Scn/Fsc
0x01   0x0013.000.00003644  0x028004b5.0922.0f  C---    0  scn 0x0a00.10b50573
0x02   0x0000.000.00000000  0x00000000.0000.00  ----    0  fsc 0x0000.00000000

data_block_dump,data header at 0xe1fe864
。。。


51804块为索引的根节点
引用
Start dump data blocks tsn: 8 file#: 15 minblk 51084 maxblk 51084
buffer tsn: 8 rdba: 0x03c0c78c (15/51084)
scn: 0x0a00.10b50656 seq: 0x01 flg: 0x04 tail: 0x06560601
frmt: 0x02 chkval: 0x8b02 type: 0x06=trans data
Hex dump of block: st=0, typ_found=1
Block header dump:  0x03c0c78c
Object id on Block? Y
seg/obj: 0x1282bf  csc: 0xa00.10b50624  itc: 1  flg: E  typ: 2 - INDEX
     brn: 0  bdba: 0x3c0c789 ver: 0x01 opc: 0
     inc: 0  exflg: 0

Itl           Xid                  Uba         Flag  Lck        Scn/Fsc
0x01   0xffff.000.00000000  0x00000000.0000.00  C---    0  scn 0x0a00.10b50624

Branch block dump
=================
header address 229374028=0xdabf84c
kdxcolev 1
KDXCOLEV Flags = - - -
kdxcolok 0
kdxcoopc 0x80: opcode=0: iot flags=--- is converted=Y
kdxconco 1
kdxcosdc 0
kdxconro 416
kdxcofbo 860=0x35c
kdxcofeo 4331=0x10eb
kdxcoavs 3471
kdxbrlmc 62965645=0x3c0c78d
kdxbrsno 0
kdxbrbksz 8056
kdxbr2urrc 10


51085块为索引的叶节点,在上面我们找到了id=10的记录和rowid,和dump信息匹配
引用
Start dump data blocks tsn: 8 file#: 15 minblk 51085 maxblk 51085
buffer tsn: 8 rdba: 0x03c0c78d (15/51085)
scn: 0x0a00.10b50627 seq: 0x01 flg: 0x04 tail: 0x06270601
frmt: 0x02 chkval: 0x8502 type: 0x06=trans data
Hex dump of block: st=0, typ_found=1
。。。
col 0; len 2; (2):  c1 0b
row#10[7911] flag: ------, lock: 0, len=11, data:(6):  03 c0 a5 8b 00 0a
。。。

SQL> select dump(10,16) from dual;

DUMP(10,16)
-----------------
Typ=2 Len=2: c1,b


SQL> select rowid,dump(rowid,16) from t11 where id=10;

ROWID                          DUMP(ROWID,16)
------------------------------ --------------------------------------------------
AAEoK+AAPAAAKWLAAJ             Typ=69 Len=10: 0,12,82,be,3,c0,a5,8b,0,9



经过以上实验,我们推出Oracle在建立了唯一性约束的表格中,如果业务程序对改表格的唯一键进行update或者insert时,首先会根据update或者insert后的值进行索引检查,如果发现相同值,则抛出ora-00001错误。

另外需要注意的是在开启开启执行计划的SQLPLUS环境中,由于违反约束,执行计划不会显示
引用
SQL> set autot traceonly exp
SQL> insert into t11 values(10,'test1');
insert into t11 values(10,'test1')
*
ERROR at line 1:
ORA-00001: unique constraint (ZHOUL.T11_IDX) violated
分享到:
评论

相关推荐

    oracle特有的错误:ORA-01036:非法的变量名/编号

    在Oracle数据库系统中,"ORA-01036:非法的变量名/编号"是一个常见的错误,通常出现在PL/SQL代码或者SQL查询语句中,当你尝试使用一个不正确或者未定义的变量时,Oracle数据库会抛出这个错误。这个错误可能是由于...

    ora-227101错误解决办法

    当尝试访问数据库时,如果没有正确的SGA存在,Oracle将抛出此错误。这种情况可能由多种原因引起,包括但不限于操作系统权限问题、数据库监听器配置错误、数据库实例崩溃或未正确关闭等。 ### 二、ORA-01034和ORA-...

    ORA-00257错误.doc

    Oracle 的 Archivelog 机制是为了确保数据库的可恢复性,在数据库中, archivelog 文件是记录数据库的所有变化的日志文件,当 archivelog 文件达到一定的大小时, Oracle 就会抛出 ORA-00257 错误,这时我们需要...

    oracle ora-各种常见java.sql.SQLException归纳

    Oracle 是一个强大的关系数据库管理系统,然而,在使用 Oracle 时,总是会遇到各种错误信息,这些错误信息是Oracle抛出的异常信息,用于提示开发者出现了什么问题。了解这些错误信息是非常重要的,因为它们可以帮助...

    如何解决Oracle 常见错误 ORA-04031(PDF)

    如果仍无法满足请求,则会抛出ORA-04031错误。 ##### 诊断步骤: 1. **检查共享池保留空间中的碎片**:运行以下查询以确定ORA-04031错误是否由共享池保留空间中的碎片引起: ```sql SELECT free_space, avg_free...

    《转载》ora-00020超出最大进程数

    如果超过了这个值,新的连接尝试将失败并抛出ORA-00020错误。 2. **资源竞争**:当大量并发用户访问数据库时,可能会耗尽可用的进程资源,尤其是在内存有限或系统负载较高的情况下。 3. **僵尸进程**:如果用户进程...

    oracle数据库-错误编码大全

    当尝试插入或更新数据导致违反已定义的唯一约束条件时,数据库将抛出ORA-00001错误。解决此问题通常需要重新检查插入或更新的数据,确保不违反唯一性要求。 其次,ORA-00017提示请求会话以设置跟踪事件。这个错误...

    ora-01720 授权选项对于'xxxx'不存在的解决方法

    当用户B试图将视图`V_B`的SELECT权限授予用户C时,系统抛出了`ORA-01720`错误。这主要是因为在第一步授权过程中,用户A只授予了用户B对`V_A`的SELECT权限,而没有提供进一步的GRANT OPTION(授权选项)。 #### 解决...

    ORACLE错误码及解决方法

    若尝试创建此类序列而未指定相应参数,系统将抛出这些错误。解决方案是在创建序列的SQL语句中加入MINVALUE或MAXVALUE参数,根据需要设置循环的起始或结束值。 错误码ORA-00903表示尝试在不存在的表中创建索引,这...

    ora-0094问题解决

    例如,如果vshortname字段被定义为唯一,而插入的数据中vshortname值已经存在,那么就会抛出ORA-0094错误。或者,如果pk_areacl字段是一个外键,指向另一个表的主键,且该值在引用表中不存在,也会引发此错误。 ...

    ORA-00119 和 ORA-00132 解决记录(win 8 升级 win 10 后,oracle 11g 无法启动及客户端连接)

    具体来说,当Oracle尝试启动时,它会在指定的端口上查找监听器来处理客户端连接请求,但如果没有找到,则会抛出此错误。 2. **ORA-00132**:这个错误表示Oracle实例无法读取初始化参数文件(init.ora),这可能是...

    解决navicat报错ORA-12737(OCI报错)

    这通常发生在尝试连接到Oracle数据库服务器时,如果客户端的OCI库无法正确地与服务器进行通信,就会抛出这个错误。 **可能的原因:** 1. **客户端和服务器的Oracle版本不兼容**:Navicat作为客户端,其使用的Oracle...

    oracle报错的详细列表

    #### ORA-00001: 违反唯一约束条件 当尝试向具有唯一约束的列插入重复值时触发。例如,在唯一索引或主键约束上。 #### ORA-00017: 请求会话以设置跟踪事件 该错误通常出现在调试过程中,当尝试跟踪某个会话或进程时...

    ORACLE ORA

    - **应用程序日志**:如果应用程序连接到Oracle数据库并抛出异常,则应用程序可能会捕获这些ORA错误并将它们记录到自己的日志文件中。 #### 常见ORA错误详解 下面列举了一些常见的ORA错误代码及其含义: - **ORA-...

    ORA-00979 不是group by 表达式

    - 当你使用聚合函数(如COUNT、SUM、AVG等)时,如果没有将所有非聚合列包含在GROUP BY子句中,Oracle会抛出这个错误。因为Oracle需要知道如何对这些非聚合列进行分组。 - 在不使用GROUP BY的情况下,SQL默认执行 ...

    oracle异常总结

    - `DUPLICATE_VALUE_ON_INDEX`(ora-00001):尝试插入已存在于唯一索引中的值时抛出。 处理预定义异常通常通过在PL/SQL块中声明`EXCEPTION`部分来实现,捕获特定异常并执行相应的错误处理逻辑。例如: ```sql BEGIN...

    ORACLE+错误一览表 第一部分

    例如,面对ORA-00001错误,可以检查插入或更新的数据是否与已存在的数据冲突;对于ORA-01422,需要确保查询只返回一行数据,或者使用BULK COLLECT INTO来处理多行结果。 Oracle错误一览表还可能包含错误的解决方法...

    linux安装oracle错误解决方法

    在 Linux 环境中安装 Oracle 时,可能会遇到各种错误,这篇文章将对 ORA-01078、LRM-00109、ORA-01102、ORA-12541、ORA-12528、ORA-01033 和 ORA-28547 等错误进行详细的解决方法。 在安装 Oracle 10 后,配置网络...

    Oracle出现ora-12154无法解析指定连接标识符的解决方法

    当TNS无法找到或解析tnsnames.ora文件中定义的服务名时,就会抛出ORA-12154错误。 解决该问题的步骤如下: 1. **安装和配置Oracle客户端**:确保已安装合适的Oracle客户端,并在“开始”菜单中找到“Oracle - ...

Global site tag (gtag.js) - Google Analytics