1、一般都说,rebuild index online 不阻塞 DML 操作,这是相对于 rebuild index 来说的,加上了 online,只是在 rebuild 的期间不阻塞 DML,但是在开始和结束阶段还是可能阻塞其他进程的 DML 的,要弄清楚到底是 阻塞还是不阻塞,何处阻塞,为什么阻塞,还是要从锁的角度来分析。本文实验环境为Oracle 10.2.0.4。Oracle 中的锁,一共有 6 两种模式:0:none 1:null 空 2:Row-S 行共享(RS):共享表锁,sub share 3:Row-X 行独占(RX):用于行的修改,sub exclusive 4:Share 共
2、享锁(S):阻止其他 DML 操作,share 5:S/Row-X 共享行独占(SRX):阻止其他事务操作,share/sub exclusive 6:exclusive 独占(X):独立访问使用,exclusive 我 们知道,DML 操作一般要加两个锁,一个是对表加模式为 3 的 TM 锁,一个是对数据行的模式为 6 的 TX 锁。只要操作的不是同一行数据,是互不阻塞的。但是 rebuild index online 在开始和结束的时候是需要对表加一个模式为 4的 TM 锁的,这个可以很容易通过实验观察到,实验中的测试表 t 是通过create table t as select * fr
3、om all_objects 生成,并且多次执行 insert into t select * from t 产生较多的数据,以便延迟 rebuild 的时间来观察系统中锁的情况:session 1:SQL delete from t where object_id=28;1 row deleted.session 2:SQL alter index ix_t rebuild online;Session 2 被阻塞,会话挂起,这时查询 v$lock,可以得到如下结果:SQL select sid,type,id1,id2,lmode,request from v$lock where typ
4、e in(DL,TM,TX);SID TY ID1 ID2 LMODE REQUEST- - - - - -1643 DL 10599 0 3 01643 DL 10599 0 3 01622 TM 10599 0 3 01643 TM 10599 0 2 41643 TM 10607 0 4 01622 TX 655398 1361 6 0从 上面的结果可以知道,1622 是 session 1,1643 是 session 2,session 2一共出现了 4 个锁,两个 DL 锁,一个针对表 t 的 TM 锁,一个是 online rebuild index 时需要的一个中间表的 TM
5、锁,中间表用于记录 rebuild 期间的增量数据,原理类似于物化视图日志,其 object_id 为 10607,这是 一个索引组织表(IOT),从这里我们也可以发现 IOT 的优点和适合的场合,这张中间表只有插入,不会有删除和修改操作,而且只有主键条件查询,正是 IOT 最合适的场景:SQL select object_name,object_type from all_objects where object_id=10607;OBJECT_NAME OBJECT_TYPE- -SYS_JOURNAL_10602 TABLESQL select table_name,iot_type f
6、rom all_tables where table_name=SYS_JOURNAL_10602;TABLE_NAME IOT_TYPE- -SYS_JOURNAL_10602 IOTSession 2 在请求一个模式为 4 的 TM 锁,模式 4 会阻塞这个表上的所有 DML 操作,所以这是再往这个表上执行 DML 也会挂起session 3:SQL delete from t where object_id=46;SQL select sid,type,id1,id2,lmode,request from v$lock where type in(DL,TM,TX);SID TY ID1
7、 ID2 LMODE REQUEST- - - - - -1643 DL 10599 0 3 01643 DL 10599 0 3 01622 TM 10599 0 3 01643 TM 10599 0 2 41643 TM 10607 0 4 01627 TM 10599 0 0 31622 TX 655398 1361 6 01627 就是 session 3,请求模式为 3 的 TM 锁无法获得,会话被阻塞。这是因为锁请求是需要排队的,即使 session 3 和 session 1 是可以并发的,但由于session 2 先请求锁并进入等待队列,或来的 session 3 也只好进入队
8、列等待。所以如果在执行 rebuild index online 前长事务,并且并发量比较大,则一旦执行 alter index rebuild online,可能因为长事务阻塞,可能导致系统瞬间出现大量的锁,对于压力比较大的系统,这是一个不小的风险。这是需要迅速找出导致阻塞的会话 kill 掉,rebuild index online 一旦执行,不可轻易中断,否则可能遇到 ORA-08104。在 session 1 执行 rollback,可以发现很短时间内 session 3 也正常执行完毕,说明 session 2 只有模式 4 的 TM 锁的时间很短,然后在 rebuild onlin
9、e 的进行过程中,对表加的是模式为 2 的 TM 锁,所以这段时间不会阻塞 DML 操作:SQL select sid,type,id1,id2,lmode,request from v$lock where type in(DL,TM,TX);SID TY ID1 ID2 LMODE REQUEST- - - - - -1643 DL 10599 0 3 01643 DL 10599 0 3 01643 TM 10599 0 2 01643 TM 10607 0 4 01627 TM 10599 0 3 01627 TX 655392 1361 6 0保持 session 3 的事务不提交,
10、等待一段时间后,session 2 始终无法完成操作,再观察系统中锁的情况,可以发现又发生了变化:SQL select sid,type,id1,id2,lmode,request from v$lock where type in(DL,TM,TX);SID TY ID1 ID2 LMODE REQUEST- - - - - -1643 DL 10599 0 3 01643 DL 10599 0 3 01643 TM 10599 0 2 41643 TM 10607 0 4 01627 TM 10599 0 3 01643 TX 589852 258 6 01627 TX 655392 13
11、61 6 0Session 2 又开始在请求模式 4 的 TM 锁,被 session 3 阻塞!这是在 session 1 再执行 DML 操作,同样会被 session 2 阻塞,进入锁等待队列。Session 1:SQLdelete from t where object_id=11;SQL select sid,type,id1,id2,lmode,request from v$lock where type in(DL,TM,TX);SID TY ID1 ID2 LMODE REQUEST- - - - - -1643 DL 10599 0 3 01643 DL 10599 0 3
12、01622 TM 10599 0 0 31643 TM 10599 0 2 41643 TM 10607 0 4 01627 TM 10599 0 3 01643 TX 589852 258 6 01627 TX 655392 1361 6 0在 session 3 执行 rollback 或者 commit 以后,session 2 和 session 3 都很快执行完毕。从 上面的试验可以发现,虽然 rebuild index online 在执行期间只持有模式2 的 TM 锁,不会阻塞 DML 操作,但在操作的开始和结束阶段,是需要短暂的持有模式为 4 的 TM 锁的,这段会阻塞表上的所
13、 有 DML 操作。我们在做 rebuild index online 的时候,一定要在开始和结束阶段观察系统中是否有长事务的存储,对于并发量较大的系统,最严重的后果,可能在这两个关键点导致数据库产生大量 锁等待,系统负载飙升,甚至宕机。rebuild index online 的锁机制浅析收藏此页 打印作者:IT 2008-10-15 内容导航:在 Oracle11g 中执行 rebuild index online 第 1 页: 在 Oracle10g 中执行 rebuild index online 第 2 页: 在 Oracle11g中执行 rebuild index online 文
14、本 Tag: Oracle 到了 Oracle11g,这种情况有所变化,还是通过同样的实验来观察一下Oracle11g 到底做出了怎样的改进,对于 DBA 来说又有怎样的好处。实验环境为 Oracle11.1.0.6。session 1:SQL delete from t where object_id=28;1 row deleted.session 2:SQL alter index ix_t rebuild online;session 2 同样被挂起,查看 v$lock:SQL select sid,type,id1,id2,lmode,request from v$lock wher
15、e type in(DL,TM,TX);SID TY ID1 ID2 LMODE REQUEST- - - - - -137 DL 13596 0 3 0137 DL 13596 0 3 0137 TX 458781 377 0 4170 TM 13596 0 3 0137 TM 13596 0 2 0137 TM 13599 0 4 0170 TX 458781 377 6 0137 TX 524304 402 6 0其 中 170 为 session 1,137 为 session 2。可以看到 session 2 正在请求一个模式为 4 的 TX 锁,注意和 Oracle10.2.0.4
16、 请求的 TM 锁是不一样的,而且在我们以前的概念中,TX 锁的模式都是 6,这里出现了 模式 4 的 TX 锁请求,应该是 Oracle11g 中新引入的。那么模式 4 的 TX 锁和 TM 锁有什么不同呢?我们继续前面的实验步骤:session 3:SQL delete from t where object_id=46;1 row deleted.session 3 的 DML 操作顺利完成,没有被阻塞。而在 10g 当中,session 3 是会被 session 2 请求的 TM 锁所阻塞的,这一点改进是非常有意思的,这样即使rebuid online 操作被 session 1 的
17、长事务阻塞,其他会话的 DML 操作,只要不和 session 1 冲突,都可以继续操作,在 Oracle10g 及以前版本中的执行rebuild index online 而造成锁等待的风险被大大的降低了。接下来在 session 1 执行 rollback,观察 rebuild index online 执行期间的锁的情况,136 是 session 3:SID TY ID1 ID2 LMODE REQUEST- - - - - -137 DL 13596 0 3 0137 DL 13596 0 3 0137 TM 13596 0 2 0137 TM 13599 0 4 0136 TM 1
18、3596 0 3 0136 TX 327684 414 6 0137 TX 524304 402 6 0137 TX 524321 402 6 0等待一段时间,rebuild index online 临近结束,再次观察锁的情况:SID TY ID1 ID2 LMODE REQUEST- - - - - -137 DL 13596 0 3 0137 DL 13596 0 3 0137 TX 327684 414 0 4137 TM 13596 0 2 0137 TM 13599 0 4 0136 TM 13596 0 3 0136 TX 327684 414 6 0137 TX 524304
19、402 6 0可 以看到 session 2 又在请求一个模式为 4 的 TX 锁,同样的,这个锁也不会阻塞其他的 DML。由于 session 3 的事务没有提交,session 2 被阻塞,这时再将 session 3 执行提交或者 rollback,则 session 2 的 rebuild 立即完成。Oracle11g 在很多细节方面确实做了不少的优化,而且像这样的优化,对于提高系统的高可用性的好处是不 言而喻的,在 Oracle11g 中,执行 rebuild index online 的风险将比 10g 以及更老版本中小得多,因为从头至尾都不再阻塞 DML 操作了,终于可以算得上名副其实的 online 操作了。