enq: TX - row lock contention事件:表的行锁等待事件。
查询资料获取:row lock contention事件产生的原因有以下五种:
1、第一种情况:当两个会话对同一行进行更新时,ORACLE为了保证数据库的一致性,加了一个TX锁,这时另一个或多个会话必须等待第一个会话commit或rollback,否则会一等待下去,这是最为常见的一种模式!
2、第二种情况:两个或多个会话向具有唯一主健索引的表中插入或更新相同的数据行,既然是唯一主健索引,那么先获得插入的session以TX排它锁模式进行添加,此时其它session只能等待,也是常见的一种情况
3、第三种情况:两个或多个会话插入或更新具有位图索引的列,跟据位图索引的特性,一个索引键值对应多个数据行的rowid值,此种情况下也是以TX模式访问,一般在OLTP系统中很少有位图索引,但不排除个别系统,本例中不存在位图索引。
4、第四种情况:调用dbms_repair包时也会产生TX--在网上看到的,具体怎么个原理,后面有空再研究该包
5、第五种情况:由ORACLE BUG引起的
Bug 3159414 documents another case where we might see a TX request in mode 4 when constraints are involved.
Bug 5849679 documents an undetected deadlock case with RAC.
产生该等待事件的原因基本上就是上面五种情况,前三种优为常见。
一、创建一个enq: TX - row lock contention 锁(使用行操作的方式)
创建临时表bd_ma
然后打开一个sql窗口(创建一个session)执行delete命令,但不提交
再打开一个sql窗口(再创建一个session)也执行delete命令
此时就可以发现该命令一直等待上一个delete结束,此时即创造了一个enq: TX - row lock contention事件。
二、被用户创建后,如何在当时找到该事件,并处理
1、视图v$session中事件等于enq: TX - row lock contention的
sid = 37的session在等待
2、同样通过v$session找到处理的对象
obj_id = 91674,该对象可能是表也可能是索引或者其他的
3、看下该对象是什么查找dba_object表,中id = 91674的
发现该对象是表,名称是bd_ma.
到此知道发生行锁等待事件的对象是bd_ma这个表造成的。
4、继续找到是哪个用户在执行什么操作造成:
同样通过v$session去找,发现osuser是derek,即客户端是derek这台客户端造成的,信息部可以追踪到该客户端的使用用户。
5、找到是哪个语句造成的,通过v$session和v$sql找到sqltext。
到此就可发现是因为delete命令一直没有提交造成。
三、若是历史AWR中如何找到线索?
1、通过dba_hist_active_sess_history找到发生过enq: TX - row lock contention事件的session_id.sql_id
发现历史有两个,分别是session = 40和session = 15。
2、找到对应的session具体信息,是哪个machine
3、找到当时发生时候的语句。
附当时发生时候跟踪的所有sql
--找到发生enq: TX - row lock contention的等待事件
select event,sid,p1,p2,p3 from v$session_wait where event = 'enq: TX - row lock contention';
--1 enq: TX - row lock contention 37 1415053318 589833 1934
--看这些session在等什么对象
select event, ROW_WAIT_OBJ#,ROW_WAIT_FILE#,ROW_WAIT_BLOCK#,ROW_WAIT_ROW# from v$session
where event='enq: TX - row lock contention';
--1 enq: TX - row lock contention 91674 5 10441 0
--说明在等91674这个对象
--看91674这个对象是什么
select object_name,object_id,owner,object_type from dba_objects where object_id='91674';
--1 BD_MA 91674 NC633 TABLE 原来是table
--另,查看是什么语句造成的等待事件,填入等待事件的sid
select sid,sql_text from v$session a,v$sql b where sid in('37')
and (b.sql_id=a.sql_id );
--看下是哪里的客户端造成的
select sid,serial#,username,status,osuser,machine,port,terminal,program,sql_id,sql_exec_start,prev_sql_id, type from v$session where sid = '37'
--1 37 162 NC633 ACTIVE derek WORKGROUP\DEREKPC 60452 DEREKPC plsqldev.exe 8tzau2c2gbdtr 2015/8/12 13:45:58 9m7787camwh4m USER
select * from v$lock where type = 'TX';
select s.sid, q.sql_id,q.SQL_FULLTEXT
from v$session s, v$sql q
where sid in
(select sid
from v$session
where state in ('WAITING')
and wait_class != 'Idle'
and event = 'enq: TX - row lock contention'
and (q.sql_id = s.sql_id or q.sql_id = s.prev_sql_id));
附历史发生时候查找的sql
--查找历史发生过enq: TX - row lock contention事件的记录
select session_id,session_serial#,sql_id from dba_hist_active_sess_history
where event = 'enq: TX - row lock contention' order by sample_time;
--找到session_id 和sql_id是1 40 298 8tzau2c2gbdtr
-- 77 15 680 8tzau2c2gbdtr
--查看对应session_id的信息
select distinct session_id,sql_id,sql_opname,program,module,action,machine from v$active_session_history where session_id in ('40','15')
and event = 'enq: TX - row lock contention'
and is_awr_sample = 'Y'
--查看对应session执行的语句
select -- s.SAMPLE_TIME,
distinct s.SESSION_ID,
sq.SQL_TEXT,
--sq.SQL_FULLTEXT,
sq.SQL_ID
from v$sql sq, v$active_session_history s
where s.SQL_ID = sq.SQL_ID
and s.SESSION_ID in ('15','40')
and sq.SQL_ID = '8tzau2c2gbdtr'
附参考:
enq: TX - row lock contention等待事件http://blog.csdn.net/songyang_oracle/article/details/6433753
解决一则enq: TX - row lock contention的性能故障http://www.oracleonlinux.cn/2012/11/resolve-row-lock-contention/
oracle的TM锁、TX锁
http://blog.sina.com.cn/s/blog_95b5eb8c0101i22x.html
结语:不适合写这种文章……以后不写了。字体都太大了~~~看起来好累