查询堵塞进程的几种SQL--

本文介绍了四种查询Oracle数据库中阻塞会话的方法,包括使用v$lock视图、v$wait_chains视图等进行查询的具体SQL语句,帮助快速定位数据库中出现的阻塞情况。
  逛论坛看到一篇关于blocking session的帖子 归纳一下几种查询


with vw_lock AS (SELECT * FROM v$lock)

select
a.sid,
'is blocking',
(select 'sid:'||s.sid||' object:'||do.object_name||' rowid:'||
    dbms_rowid.rowid_create ( 1, ROW_WAIT_OBJ#, ROW_WAIT_FILE#, ROW_WAIT_BLOCK#, ROW_WAIT_ROW# )
    ||' sql_id:'||s.sql_id
   from v$session s, dba_objects do
    where s.sid=b.sid
    and s.ROW_WAIT_OBJ# = do.OBJECT_ID
) blockee,
b.sid,b.id1,b.id2
from vw_lock a, vw_lock b
where a.block = 1
and b.request > 0
and a.id1 = b.id1
and a.id2 = b.id2;

SELECT /*+ ORDERED USE_HASH(H,R) */ 
          H.SID HOLD_SID, 
          R.SID WAIT_SID, 
          decode(H.type, 
        'MR', 'Media Recovery', 
        'RT', 'Redo Thread', 
        'UN', 'User Name', 
        'TX', 'Transaction', 
        'TM', 'DML', 
        'UL', 'PL/SQL User Lock', 
        'DX', 'Distributed Xaction', 
        'CF', 'Control File', 
        'IS', 'Instance State', 
        'FS', 'File Set', 
        'IR', 'Instance Recovery', 
        'ST', 'Disk Space Transaction', 
        'TS', 'Temp Segment', 
        'IV', 'Library Cache Invalidation', 
        'LS', 'Log Start or Switch', 
        'RW', 'Row Wait', 
        'SQ', 'Sequence Number', 
        'TE', 'Extend Table', 
        'TT', 'Temp Table', 
        'TC', 'Thread Checkpoint', 
              'SS', 'Sort Segment', 
              'JQ', 'Job Queue', 
              'PI', 'Parallel operation', 
              'PS', 'Parallel operation', 
              'DL', 'Direct Index Creation', 
        H.type) type, 
      decode(H.lmode, 
        0, 'None',   1, 'Null', 
        2, 'Row-S (SS)',   3, 'Row-X (SX)', 
        4, 'Share',        5, 'S/Row-X (SSX)', 
        6, 'Exclusive',    to_char(H.lmode)) hold, 
       decode(r.request,   0, 'None', 
        1, 'Null',   2, 'Row-S (SS)', 
        3, 'Row-X (SX)',   4, 'Share', 
        5, 'S/Row-X (SSX)',6, 'Exclusive', 
        to_char(R.request)) request, 
      R.ID1,R.ID2,R.CTIME 
    FROM V$LOCK H,V$LOCK R 
    WHERE H.BLOCK = 1 AND R.REQUEST > 0 AND H.SID <> R.SID 
      and H.TYPE <> 'MR' AND R.TYPE <> 'MR' 
      AND H.ID1 = R.ID1 AND H.ID2 = R.ID2 AND H.TYPE=R.TYPE 
      AND H.LMODE > 0 AND R.REQUEST > 0 ORDER BY 1,2;


select /*+ rule */
l.block blk_status,
l.inst_id,
l.sid, /* s.serial#, */
p.spid,
s.status,
s.sql_hash_value hash_value,
s.program,
s.username,
s.last_call_et, /* s.sql_id,s.sql_child_number c_n,*/
l.lmode,
l.type,
l.request,
l.ctime
  from (select inst_id,
               sid,
               type,
               id1,
               id2,
               lmode,
               request,
               ctime,
               decode(block, 0, 'blocked', 1, 'blocking', 2, 'global') block
          from gv$lock
         where (id1, id2, type) in
               (select id1, id2, type from gv$lock where request > 0)) l,
       gv$session s,
       gv$process p
where l.sid = s.sid
   and l.inst_id = s.inst_id
   and s.inst_id = p.inst_id
   and s.paddr = p.addr
   and s.username is not null
order by 1, inst_id, status;

现在有v$wait_chains接口了

Basic Information:
SELECT chain_id, num_waiters, in_wait_secs, osid, blocker_osid, substr(wait_event_text,1,30) FROM v$wait_chains;

Top 100 wait chain processes:
set pages 1000
set lines 120
set heading off
column w_proc format a50 tru
column instance format a20 tru
column inst format a28 tru
column wait_event format a50 tru
column p1 format a16 tru
column p2 format a16 tru
column p3 format a15 tru
column Seconds format a50 tru
column sincelw format a50 tru
column blocker_proc format a50 tru
column waiters format a50 tru
column chain_signature format a100 wra
column blocker_chain format a100 wra

SELECT *
FROM (SELECT 'Current Process: '||osid W_PROC, 'SID '||i.instance_name INSTANCE,
'INST #: '||instance INST,'Blocking Process: '||decode(blocker_osid,null,'',blocker_osid)||
' from Instance '||blocker_instance BLOCKER_PROC,'Number of waiters: '||num_waiters waiters,
'Wait Event: ' ||wait_event_text wait_event, 'P1: '||p1 p1, 'P2: '||p2 p2, 'P3: '||p3 p3,
'Seconds in Wait: '||in_wait_secs Seconds, 'Seconds Since Last Wait: '||time_since_last_wait_secs sincelw,
'Wait Chain: '||chain_id ||': '||chain_signature chain_signature,'Blocking Wait Chain: '||decode(blocker_chain_id,null,
'',blocker_chain_id) blocker_chain
FROM v$wait_chains wc,
v$instance i
WHERE wc.instance = i.instance_number (+)
AND ( num_waiters > 0
OR ( blocker_osid IS NOT NULL
AND in_wait_secs > 10 ) )
ORDER BY chain_id,
num_waiters DESC)
WHERE ROWNUM < 101;

Final Blocking Session in 11.2:
set pages 1000
set lines 120
set heading off
column w_proc format a50 tru
column instance format a20 tru
column inst format a28 tru
column wait_event format a50 tru
column p1 format a16 tru
column p2 format a16 tru
column p3 format a15 tru
column Seconds format a50 tru
column sincelw format a50 tru
column blocker_proc format a50 tru
column fblocker_proc format a50 tru
column waiters format a50 tru
column chain_signature format a100 wra
column blocker_chain format a100 wra

SELECT *
FROM (SELECT 'Current Process: '||osid W_PROC, 'SID '||i.instance_name INSTANCE,
'INST #: '||instance INST,'Blocking Process: '||decode(blocker_osid,null,'',blocker_osid)||
' from Instance '||blocker_instance BLOCKER_PROC,
'Number of waiters: '||num_waiters waiters,
'Final Blocking Process: '||decode(p.spid,null,'',
p.spid)||' from Instance '||s.final_blocking_instance FBLOCKER_PROC,
'Program: '||p.program image,
'Wait Event: ' ||wait_event_text wait_event, 'P1: '||wc.p1 p1, 'P2: '||wc.p2 p2, 'P3: '||wc.p3 p3,
'Seconds in Wait: '||in_wait_secs Seconds, 'Seconds Since Last Wait: '||time_since_last_wait_secs sincelw,
'Wait Chain: '||chain_id ||': '||chain_signature chain_signature,'Blocking Wait Chain: '||decode(blocker_chain_id,null,
'',blocker_chain_id) blocker_chain
FROM v$wait_chains wc,
gv$session s,
gv$session bs,
gv$instance i,
gv$process p
WHERE wc.instance = i.instance_number (+)
AND (wc.instance = s.inst_id (+) and wc.sid = s.sid (+)
and wc.sess_serial# = s.serial# (+))
AND (s.final_blocking_instance = bs.inst_id (+) and s.final_blocking_session = bs.sid (+))
AND (bs.inst_id = p.inst_id (+) and bs.paddr = p.addr (+))
AND ( num_waiters > 0
OR ( blocker_osid IS NOT NULL
AND in_wait_secs > 10 ) )
ORDER BY chain_id,
num_waiters DESC)
WHERE ROWNUM < 101;

Troubleshooting Database Contention With V$Wait_Chains (Doc ID 1428210.1)
11g upgrade
Infinity I/O SAN Bootcamp
O'Reilly.Mastering.Perl,Intermediate.Perl
mysql......
oracle on linux!!

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/26526320/viewspace-2121361/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/26526320/viewspace-2121361/

<think> 嗯,用户问的是SQL Server中查找死锁进程的方法。从用户提供的引用内容来看,重点在如何识别导致死锁的源头进程阻塞关系。用户可能是个DBA或者开发人员,遇到了死锁问题需要紧急排查。 用户引用的资料里提到了几种典型方法:一是通过sysprocesses系统视图查询blocked字段(引用2和3),二是使用游标遍历阻塞链(引用2),三是创建存储过程分析死锁关系(引用4)。这些方法各有优劣,需要整合成清晰的操作步骤。 考虑到用户实际使用场景,应该优先推荐动态管理视图DMV的方案,因为SQL Server 2005之后官方更推荐这种方式。引用3中提到的sys.dm_tran_locks和sys.dm_exec_requests组合查询会更准确。不过老版本的sysprocesses方法也要保留,毕竟很多企业还在用SQL Server 2000。 用户可能没意识到死锁监控的持续性需求,所以补充了扩展监控方案。引用4里那个存储过程其实挺实用,但代码太长不适合直接放在回答里,改成说明核心逻辑就好。安全方面要提醒用户谨慎使用KILL命令,避免在生产环境随意杀进程。 具体操作步骤需要分层设计:基础查询放第一部分,高级诊断放第二部分。引用5展示的DBCC INPUTBUFFER很重要,这是定位问题SQL的关键,必须包含在第二步里。最后补充的服务器级监控参考了引用1和引用4的混合思路。 用户语气比较急,回答要侧重可操作性。每个步骤都给出完整SQL示例,字段说明用表格呈现更直观。危险操作如KILL命令需要特别标注警示符号,毕竟运维事故往往发生在紧急处理时。 </think>在 SQL Server 中查找导致死锁的源头进程,可以通过系统视图、动态管理视图 (DMV) 和特定查询来实现。以下是几种常用方法: --- ### **方法 1:使用系统视图 `sys.sysprocesses`(适用于所有版本)** ```sql -- 查询阻塞链源头(死锁的发起者) SELECT spid AS [进程ID], blocked AS [阻塞者ID], loginame AS [登录名], hostname AS [主机名], program_name AS [程序名], last_batch AS [最后执行时间], cmd AS [命令类型], [状态] = CASE WHEN blocked = 0 THEN '死锁源头' ELSE '被阻塞进程' END FROM sys.sysprocesses WHERE blocked <> 0 OR spid IN (SELECT blocked FROM sys.sysprocesses WHERE blocked <> 0) ORDER BY blocked DESC; ``` **说明**: - `blocked <> 0` 表示当前进程阻塞- 若某进程的 `blocked = 0` 但被其他进程阻塞,则是死锁源头。 - 结果中 `[状态]` 列标识了死锁源头进程--- ### **方法 2:使用动态管理视图 (DMV)(推荐 SQL Server 2005+)** ```sql -- 查询当前阻塞链 SELECT w.session_id AS [被阻塞进程ID], w.blocking_session_id AS [阻塞进程ID], w.wait_type AS [等待类型], w.wait_duration_ms AS [等待时长(ms)], r.command AS [命令类型], t.text AS [执行语句], s.login_name AS [登录名], s.program_name AS [程序名] FROM sys.dm_exec_requests w INNER JOIN sys.dm_exec_sessions s ON w.session_id = s.session_id CROSS APPLY sys.dm_exec_sql_text(w.sql_handle) t INNER JOIN sys.dm_exec_requests r ON w.blocking_session_id = r.session_id WHERE w.blocking_session_id <> 0; ``` **关键字段**: - `blocking_session_id`:直接显示阻塞当前进程进程 ID。 - 通过递归查询可追溯到死锁源头(即最顶层的 `blocking_session_id`)。 --- ### **方法 3:捕获死锁源头进程SQL 语句** ```sql -- 根据进程 ID 获取执行语句 DBCC INPUTBUFFER (<进程ID>); -- 替换为实际进程ID -- 或使用 DMV 查询 SELECT session_id, text AS [执行语句] FROM sys.dm_exec_connections CROSS APPLY sys.dm_exec_sql_text(most_recent_sql_handle) WHERE session_id = <进程ID>; -- 替换为实际进程ID ``` --- ### **方法 4:使用系统存储过程 `sp_who` / `sp_who2`** ```sql EXEC sp_who; -- 简略信息 EXEC sp_who2; -- 详细信息(含阻塞链) ``` **解读结果**: - `BlkBy` 列显示阻塞当前进程的 ID(若为 `.` 表示无阻塞)。 - 找到 `BlkBy` 值为 `0` 但阻塞其他进程进程(即死锁源头)。 --- ### **扩展:自动化监控死锁(创建存储过程)** 参考引用 [4],创建存储过程 `p_lockinfo` 可自动分析死锁链条: ```sql CREATE PROC p_lockinfo @kill_lock_spid BIT = 0, -- 是否终止死锁进程(0=仅显示) @show_spid_if_nolock BIT = 1 -- 无死锁时是否显示正常进程 AS BEGIN -- 分析死锁链并输出结果(代码详见引用[4]) END; ``` **执行示例**: ```sql EXEC p_lockinfo @kill_lock_spid = 0; -- 仅显示死锁信息 ``` --- ### **终止死锁进程** ```sql -- 终止指定进程 KILL <进程ID>; -- 替换为源头进程ID ``` ⚠️ **警告**: 终止进程可能导致事务回滚,需评估业务影响后再操作[^3]。 --- ### **总结步骤** 1. **定位死锁源头**:通过 `sys.sysprocesses` 或 `sp_who2` 找到 `blocked=0` 且阻塞他人的进程。 2. **查看执行语句**:用 `DBCC INPUTBUFFER` 或 DMV 检查源头进程SQL。 3. **终止进程**:谨慎使用 `KILL` 命令解除死锁[^5]。 --- **相关问题** 1. 如何自动捕获 SQL Server 的死锁图形和详细信息? 2. 如何通过 SQL Server Profiler 监控死锁事件? 3. 死锁发生的常见场景及预防策略有哪些? 4. 如何配置 SQL Server 在死锁时自动终止优先级低的进程? [^1]: 通过系统存储过程分析死锁链条。 [^2]: 使用游标遍历阻塞链并定位源头。 [^3]: 终止进程前需确认影响范围。 [^4]: 创建存储过程自动化监控死锁。 [^5]: 终止进程是解除死锁的直接手段。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值