问题原因
应用反应堵塞,检查数据库等待事件出现’enq: TX – row lock contention’
业务更新或者删除同一行记录
对创建位图索引的列值更新
对主键或唯一键插入相同记录
解决方案
在enq: TX – row lock contention发生的实例上执行查询:
set linesize 180
set pagesize 999
column username format a16
column event format a40
column sql_child_number format 9999 heading 'SQL Child|Number'
column blocking_instance format 9999 heading 'Blocker|Instance'
column blocking_session format 99999 heading 'Blocker|Session'
column FINAL_BLOCKING_INSTANCE format 9999 heading 'F_Blocker|Instance'
column FINAL_BLOCKING_SESSION format 99999 heading 'F_Blocker|Session'
column "Lock" format a6
column "Mode" format a6
Select sid,
seq#,
username,
event,
sql_id,
sql_child_number,
chr(to_char(bitand(p1, -16777216)) / 16777215) ||
chr(to_char(bitand(p1, 16711680)) / 65535) "Lock",
to_char(bitand(p1, 65535)) "Mode",
blocking_instance,
blocking_session,
final_blocking_instance,
final_blocking_session,
last_call_et
From v$session
Where event = 'enq: TX - row lock contention';
关注blocking_instance/blocking_session和final_blocking_instance/final_blocking_session(适用于11g)
1) 如果final_blocking_instance/final_blocking_session没有变化,说明可能是由于某个进程没有提交事务导致的enq: TX = row lock contention
到holder所在的实例执行以下查询:
set lines 180 pages 999
column username format a15
column program format a35
column machine format a20
column event format a30
column sql_id format a13
column status format a10
Select s.sid,
s.username,
s.event,
s.program,
s.machine,
s.sql_id,
s.sql_child_number,
s.status,
s.last_call_et
From v$session s
Where s.sid in (&sid);
确认不是DB进程,对堵塞者生成kill语句:
set lines 200 pages 999
col username for a15
col machine for a20
col program for a35
col spid for 99999999999
col dbkill for a40
col oskill for a20
col service_name for a20
select a.username,
a.program,
b.addr,
b.spid,
'alter system kill session ''' || a.sid || ',' || a.serial# || ''';' "dbkill",
'kill -9 ' || b.spid "oskill"
from v$session a, v$process b
where a.paddr = b.addr(+)
and a.sid = &sid
-- and a.serial#=&serial
order by a.username, a.program;
执行生成的dbkill命令后继续观察session状态,如果长时间没有消失,在OS级别执行生成的oskill命令(如果是DB 进程,不可随意kill,否则会导致系统crash):
ps –ef|grep &spid
kill -9 &spid
2) 如果blocking_instance/blocking_session和final_blocking_instance/final_blocking_session均在不停变化,说明可能是由于业务SQL执行慢或者是并发高于正常值导致。
确认应用模块,执行如下查询:
column username format a15
column program format a35
column machine format a20
column event format a30
column sql_id format a13
column status format a10
Select s.sid,
s.username,
s.event,
s.program,
s.machine,
s.sql_id,
s.sql_child_number,
s.status,
s.last_call_et
From v$session s
Where event = 'enq: TX - row lock contention'
Order By event, sql_id;
查看SQL执行计划,进一步分析是否是SQL性能问题,如下查询生成查看SQL执行计划的语句:
set lines 160 pages 999
set long 99999
col PLAN_TABLE_OUTPUT for a160
select sql_fulltext,
parsing_schema_name,
'select * from table(dbms_xplan.display_cursor(''' || sql_id ||
''',' || child_number || ',''all iostats last +PEEKED_BINDS''));' xplan
from v$sql
where sql_id = '&sql_id';
包括SQL本身性能问题或者并发突发性增长,这类情况下kill阻塞者并不能解决问题,通知应用处理,允许的条件下通过临时kill所有等待的会话释放:
col username for a15
col machine for a20
col program for a35
col spid for 99999999999
col dbkill for a40
col oskill for a20
Select a.username,
a.program,
a.machine,
b.addr,
b.spid,
'alter system kill session ''' || a.sid || ',' || a.serial# || ''';' "dbkill",
'kill -9 ' || b.spid "oskill"
From v$session a, v$process b
Where a.paddr = b.addr(+)
And a.event = 'enq: TX - row lock contention'
And a.type = ‘USER’
Order By a.username, a.program;
【后续分析】
如果是固定阻塞者,根据blocker session信息,联系相关应用确认该事务未正常提交的原因,避免下次问题发生。
如果是SQL性能变差导致执行慢进而产生等待,进一步分析处理SQL性能问题。
如果SQL执行效率没有问题,那么有可能是并发异常导致的等待,根据应用模块及执行SQL的信息,联系相关应用及时处理并发过高的异常.
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
机房租用,北京机房租用,IDC机房托管, http://www.fwqtg.net
相关推荐: 多云系列|10个关键的多云战略: 评估你对多云的准备情况
尊嘟假嘟服务器托管网,成都程序员也 996 吗? 一家公司在其多云旅程中最可能犯的错误,是没有详尽的计划就入局。在上一篇介绍云智能旅程的文章中,最初的阶段是云优先(Cloud First)。大多数企业没有经过深思熟虑就引入云,这最终导致他们陷入了云混乱(Clo…