签到成功

知道了

CNDBA社区CNDBA社区

oracle 等待事件 enq TX - row lock contention

2018-05-10 02:45 2129 0 原创 Oracle 11g
作者: leo

产生原因:

    第一种情况:当两个会话对同一行进行更新时,ORACLE为了保证数据库的一致性,加了一个TX锁,这时另一个或多个会话必须等待第一个会话commit或rollback,否则会一等待下去,这是最为常见的一种模式!
    第二种情况:两个或多个会话向具有唯一主健索引的表中插入或更新相同的数据行,既然是唯一主健索引,那么先获得插入的session以TX排它锁模式进行添加,此时其它session只能等待,也是常见的一种情况
    第三种情况:两个或多个会话插入或更新具有位图索引的列,跟据位图索引的特性,一个索引键值对应多个数据行的rowid值,此种情况下也是以TX模式访问,一般在OLTP系统中很少有位图索引,但不排除个别系统。
    第四种情况:调用dbms_repair包时也会产生TX
第五种情况:由ORACLE BUG引起的
Bug 5849679 - Undetected deadlock in RAC involving a TM lock
产生该等待事件的原因基本上就是上面五种情况,前三种优为常见,那么跟据本例中的

模拟环境:

会话1执行:

create table test
  (  id number(10), 
      name varchar2(16)
   ) ;

insert into test values(1001, 'kk');
insert into test values(1002, 'tttt');
commit;
SQL> update test set name='ken' where id=1001;

1 row updated.

会话2执行:

SQL> update test set name='kerry' where id=1001;
会话2 被hang 住

会话3 执行:

找出出现该等待事件的会话及sql
set lines 1000
col USERNAME for a20
col SQL_FULLTEXT for a50
col EVENT for a50
col SQL_ID for a20
col STATUS for a10
select a.sid,
       a.SERIAL#,
       a.EVENT,
       a.USERNAME,
       a.BLOCKING_SESSION,    ----锁的持有者的sid
       b.sql_id,
       b.SQL_FULLTEXT,
       a.SECONDS_IN_WAIT      -----等待时间
  from gv$session a, v$sql b
 where a.EVENT = 'enq: TX - row lock contention'
   and a.SQL_ID = b.SQL_ID;

http://www.cndba.cn/leo1990/article/2769
http://www.cndba.cn/leo1990/article/2769
http://www.cndba.cn/leo1990/article/2769http://www.cndba.cn/leo1990/article/2769
http://www.cndba.cn/leo1990/article/2769

找到等待的热块信息
select blocking_session,sid,serial#,wait_class,seconds_in_wait
from v$session
where blocking_session is not NULL
and sid in(' 33');

http://www.cndba.cn/leo1990/article/2769
http://www.cndba.cn/leo1990/article/2769http://www.cndba.cn/leo1990/article/2769

查询阻塞会话的sid
select sid,serial#,machine,program,EVENT,SQL_ID,STATUS from v$session where sid in('1');

http://www.cndba.cn/leo1990/article/2769http://www.cndba.cn/leo1990/article/2769

确认之后杀掉这个阻塞会话
alter system kill session '1,7';
rac 执行命令alter system kill session 'sid,serial#,@1';
也可以系统层面杀进程
select spid from v$process where addr in (select paddr from v$session where sid=1);

SPID
------------------------
3258
kill -9 3258 
杀掉阻塞会话之后,会话2正常更新。
SQL> update test set name='kerry' where id=1001;

1 row updated.
在会话3 查看没有阻塞
SQL> set lines 1000
col USERNAME for a20
col SQL_FULLTEXT for a50
col EVENT for a50
col SQL_ID for a20
col STATUS for a10
select a.sid,
       a.SERIAL#,
       a.EVENT,
       a.USERNAME,
       a.BLOCKING_SESSION,    ----锁的持有者的sid
       b.sql_id,
b.SQL_FULLTEXT,
       a.SECONDS_IN_WAIT      -----等待时间
  from gv$session a, v$sql b
 where a.EVENT = 'enq: TX - row lock contention'
   and a.SQL_ID = b.SQL_ID;
  8    9   10   11  
no rows selected

解决方案:

第一步:找到那些会话在等待
set lines 1000
col USERNAME for a20
col SQL_FULLTEXT for a50
col EVENT for a50
col SQL_ID for a20
col STATUS for a10
select a.sid,
       a.SERIAL#,
       a.EVENT,
       a.USERNAME,
       a.BLOCKING_SESSION,    ----锁的持有者的sid
       b.sql_id,
       b.SQL_FULLTEXT,
       a.SECONDS_IN_WAIT      -----等待时间
  from gv$session a, v$sql b
 where a.EVENT = 'enq: TX - row lock contention'
   and a.SQL_ID = b.SQL_ID;
第二步:找到等待的热块信息
select blocking_session,sid,serial#,wait_class,seconds_in_wait
from v$session
where blocking_session is not NULL
and sid in(sid);
第三步:杀掉seconds_in_wait=0的会话,即可解决现实问题
alter system kill session 'sid,serail#'
第四步:跟据SQL_ID找到对应的SQL,向开发人员反馈,修改相应的业务逻辑,是否可避免此类情况的发生
第五步:查看表和索引的统计信息是否过旧,及时收集表和索引的统计信息

版权声明:本文为博主原创文章,未经博主允许不得转载。

用户评论
* 以下用户言论只代表其个人观点,不代表CNDBA社区的观点或立场
leo

leo

关注

坚持你的坚持

  • 202
    原创
  • 0
    翻译
  • 39
    转载
  • 16
    评论
  • 访问:670840次
  • 积分:1270
  • 等级:核心会员
  • 排名:第8名
精华文章
    最新问题
    查看更多+
    热门文章
      热门用户
      推荐用户
        Copyright © 2016 All Rights Reserved. Powered by CNDBA · 皖ICP备2022006297号-1·

        QQ交流群

        注册联系QQ