日常运维之TX锁处理(一)

来源:这里教程网 时间:2026-03-03 17:22:49 作者:

有经验的DBA 在遇到TX 锁时,第一反应就是查询v$lock v$session 视图,定位LMODE REQUEST 类型互斥的会话并进行查杀。然而,随着数据库版本不断地迭代更新,v$session 视图的内容越来越丰富,可以直接使用blocking_session blocking_instance final_blocking_instance final_blocking_session 字段进行定位。对于锁层次的排查可以重复查询v$session 来确定,但如果锁层次有100 层,我们就不可能通过人工遍历100 次,显然这种方式过于低效,不适用于生产环境。 下面就来介绍本节的主角:Oracle SYS_CONNECT_BY_PATH 函数。自Oracle 9i 开始,DBA 可以使用SYS_CONNECT_BY_PATH 函数,将父节点到当前行的内容以“路径”或层次的形式显示出来。该功能刚好符合我们递归查找锁层次的需求,在这里 笔者模拟了锁环境,使用如下语句查询锁信息: SQL> select a.inst_id ,       a.process ,       a.sid ,       a.serial# ,       a.sql_id ,       a.event ,       a.status ,       a.program ,       a.machine ,       connect_by_isleaf as isleaf ,       sys_connect_by_path (a.SID || '@' || a.inst_id , ' <- ' ) tree ,       level as tree_level  from gv$session a  start with a.blocking_session is not null connect by (a.sid || '@' || a.inst_id ) = prior           (a.blocking_session || '@' || a.blocking_instance );

<!-- 省略部分列 -->

INST_ID PROCESS   SID    SERIAL#  EVENT                          STATUS     ISLEAF TREE              TREE_LEVEL

------- -------- ---- ----------  ------------------------------ ---------- ------ -----------------  ----------

      1 7663       17       6749  enq: TX - row lock contention  ACTIVE          0  <- 17@1                   1

      1 6198       25       9989  SQL*Net message from client    INACTIVE        1  <- 17@1 <- 25@1           2

      1 6310       28      23199  enq: TX - row lock contention  ACTIVE          0  <- 28@1                   1

      1 6198       25       9989  SQL*Net message from client    INACTIVE        1  <- 28@1 <- 25@1           2 代码段中,部分参数说明如下。

q   INST_ID :会话所在的节点号。

q   PROCESS :客户端进程号,与v$process 中的spid 不是同一个。

q   SID SERIAL# SQL_ID STATUS PROGRAM MACHINE :会话信息。

q   ISLEAF :是否为源头,0 代表否,1 代表是。TREE :树形结构,锁的层次,例如,<- 152@2 <- 153@2 <- 161@1 ,从左到右表示为2 节点的会话152 2 节点的会话153 堵塞,而2 节点的会话153 又被1 节点的会话161 堵塞。所以1 节点的会话161 是锁的源头。

q   TREE_LEVEL :树形层次。 锁源头的查杀方法有两种,说明如下。

1   通过ISLEAF 进行筛选,直接查杀锁源头,语句如下: SQL> select 'alter system kill session ''' || sid || '' || ',' || serial# || ',@' ||       inst_id || ''' immediate;' db_kill_session  from ( select a.inst_id ,               a.process ,               a.sid ,               a.serial# ,               a.sql_id ,               a.event ,               a.status ,               a.program ,               a.machine ,               connect_by_isleaf as isleaf ,               sys_connect_by_path (a.SID || '@' || a.inst_id , ' <- ' ) tree ,               level as tree_level          from gv$session a         start with a.blocking_session is not null        connect by (a.sid || '@' || a.inst_id ) = prior                   (a.blocking_session || '@' || a.blocking_instance ))  where isleaf =order by tree_level asc ;KILL_SESSION---------------------------------------------------alter system kill session '161,5579,@1' immediate;alter system kill session '161,5579,@1' immediate;  SQL> select inst_id , 'kill -9 ' || spid os_kill_session  from ( select p.inst_id ,               p.spid ,               a.sid ,               a.serial# ,               a.sql_id ,               a.event ,               a.status ,               a.program ,               a.machine ,               connect_by_isleaf as isleaf ,               sys_connect_by_path (a.SID || '@' || a.inst_id , ' <- ' ) tree ,               level as tree_level          from gv$session a , gv$process p         where a.inst_id = p.inst_id           and a.paddr = p.addr         start with a.blocking_session is not null        connect by (a.sid || '@' || a.inst_id ) = prior                   (a.blocking_session || '@' || a.blocking_instance ))  where isleaf =order by tree_level asc ;    INST_ID OS_KILL_SESSION---------- --------------------------------         1 kill -9 30049

2   借助v$session 中的final_blocking_instance final_blocking_session 定位锁源头,语句如下: SQL> select 'alter system kill session ''' || ss.sid || '' || ',' || ss.serial# || ',@' ||       ss.inst_id || ''' immediate;' db_kill_session  from gv$session s , gv$session ss  where s.final_blocking_session is not null   and s.final_blocking_instance = ss.inst_id   and s.final_blocking_session = ss.sid   and s.sid <> ss.sidDB_KILL_SESSION--------------------------------------------------alter system kill session '161,5579,@1' immediate;alter system kill session '161,5579,@1' immediate;  SQL> select p.inst_id , 'kill -9 ' || p.spid os_kill_session  from gv$session s , gv$session ss , gv$process p  where s.final_blocking_session is not null   and s.final_blocking_instance = ss.inst_id   and s.final_blocking_session = ss.sid   and ss.paddr = p.addr   and ss.inst_id = p.inst_id   and s.sid <> ss.sid   INST_ID OS_KILL_SESSION---------- --------------------------------         1 kill -9 30049 执行拼接生成的语句,即可杀掉锁的源头。

相关推荐