等待事件enq TX row lock contention分析(一)

2014-11-24 12:35:06 · 作者: · 浏览: 6
等待事件enq TX row lock contention分析
在Oracle 数据库性能报告AWRRPT分析时,发现top 5等待事件第一位的是enq: TX - row lock contention。 www.2cto.com
Rpt代码
Top 5 Timed Events
Event Waits Time(s) Avg Wait(ms) % Total Call Time Wait Class
enq: TX - row lock contention 27,190 62,674 2,305 63.1 Application
CPU time 36,227 36.5
log file sync 133,744 52 0 .1 Commit
log file parallel write 143,992 29 0 .0 System I/O
db file sequential read 49,403 23 0 .0 User I/O
声明一下,数据库版本是10g for linux x86 64bit。
这个等待事件消耗了绝大多数的CPU资源,导致系统整理性能下降。有些查询以前只要几个毫秒,现在变成了数分钟。CPU使用率长时间维持在100%。 www.2cto.com
等待事件enq: TX - row lock contention在下列三种情况下会出现。
第一种情况,是真正的业务逻辑上的行锁冲突,一条记录被多个人同时操作如同时更新。这种锁对应的请求模式是6。
第二种情况,是唯一键冲突,就是如主键字段相同的多条记录同时插入。这种锁对应的请求模式是4。这也是应用逻辑问题。
第三种情况,是bitmap索引块上更新冲突,就是多个会话同时更新bitmap索引上同一个数据块。此时会话请求锁的对应的请求模式是4。
bitmap索引的物理结构和普通索引一样,也是 B-tree 结构。它存储的数据记录的逻辑结构为"key_value,start_rowid,end_rowid,bitmap"。
其内容类似这样:
"‘8088’,00000000000,10000034441,1001000100001111000"
Bitmap是一个二进制,表示 START_ROWID 到 END_ROWID 的记录, 1 表示等于 key_value 即‘ 8088 ‘的 ROWID 记录, 0 则表示不是这个记录。
我们了解bitmap索引的结构,就能理解同时插入多条记录到拥有bitmap索引的表中时,会同时更新bitmap索引中一个块中的记录。并发量越大,等待越严重。
enquence是协调访问数据库资源的锁。enq:打头的等待事件表示这个会话正在等待另一个会话持有的锁,它的名称组成是enq:enqueue_type - related_details。在v$event_name中提供enq:开头的等待事件的完整列表。
在v$session和v$session_wait中,看到的event列是enq: TX - row lock contention的,就是表示这个会话正处于行锁等待。该等待事件的p1参数值是name|mode。
select sid,
chr(bitand(p1, -16777216) / 16777215) ||
chr(bitand(p1, 16711680) / 65535) "Name",
(bitand(p1, 65535)) "Mode"
from v$session_wait
where event like 'enq%';
通过这个SQL可以将p1转换为易 阅读的文字。
我针对这三种情况,分别进行测试。
首先,我准备一下测试表和数据。
--创建测试表和数据
create table t_all_objs as select owner,object_id,object_name from all_objects where 0=1;
alter table T_ALL_OBJS add constraint pk_t_all_objs primary key (OBJECT_ID);
insert into t_all_objs(owner,object_id,object_name) values('TEST',2013011701,'test1');
insert into t_all_objs(owner,object_id,object_name) values('TEST',2013011702,'test2');
commit;
第一种情况,不同会话同时更新同一条记录
--test1
--sid=1015
update t_all_objs set object_name='test11' where object_id=2013011701;
--sid=1065
update t_all_objs set object_name='test101' where object_id=2013011701;
--第三个会话中查询
select sid,sql_id,blocking_session,event,p1text,p1,wait_class,state from v$session where sid in (1015, 1065);
select * from v$session_wait where sid in (1015, 1065);
SID SQL_ID BLOCKING_SESSION EVENT P1TEXT P1 WAIT_CLASS STATE
1 1015 SQL*Net message from client driver id 1413697536 Idle WAITING
2 1065 6y6u0gx4qa5v5 1015 enq: TX - row lock contention name|mode 1415053318 Application WAITING
SID SEQ# EVENT P1TEXT P1 P1RAW P2TEXT P2 P2RAW P3TEXT P3 P3RAW WAIT_CLASS_ID WAIT_CLASS# WAIT_CLASS WAIT_TIME SECONDS_IN_WAIT STATE
1 1015 44 SQL*Net message from client driver id 1413697536 54435000 #bytes 1 00000001 0 00 2723168908 6 Idle 0 1306 WAITING
2 1065 41 enq: TX - row lock contention name|mode 1415053318 54580006 usn<<16 | slot 655407 000A002F sequence 92680 00016A08 4217450380 1 Application 0 1291 WAITING
--得到sql_id值,查询出SQL信息。