[20120712]10g下Oracle Index rebuild online.txt

[20120712]10g下Oracle Index rebuild online.txt

oracle rebuild online时要建立一张IOT表,为了保证事务依旧能操作,需要记录索引rebuild期间的DML操作。
但是10g与11g下rebuild的机制有一些不同。

index online rebuild 前先建立一张IOT表跟踪后续DML操作,然后merge全部的改变到索引中。
 
下面通过例子来说明:

BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bi
PL/SQL Release 10.2.0.4.0 - Production
CORE    10.2.0.4.0      Production
TNS for Linux: Version 10.2.0.4.0 - Production
NLSRTL Version 10.2.0.4.0 - Production

create table t (id number,name varchar2(10));
create index i_t_id on t(id);
insert into t  select rownum id ,'test' name from dual connect by level 
commit ;

跟踪rebuild online的过程:

alter session set events '10046 trace name context forever, level 12';
alter index i_t_id rebuild online ;
alter session set events '10046 trace name context off';

--看跟踪文件如下:

create table "SCOTT"."SYS_JOURNAL_254930" (C0 NUMBER,  opcode char(1), partno number,  rid rowid, primary key( C0 , rid )) organization index TABLESPACE "USERS"
CREATE UNIQUE INDEX "SCOTT"."SYS_IOT_TOP_254932" on "SCOTT"."SYS_JOURNAL_254930"("C0","RID") INDEX ONLY TOPLEVEL TABLESPACE "USERS" NOPARALLEL;
drop table "SCOTT"."SYS_JOURNAL_2543930" purge

可以看出在发出命令alter index i_t_id rebuild online;后,要建立一张IOT表:

C0对应索引字段ID。
OPCODE字段表示操作类型。"I" =》 Insert ,"D" =》 Delete ,"U"=>UPDATE.
PARTNO字段表示该表T的partition number。
rid字段类型rowid,一定与表的rowid相对应。

SQL> select object_name,object_id,data_object_id from dba_objects where wner=user and object_name='I_T_ID';
OBJECT_NAME                     OBJECT_ID DATA_OBJECT_ID
------------------------------ ---------- --------------
I_T_ID                             254930         254931

--建立的IOT表SYS_JOURNAL_254930的数字与I_T_ID的OBJECT_ID对应。

1.开始测试:
会话1插入1行:

SQL> select * from v$mystat where rownum
   SID STATISTIC#      VALUE
------ ---------- ----------
   390          0          1
SQL> insert into t (101,'a');
会话2索引rebuild online:
SQL> select * from v$mystat where rownum
       SID STATISTIC#      VALUE
---------- ---------- ----------
       375          0          1
SQL> alter index i_t_id rebuild online ;

可以发现系统挂起!

执行如下:

SQL> host cat viewlock.sql
SELECT lk.SID, se.username, se.osuser, se.machine,
       DECODE (lk.TYPE, 'TX', 'Transaction', 'TM', 'DML', 'UL', 'PL/SQL User Lock', lk.TYPE) lock_type,
       DECODE (lk.lmode,
               0, 'None',
               1, 'Null',
               2, 'Row-S (SS)',
               3, 'Row-X (SX)',
               4, 'Share',
               5, 'S/Row-X (SSX)',
               6, 'Exclusive',
               TO_CHAR (lk.lmode)
              ) mode_held,
       DECODE (lk.request,
               0, 'None',
               1, 'Null',
               2, 'Row-S (SS)',
               3, 'Row-X (SX)',
               4, 'Share',
               5, 'S/Row-X (SSX)',
               6, 'Exclusive',
               TO_CHAR (lk.request)
              ) mode_requested,
       TO_CHAR (lk.id1) lock_id1, TO_CHAR (lk.id2) lock_id2, ob.owner, ob.object_type, ob.object_name,
       DECODE (lk.BLOCK, 0, 'No', 1, 'Yes', 2, 'Global') BLOCK, se.lockwait
  FROM v$lock lk, dba_objects ob, v$session se
 WHERE lk.TYPE IN ('TX','TM','UL') AND lk.SID = se.SID AND lk.id1 = ob.object_id(+);
SQL> @viewlock ;
   SID USERNAME   OSUSER     MACHINE    LOCK_TYPE    MODE_HELD  MODE_REQUE LOCK_ID1   LOCK_ID2   OWNER  OBJECT_TYP OBJECT_NAME          BLOCK LOCKWAIT
------ ---------- ---------- ---------- ------------ ---------- ---------- ---------- ---------- ------ ---------- -------------------- ----- --------------------
   375 SCOTT       oracle     qyytest    DML          Share      None       254935     0          SCOTT   TABLE      SYS_JOURNAL_254930   No    0000000221383B78
   390 SCOTT       oracle     qyytest    DML          Row-X (SX) None       254929     0          SCOTT   TABLE      T                    Yes
   375 SCOTT       oracle     qyytest    DML          Row-S (SS) Share      254929     0          SCOTT   TABLE      T                    No    0000000221383B78
   390 SCOTT       oracle     qyytest    Transaction  Exclusive  None       327776     335372                                             No

