一次遇到一个表锁住了,导致对这个表的子表做相关的操作也被锁住的情况,但是当时只能查询到子表对应的sql的sess_id,找不到父表锁住的sql对应的sess_id,后来在付总等的帮助下成功解决了问题,下面把方法描述下。
1、先select count(*) from v$lock where lmode = 'X' and table_id <> 0; 看看多不多,如果很多的话就要分开分析。
a、知道被锁住的表,从sysobjects里面找到对应的table_id,select id from sysobjects where name = '锁住表的表名';
select trx_id,ltype,lmode,table_id from v$lock where table_id=锁住表的id;
然后到v$sessions中找出对应的sess_id,select * from v$sessions where trx_id = trx1;(trx1上面的sql查询出来的事务ID);
然后执行sp_close_session(sess_id);即可。(注意确认能否杀)
b、不知道被锁住的表,这个可以根据table_id找出阻塞的sql。
with locks as(
select o.name,l.*,s.sess_id,s.sql_text,s.clnt_ip
from v$lock l,sysobjects o,v$sessions s
where l.table_id=o.id and l.trx_id=s.trx_id ),
lock_tr as (
select trx_id wt_trid,row_idx blk_trid from locks where blocked=1),
res as(
select sysdate stattime,t1.name,t1.sess_id wt_sessid,s.wt_trid,t1.sql_text wt_sql,
t2.sess_id blk_sessid,s.blk_trid,t2.clnt_ip
from lock_tr s,locks t1,locks t2
where t1.ltype='OBJECT'
and t1.table_id<>0
and t2.ltype='OBJECT'
and t2.table_id<>0
and s.wt_trid=t1.trx_id
and s.blk_trid=t2.trx_id)
select * from res;
然后再杀掉锁住的会话;
2、select count(*) from v$lock where lmode = 'X' and table_id =0;然后根据这个里面的trx_id在v$sessions里面查询,如果发现查询到的是查询语句,
表明这个查询语句之前可能做了增删改,这里看不到了,那可以在v$sql_history里面找(这个需要enable_monitor>=2)
select top_sql_text from v$sql_history where trx_id = 可疑的事务id;
但是这个v$sql_history只保存最近的语句,如果session中,增删改之后,做了很多的查询语句,有可能也会被冲掉,查询不到结果的。
还有一种可能,就是引发卡住的增删改语句,被新的、不引发卡住增删改语句给冲掉了,
select count(*) from v$lock where lmode = 'X' and table_id =0;记录太多,不好分析时,可借助v$trxwait来分析,到底哪个事务才是真正的罪魁祸首。
执行select * from v$trxwait;(ID 事务 ID ;WAIT_FOR_ID 所等待的事务 ID)
比如trx1在t1上更新没提交,导致trx2也被卡住了,通过v$trxwait可以找到trx2的trx_id,
再通过v$session查trx2的sql,就知道是操作什么表被阻塞了。在v$sessions中不一定能找到trx1的导致卡住的SQL,但肯定能找到trx2的被卡住的SQL。
3、如果实在找不到SQL语句,利用sess_id或trx id,如果log_commit打开了,在log_commit里面应该也能找到sql,然后再针对具体的sql进行分析。
本文地址:https://blog.csdn.net/weixin_42447367/article/details/107675848
您可能感兴趣的文章:
如您对本文有疑问或者有任何想说的,请点击进行留言回复,万千网友为您解惑!
网友评论