love wife love life —Roger的Oracle/MySQL/PostgreSQL数据恢复博客

Phone:18180207355 提供专业Oracle/MySQL/PostgreSQL数据恢复、性能优化、迁移升级、紧急救援等服务

关于enq: TX – row lock contention的测试和案例分析

1、主键或唯一index

可以看出,对于表存在主键或者 unique index 时,一个会话操作主键不提交时,其他会话如果也操作相同的主键时,那么必须进行等待,而其持有的mode=4;而阻塞blocker的持有mode=6.

2、Bitmap INDEX

我们可以看到,如果表上存在位图index,那么在update时,多个会话同时进行更新,必然出现tx 等待。
此时waiter申请持有的tx 锁mode=4,而blocker持有的mode=6,而且通过v$session试图还无法查询到blocker会话到sql_id.

3、数据位于同一block

我们可以看到,不同会话更新同一block中到不同行,不会存在等待,假设更新同一行,那么不提交到情况执行,必然存在等待,这里不再累述。

4、外键

 

实际上我们可以发现,无论子表有没有主键约束,都会存在这种情况,只有主表操作不提交.

实际上还有一种更特殊到情况,也会出现,当然原理上来讲,也上主外键的问题,如下测试:

 

所以,对于enq: TX – row lock contention 我们可以进行如下简单总结:


1. 其原因一般有如下几种:
1) 表上存在主键或唯一性约束,多个会话操作同一条记录

2) 表存在主外键读情况,主表不提交,子表那么必须进行等待.

3) 表上存在位图Index,这跟uniqeue index中存在重复值是一样的道理,其中一个会话操作,其他会话必须等待.

4) 表进行自我外键关联,前面的事务不提交,那么会导致后面的会话一直等待.


2. 对于网上说的enq: TX – row lock contention也有可能是在等待index block分裂的情况,我没有进行测试,   从理论上来讲,如果是在等待index block分裂,那么应该还伴有enq: TX – index contention等待事件产生.


3. 对于enq: TX – row lock contention,通过v$session视图查询时,等待会话带lock mode通常为4,而blocker   会话带lock mode通常为6,并且一般查询blocker会话的sql_id都为空。这是正常现象,v$session显示是当前状态,   而非历史数据.

如下是某客户的真实例子的分析过程,如下:

这里通过dump 这几个process,然后过滤insert into 并没有发现针对party表的insert 操作。
于是尝试换一种思路,通过logminer 来分析进程的操作进程,如下:

当前6个waiter 会话的事务信息如下:

当前2个blocker会话的事务信息如下:

利用logminer 来分析waiter和blocker 会话的操作信息:

最后查询发现blocker和waiter执行的SQL都类似,因此这就很容易说明问题了. 由于logminer抓取的SQL涉及到客户信息,因此这里不便贴出来。这里只是给大家提供一种思路,对于TX锁的分析,也是可以利用logminer来做的。

最后分析发现,本质上来讲,就是因为前后会话操作相同的数据导致,而表上有存在主键,这必然导致出现TX锁等待。

 

PS:或许有人会说,为什么不直接查v$试图抓取sql的绑定变量,实际上我这里已经查过,没有查到,而且通过dump processstate也没有发现,因此才想到利用logminer来分析问题,找到根本原因。



Leave a Reply

You must be logged in to post a comment.