--可以发现会话1(SID=390)的事务没有提交,rebuild online无法获得exclusive lock锁。
--注意SID=390,LOCK_TYPE=DML(type='TM'),block=YES.这样其他用户执行DML首先要获得TM锁,这样其他用户执行DML会出现阻塞情况。

打开会话3:

SQL> select * from v$mystat where rownum
       SID STATISTIC#      VALUE
---------- ---------- ----------
       398          0          1
SQL> select * from  SYS_JOURNAL_254930;
no rows selected
SQL> insert into t  values (102,'b');

会话3挂起!

在回话1执行:

SQL> @viewlock ;
   SID USERNAME   OSUSER     MACHINE    LOCK_TYPE    MODE_HELD  MODE_REQUE LOCK_ID1   LOCK_ID2   OWNER  OBJECT_TYP OBJECT_NAME          BLOCK LOCKWAIT
------ ---------- ---------- ---------- ------------ ---------- ---------- ---------- ---------- ------ ---------- -------------------- ----- --------------------
   375 SCOTT       oracle     qyytest    DML          Share      None       254935     0          SCOTT   TABLE      SYS_JOURNAL_254930   No    0000000221383B78
   398 SCOTT       oracle     qyytest    DML          None       Row-X (SX) 254929     0          SCOTT   TABLE      T                    No    0000000221383D78
   390 SCOTT       oracle     qyytest    DML          Row-X (SX) None       254929     0          SCOTT   TABLE      T                    Yes
   375 SCOTT       oracle     qyytest    DML          Row-S (SS) Share      254929     0          SCOTT   TABLE      T                    No    0000000221383B78
   390 SCOTT       oracle     qyytest    Transaction  Exclusive  None       327776     335372                                             No

2.继续测试,回到会话1:

SQL> select * from  SYS_JOURNAL_254930;
no rows selected
SQL>rollback;
Rollback complete.
SQL> @viewlock ;
   SID USERNAME   OSUSER     MACHINE    LOCK_TYPE    MODE_HELD  MODE_REQUE LOCK_ID1   LOCK_ID2   OWNER  OBJECT_TYP OBJECT_NAME          BLOCK LOCKWAIT
------ ---------- ---------- ---------- ------------ ---------- ---------- ---------- ---------- ------ ---------- -------------------- ----- --------------------
   375 SCOTT       oracle     qyytest    DML          Share      None       254935     0          SCOTT   TABLE      SYS_JOURNAL_254930   No    0000000221383B78
   398 SCOTT       oracle     qyytest    DML          Row-X (SX) None       254929     0          SCOTT   TABLE      T                    Yes
   375 SCOTT       oracle     qyytest    DML          Row-S (SS) Share      254929     0          SCOTT   TABLE      T                    No    0000000221383B78
   375 SCOTT       oracle     qyytest    Transaction  Exclusive  None       589904     365176                                             No    0000000221383B78
   398 SCOTT       oracle     qyytest    Transaction  Exclusive  None       655391     397962                                             No

--回到会话3(SID=398),可以发现阻塞的会话执行完成。
--但是注意回话3(SID=398),LOCK_TYPE=DML(type='TM'),block=YES.(原来是回话1).这样其他用户再执行DML也会出现阻塞情况。
--在回话1执行:
SQL> insert into t values (101,'a');
--再次挂起!

3.回到会话3,执行提交语句:

SQL> @viewlock.sql
   SID USERNAME   OSUSER     MACHINE    LOCK_TYPE    MODE_HELD  MODE_REQUE LOCK_ID1   LOCK_ID2   OWNER  OBJECT_TYP OBJECT_NAME          BLOCK LOCKWAIT
------ ---------- ---------- ---------- ------------ ---------- ---------- ---------- ---------- ------ ---------- -------------------- ----- --------------------
   375 SCOTT       oracle     qyytest    DML          Share      None       254938     0          SCOTT   TABLE      SYS_JOURNAL_254930   No    0000000221383B78
   398 SCOTT       oracle     qyytest    DML          Row-X (SX) None       254929     0          SCOTT   TABLE      T                    Yes
   390 SCOTT       oracle     qyytest    DML          None       Row-X (SX) 254929     0          SCOTT   TABLE      T                    No    0000000221383A78
   375 SCOTT       oracle     qyytest    DML          Row-S (SS) Share      254929     0          SCOTT   TABLE      T                    No    0000000221383B78
   375 SCOTT       oracle     qyytest    Transaction  Exclusive  None       589877     365190                                             No    0000000221383B78
   398 SCOTT       oracle     qyytest    Transaction  Exclusive  None       655443     397972                                             No
6 rows selected.
SQL>commit;

检查回话1,发现插入执行完成!why?
因为回话1(sid=390),LOCK_TYPE=DML,mode_request的是Row-X(SX),lock_id1=254929(对应表T),并不会阻塞。

检查会话2,可以发现rebuild online完成。

SQL> @viewlock.sql
   SID USERNAME   OSUSER     MACHINE    LOCK_TYPE    MODE_HELD  MODE_REQUE LOCK_ID1   LOCK_ID2   OWNER  OBJECT_TYP OBJECT_NAME          BLOCK LOCKWAIT
