Oracle新建或重建索引过程中的锁信息

0    426    2

Tags:

👉 本文共约4364个字,系统预计阅读时间或需17分钟。

简介

可以利用10704和10046事件跟踪新建或重建索引过程中的锁信息,命令为:

新建或重建索引的锁信息如下图所示:

不带ONLINE的新建或重建索引的SQL语句获取的是4级TM锁,它会阻塞任何DML操作。

在Oracle 10g中,带ONLINE的新建或重建索引的SQL语句在开始和结束的时候获取的是4级TM锁,而在读取表数据的过程中获取的是2级TM锁,所以,在Oracle 10g中,即使加上ONLINE也会阻塞其它会话的DML操作。

在Oracle 11g中,带ONLINE的新建或重建索引的SQL语句在整个执行过程中获取的是2级TM锁,并不会阻塞其它会话的DML操作,但是在创建或重建索引的过程中,其它的会话产生的事务会阻塞索引的创建或重建操作,所以必须结束其它会话的事务才能让创建或重建索引的操作完成。所以应该避免在业务高峰期创建索引。

在Oracle 11g带ONLINE的新建或重建索引的情况下:

① 过程中会持有OD(ONLINE DDL)、DL(Direct Loader Index Creation)两种类型的锁,在Oracle 10g下只有DL锁没有OD锁。

② 表级锁TM的持有模式为2级RS(Row Share)与3级RX(Row Exclusive)类型的锁互相兼容,因此不会在表级发生阻塞。

③ 阻塞发生在行级锁申请阶段,即请求的4级S(Share)类型的锁与执行DML的会话已经持有的6级X(Exclusive)锁之间存在不兼容的情况;相比非ONLINE方式的表级锁,锁的粒度上更加细化,副作用更小。

④ 新增以“SYSJOURNAL”为前缀的IOT表,记录与索引创建动作同时进行的其它DML操作修改过的记录,等到索引创建完成前将IOT表里的记录合并至索引中并删除IOT表。

实验

创建或重建索引会阻塞DML操作

版本:11.2.0.3

可以发现在会话1中,在创建索引的过程中会生成2个TM锁,锁类别分别为4和3,根据查询结果发现lmode=4的object_id为77629的对象对应的是T_INDEX_161113这个表,对应的是TM的S锁。另一个lmode=3的锁对象是系统基表OBJ$表,允许其它会话对该表执行DML操作。可以得出这样一个结论:当对表进行创建索引操作时,会伴随出现LMODE=4的S锁。根据锁的兼容模式可以发现S锁和任何DML操作都是冲突的!所以,尤其是在生产上,当在一个很大的表上进行索引创建的时候,任何对该表的DML操作都会被夯住!!!

从DBA_DDL_LOCKS视图可以看到,建索引的同时有6级排它DDL锁。

Oracle 11g下ONLINE选项不会堵塞DML操作

版本:11.2.0.3

接着上面的实验,重建索引的时候加上ONLINE,由于会话断开了,重新开2个会话,会话1为22,会话2为142:

可以发现在会话1中,在加上ONLINE重建索引的过程中会生成2个TM锁,锁类别分别为2和4,根据查询结果发现lmode=2的object_id为77629的对象对应的是T_INDEX_161113这个表,对应的是TM的Row-S (SS)锁即行级共享锁,该锁允许其它会话对该表执行DML操作。另一个lmode=4的锁对象是SYS_JOURNAL_77631,应该为系统临时创建的对象,对应的是TM的S锁。
在会话2中,TX为6的锁,阻塞了其它会话,在这里其实是阻塞了会话1的重建索引的操作。
可以得出这样一个结论:当对表进行创建或重建索引操作时,可以加上ONLINE选项,不阻塞其它会话的DML操作,但是在创建或重建索引的过程中,其它的会话产生的事务会阻塞索引的创建或重建操作,所以必须结束其它会话的事务才能让创建或重建索引的操作完成。
注意:在加上ONLINE选项创建索引的过程中,若手动CTRL+C取消后,可能导致索引被锁,出现ORA-08104: this index object 77645 is being online built or rebuilt的错误,这个时候可以利用如下的脚本清理对象,77645为对象的OBJECT_ID:

Oracle 10g下ONLINE选项会堵塞DML操作

版本为:10.2.0.1.0

重新开3个会话,会话1为143,会话2为152,会话3为158:

可以发现在会话1中,在加上ONLINE重建索引的过程中会生成2个TM锁,锁类别分别为2和4,根据查询结果发现lmode=2的object_id为53121的对象对应的是T_INDEX_161113这个表,对应的是TM的Row-S (SS)锁即行级共享锁,该锁允许其它会话对该表执行DML操作,但是该会话在请求模式为4的S锁。另一个lmode=4的锁对象是SYS_JOURNAL_53122,为系统临时创建的索引组织表(IOT),对应的是TM的S锁。

在会话2中,请求3级TM锁。会阻塞关系可以看出,会话3阻塞了会话1,而会话1阻塞了会话2,所以提交会话3即可让索引创建完成。

实验10.2.0.1.0

版本为:10.2.0.1.0
重新开3个会话,会话1为143,会话2为152,会话3为158,会话1插入一条记录:

从上面的结果可以知道,会话2即创建索引的会话一共出现了4个锁,两个DL锁,一个针对表T_INDEX_161113的TM锁,一个是online rebuild index时需要的一个中间表的TM锁,中间表用于记录rebuild期间的增量数据,原理类似于物化视图日志,其object_id为53162,这是一个索引组织表(IOT),从这里我们也可以发现IOT的优点和适合的场合,这张中间表只有插入,不会有删除和修改操作,而且只有主键条件查询,正是IOT最合适的场景。

会话2在请求一个模式为4的TM锁,模式4会阻塞这个表上的所有DML操作,所以这时再往这个表上执行DML也会挂起。

会话3删除一条语句:

会话3请求模式为3的TM锁无法获得,会话被阻塞。这是因为锁请求是需要排队的,即使会话3和会话1是可以并发的,但由于会话2先请求锁并进入等待队列,后来的会话3也只好进入队列等待。所以,如果在执行rebuild index online前有长事务,并且并发量比较大,则一旦执行alter index rebuild online,可能因为长事务阻塞,可能导致系统瞬间出现大量的锁,对于压力比较大的系统,这是一个不小的风险。这是需要迅速找出导致阻塞的会话kill掉,rebuild index online一旦执行,不可轻易中断,否则可能遇到ORA-08104。

从会话级别可以看出,会话1阻塞了会话2,会话2阻塞了会话3,在会话1执行rollback,可以发现很短时间内会话3也正常执行完毕,说明会话2持有模式4的TM锁的时间很短,然后在rebuild online的进行过程中,对表加的是模式为2的TM锁,所以这段时间不会阻塞DML操作:

回滚会话1,然后观察锁的情况:

会话2又开始在请求模式4的TM锁,被会话3阻塞!这时在会话1再执行DML操作,同样会被会话2阻塞,进入锁等待队列。

本人提供Oracle(OCP、OCM)、MySQL(OCP)、PostgreSQL(PGCA、PGCE、PGCM)等数据库的培训和考证业务,私聊QQ646634621或微信dbaup66,谢谢!
AiDBA后续精彩内容已被站长无情隐藏,请输入验证码解锁本文!
验证码:
获取验证码: 请先关注本站微信公众号,然后回复“验证码”,获取验证码。在微信里搜索“AiDBA”或者“dbaup6”或者微信扫描右侧二维码都可以关注本站微信公众号。

标签:

Avatar photo

小麦苗

学习或考证,均可联系麦老师,请加微信db_bao或QQ646634621

您可能还喜欢...

发表回复