------ ---------- ---------- ---------- ------------ ---------- ---------- ---------- ---------- ------ ---------- -------------------- ----- --------------------
   390 SCOTT       oracle     qyytest    DML          Row-X (SX) None       254929     0          SCOTT   TABLE      T                   No
   390 SCOTT       oracle     qyytest    Transaction  Exclusive  None       196662     332227                                            No

--可以发现回话1(sid=390),mode_held变成了 Row-X (SX)。

总结:
如果在10g下执行reuild online,之前的事务没有commit或者rollback,rebuild online会挂起,同时其他用户对该表DML操作,都会出现阻塞情况。

 

时间: 2024-09-20 15:02:05

[20120712]10g下Oracle Index rebuild online.txt的相关文章

[20120801]11g下Oracle Index rebuild online之3.txt

[20120801]11g下Oracle Index rebuild online之3.txt 接着昨天的测试继续: 昨天在索引rebuild online时,按ctrl+c中断时,要等很长时间,不想一些dml语句如果挂起,按ctrl+c很快退出.今天继续测试看看.. SQL> select * from v$version ; BANNER -----------------------------------------------------------------------------

Windows下ORACLE 10g完全卸载的方法分析_oracle

Windows下ORACLE完全卸载:使用OUI可以卸载数据库,但卸载后注册表和文件系统内仍会有部分残留.这些残留不仅占用磁盘空间,而且影响ORACLE的重新安装及系统性能. 在WINDOWS下卸载ORACLE 10g的步骤:1 删除聚集同步服务CSS(Cluster Synchronization Services).如果数据库配置了自动存储管理ASM,应该先删除CSS服务,因为ORACLE不会自动删除这个服务.在DOS命令下使用localconfig delete命令可删除该服务. C:\D

[20150810]10g下dbms_xplan.display_cursor

[20150810]10g下dbms_xplan.display_cursor.txt --执行过的sql语句要查看执行计划要使用dbms_xplan包,我一般写成脚本反复使用,这样快捷方便一些. --我的定义如下: $  cat dpc.sql set verify off select * from table(dbms_xplan.display_cursor(NVL('&1',NULL),NULL,'ALL ALLSTATS LAST PEEKED_BINDS cost partitio

[20160229]探究oracle的启动过程.txt

[20160229]探究oracle的启动过程.txt --昨天自己研究了sys.bootstrap$,链接http://blog.itpub.net/267265/viewspace-2016219/ --今天换一种方式探究,当加载某个对象时,会调用内部函数kqlobjlod,通过gdb设置断点,可以实现了解启动的过程. --还是通过测试来讲解: 1.建立测试环境: SYS@book> @ &r/ver1 PORT_STRING                    VERSION    

[20150113]关于oracle的存储结构.txt

[20150113]关于oracle的存储结构.txt --这阵子在看vage写的>,里面第一章提到: --P2 --每个文件的前128个块,都是文件头,被Oracle留用了.在oracle 10g中是0-8号块被oracle留用.而从oracle 11GR2开始,一下就留用 -- 128个块. 而实际的情况呢?自己做一个测试: 1.测试环境: --我的测试环境:数据块大小8K. SCOTT@test> @ver1 PORT_STRING                    VERSION 

[20160606]windows下使用bbed的疑问.txt

[20160606]windows下使用bbed的疑问.txt --链接:http://blog.itpub.net/267265/viewspace-2109019/        http://blog.itpub.net/267265/viewspace-2109558/ --我曾经提到要访问的块要+1,比如: SCOTT@book> @ &r/ver1 PORT_STRING                    VERSION        BANNER -------------

[20130909]12C执行计划的TABLE ACCESS BY INDEX ROWID BATCHED.txt

[20130909]12C执行计划的TABLE ACCESS BY INDEX ROWID BATCHED.txt 在写[20130809]12c Clustering Factor.txt,链接 提到执行计划里面存在TABLE ACCESS BY INDEX ROWID BATCHED,这里的BATCHED表示什么? 自己不是很清楚. 既然多了一个batched,一定与原来的不同,具体含义是什么呢?做一些简单的探究: 1.建立测试环境: SCOTT@test01p> @ver BANNER  

[20131017]11G下truncate的新特性.txt

[20131017]11G下truncate的新特性.txt http://www.askmaclean.com/archives/know-high-water-mark-truncate.html 11.2.0.2中出现truncate的新特性,截断表目前有了新选项:即drop all storage. 测试看看:SCOTT@test> @verBANNER--------------------------------------------------------------------

solaris X86-64下ORACLE打11.2.0.3.8补丁遇到的问题

solaris X86-64下ORACLE打11.2.0.3.8补丁: 正确步骤: 1.BUG6880880 ,OPATCH的补丁 2.BUG16902043,11.2.0.3.8补丁 感慨就是要实践啊看着容易的事也一波三折--像OPATCH的版本问题在安装11.2.0.3.8补丁前有提示的,要细心唉. MOS还是很好用的哈哈. 安装过程: 1.环境检查 -bash-3.2$ ls 16902043                           alert_byssolaris.log D