锁对象

Understand and resolve blocking problems - SQL Server | Microsoft Learn

类型 KEY 代表锁的是索引中的一行。

锁类型

SQL Server 锁(LOCK)大全 - 五维思考 - 博客园

意向锁

SQL Server 意向锁 - 墨天轮

sql server中意向锁的作用 - xwdreamer - 博客园

常用判断锁表的查询

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
-- 查看锁和被锁的 SQL
SELECT
t1.resource_type ,
DB_NAME( resource_database_id) AS dat_name ,
t1.resource_associated_entity_id,
t1.request_mode,
t1.request_session_id,
t2.wait_duration_ms,
( SELECT TEXT FROM sys.dm_exec_requests r CROSS apply sys.dm_exec_sql_text ( r.sql_handle ) WHERE r.session_id = t1.request_session_id ) AS wait_sql,
t2.blocking_session_id,
( SELECT TEXT FROM sys.sysprocesses p CROSS apply sys.dm_exec_sql_text ( p.sql_handle ) WHERE p.spid = t2.blocking_session_id ) AS blocking_sql
FROM
sys.dm_tran_locks t1,
sys.dm_os_waiting_tasks t2
WHERE
t1.lock_owner_address = t2.resource_address;

来源:sql - How to check which locks are held on a table - Stack Overflow

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
-- List all Locks of the Current Database
SELECT TL.resource_type AS ResType
,TL.resource_description AS ResDescr
,TL.request_mode AS ReqMode
,TL.request_type AS ReqType
,TL.request_status AS ReqStatus
,TL.request_owner_type AS ReqOwnerType
,TAT.[name] AS TransName
,TAT.transaction_begin_time AS TransBegin
,DATEDIFF(ss, TAT.transaction_begin_time, GETDATE()) AS TransDura
,ES.session_id AS S_Id
,ES.login_name AS LoginName
,COALESCE(OBJ.name, PAROBJ.name) AS ObjectName
,PARIDX.name AS IndexName
,ES.host_name AS HostName
,ES.program_name AS ProgramName
FROM sys.dm_tran_locks AS TL
INNER JOIN sys.dm_exec_sessions AS ES
ON TL.request_session_id = ES.session_id
LEFT JOIN sys.dm_tran_active_transactions AS TAT
ON TL.request_owner_id = TAT.transaction_id
AND TL.request_owner_type = 'TRANSACTION'
LEFT JOIN sys.objects AS OBJ
ON TL.resource_associated_entity_id = OBJ.object_id
AND TL.resource_type = 'OBJECT'
LEFT JOIN sys.partitions AS PAR
ON TL.resource_associated_entity_id = PAR.hobt_id
AND TL.resource_type IN ('PAGE', 'KEY', 'RID', 'HOBT')
LEFT JOIN sys.objects AS PAROBJ
ON PAR.object_id = PAROBJ.object_id
LEFT JOIN sys.indexes AS PARIDX
ON PAR.object_id = PARIDX.object_id
AND PAR.index_id = PARIDX.index_id
WHERE TL.resource_database_id = DB_ID()
AND ES.session_id <> @@Spid -- Exclude "my" session
-- optional filter
AND TL.request_mode <> 'S' -- Exclude simple shared locks
ORDER BY TL.resource_type
,TL.request_mode
,TL.request_type
,TL.request_status
,ObjectName
,ES.login_name;

来源:sql - How to check which locks are held on a table - Stack Overflow

SPID 和 Session_id 有什么区别?

答:一样的。

参考:sql server - differences between SPID and session_id - Database Administrators Stack Exchange

排查 ASYNC_NETWORK_IO 等待问题

Troubleshoot slow queries resulting from ASYNC_NETWORK_IO - SQL Server | Microsoft Learn

微软给出的原因是客户端查询了大量数据,但是没有及时消费,所以服务端一直在等待客户端消费完对应的数据。

Reducing SQL Server ASYNC_NETWORK_IO wait type

杀掉阻塞的进程

KILL SPID command in SQL Server

KILL (Transact-SQL) - SQL Server | Microsoft Learn

1
KILL <session_id>;

执行之后可以通过:

1
KILL <session_id> with STATUSONLY;

来查询杀进程的执行进度。

排查阻塞问题

Understand and resolve blocking problems - SQL Server | Microsoft Learn

死锁问题排查

SQL Server 官方文档中推荐的查询是

1
2
3
4
5
6
7
8
9
10
SELECT xdr.value('@timestamp', 'datetime') AS [Date],
xdr.query('.') AS [Event_Data]
FROM (SELECT CAST([target_data] AS XML) AS Target_Data
FROM sys.dm_xe_session_targets AS xt
INNER JOIN sys.dm_xe_sessions AS xs ON xs.address = xt.event_session_address
WHERE xs.name = N'system_health'
AND xt.target_name = N'ring_buffer'
) AS XML_Data
CROSS APPLY Target_Data.nodes('RingBufferTarget/event[@name="xml_deadlock_report"]') AS XEventData(xdr)
ORDER BY [Date] DESC;

但是有可能查询不出来数据,参考:

sql server - Deadlock graph from Extended Events not showing - Stack Overflow

Query for deadlocks from system health empty results - Microsoft Q&A

第二种方法:

1
2
3
4
5
6
7
8
9
10
11
12
WITH
-- get trace folder path and append session name with wildcard (assumes base file name is same as session name)
all_trace_files AS (SELECT path + '\system_health*.xel' AS FileNamePattern
FROM sys.dm_os_server_diagnostics_log_configurations)
-- get xml_deadlock_report events from all system_health trace files
, deadlock_reports AS (SELECT CAST(event_data AS xml) AS deadlock_report_xml
FROM all_trace_files
CROSS APPLY sys.fn_xe_file_target_read_file(FileNamePattern, NULL, NULL, NULL) AS trace_records
WHERE trace_records.object_name LIKE 'xml_deadlock_report')
SELECT deadlock_report_xml.value('(/event/@timestamp)[1]', 'datetime2') AS UtcTimestamp
, deadlock_report_xml AS DeadlockReportXml
FROM deadlock_reports;

示例死锁XML:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
<event name="xml_deadlock_report" package="sqlserver" timestamp="2023-12-13T03:14:37.276Z">
<data name="xml_report">
<value>
<deadlock>
<victim-list>
<victimProcess id="process286f69bb848" />
</victim-list>
<process-list>
<process id="process286f69bb848" taskpriority="0" logused="332"
waitresource="KEY: 5:72057594072793088 (8194443284a0)" waittime="2411"
ownerId="5069955" transactionname="implicit_transaction"
lasttranstarted="2023-12-13T11:14:28.800" XDES="0x286d9734428" lockMode="X"
schedulerid="14" kpid="23144" status="suspended" spid="73" sbid="0" ecid="0"
priority="0" trancount="2" lastbatchstarted="2023-12-13T11:14:34.860"
lastbatchcompleted="2023-12-13T11:14:34.857"
lastattention="1900-01-01T00:00:00.857" clientapp="DataGrip"
hostname="DESKTOP-6I6KS5U" hostpid="0" loginname="sa"
isolationlevel="read committed (2)" xactid="5069955" currentdb="5"
currentdbname="testdb" lockTimeout="4294967295" clientoption1="671088672"
clientoption2="128058">
<executionStack>
<frame procname="adhoc" line="1" stmtstart="58" stmtend="180"
sqlhandle="0x020000004b4a582c63ed2d81362368a3ee68b97ad3e374570000000000000000000000000000000000000000">
unknown </frame>
<frame procname="adhoc" line="1" stmtend="112"
sqlhandle="0x02000000949b4e345c0730aab118b4ee71228d7c4b47e3fa0000000000000000000000000000000000000000">
unknown </frame>
</executionStack>
<inputbuf>
UPDATE "peng_test1"."ddl_test1" SET col1 = '2' WHERE id=1 </inputbuf>
</process>
<process id="process286f606bc28" taskpriority="0" logused="332"
waitresource="KEY: 5:72057594072793088 (61a06abd401c)" waittime="4594"
ownerId="5069937" transactionname="implicit_transaction"
lasttranstarted="2023-12-13T11:14:27.133" XDES="0x286dab84428" lockMode="X"
schedulerid="4" kpid="12460" status="suspended" spid="72" sbid="0" ecid="0"
priority="0" trancount="2" lastbatchstarted="2023-12-13T11:14:32.680"
lastbatchcompleted="2023-12-13T11:14:32.673"
lastattention="1900-01-01T00:00:00.673" clientapp="DataGrip"
hostname="DESKTOP-6I6KS5U" hostpid="0" loginname="sa"
isolationlevel="read committed (2)" xactid="5069937" currentdb="5"
currentdbname="testdb" lockTimeout="4294967295" clientoption1="671088672"
clientoption2="128058">
<executionStack>
<frame procname="adhoc" line="1" stmtstart="58" stmtend="180"
sqlhandle="0x020000004b4a582c63ed2d81362368a3ee68b97ad3e374570000000000000000000000000000000000000000">
unknown </frame>
<frame procname="adhoc" line="1" stmtend="112"
sqlhandle="0x020000009b0a9a298c276a4c196c029bfbdf7ca9c61fbc330000000000000000000000000000000000000000">
unknown </frame>
</executionStack>
<inputbuf>
UPDATE "peng_test1"."ddl_test1" SET col1 = '2' WHERE id=2 </inputbuf>
</process>
</process-list>
<resource-list>
<keylock hobtid="72057594072793088" dbid="5"
objectname="testdb.peng_test1.ddl_test1"
indexname="PK__ddl_test__3213E83F925CEC1B" id="lock286ea561080" mode="X"
associatedObjectId="72057594072793088">
<owner-list>
<owner id="process286f606bc28" mode="X" />
</owner-list>
<waiter-list>
<waiter id="process286f69bb848" mode="X" requestType="wait" />
</waiter-list>
</keylock>
<keylock hobtid="72057594072793088" dbid="5"
objectname="testdb.peng_test1.ddl_test1"
indexname="PK__ddl_test__3213E83F925CEC1B" id="lock286f5124580" mode="X"
associatedObjectId="72057594072793088">
<owner-list>
<owner id="process286f69bb848" mode="X" />
</owner-list>
<waiter-list>
<waiter id="process286f606bc28" mode="X" requestType="wait" />
</waiter-list>
</keylock>
</resource-list>
</deadlock>
</value>
</data>
</event>

资料:

死锁指南 - SQL Server | Microsoft Learn

How to use SQL Server Extended Events to parse Deadlock XML and generate statistical reports

Understanding the graphical representation of the SQL Server Deadlock Graph

死锁监控四步走,从此性能不再愁! - SQLServer - dbaplus社群:围绕Data、Blockchain、AiOps的企业级专业社群。技术大咖、原创干货,每天精品原创文章推送,每周线上技术分享,每月线下技术沙龙。

SQL Server扩展事件system_health会话总结 - 潇湘隐者 - 博客园

Use the system_health session - SQL Server | Microsoft Learn

SQL Server 使用扩展事件(Extended Event)监控死锁 - VicLW - 博客园

SQL SERVER - 谈死锁的监控分析解决思路 - 苏家小萝卜 - 博客园

常用系统表

sys.dm_os_waiting_tasks

sys.dm_os_waiting_tasks (Transact-SQL) - SQL Server | Microsoft Learn

返回等待资源相关的查询。

这张表的 resource_description 字段对于等待的资源的描述非常清晰。

关于 wait_type

常见的 wait_typeLCK_M_X,意思是

This wait type is when a thread is waiting to acquire an Exclusive lock on a resource and there is at least one other lock in an incompatible mode granted on the resource to a different thread.

——SQL Server LCK_M_X Wait

一个进程要获取独占锁,但是对应资源已经被加上了别的不兼容的锁,需要等待其他锁释放后才能加锁成功。

Troubleshoot blocking issues caused by compile locks - SQL Server | Microsoft Learn

SQL Server LCK_M_X Wait

sys.dm_tran_locks

sys.dm_tran_locks (Transact-SQL) - SQL Server | Microsoft Learn

参考资料

  1. sys.dm_tran_locks (Transact-SQL) - SQL Server | Microsoft Learn
  2. SQL Server死锁产生原因及解决办法 ._51CTO博客_oracle死锁的原因及解决方法
  3. tsql - SQL Server deadlock on the same table - Stack Overflow
  4. sql server - Can I be a deadlock victim if I’m not executing a query within a transaction? - Stack Overflow
  5. Deadlock due to Implicit Conversion | sqlindian - On Locks and Deadlocks
  6. SQL SERVER - How Can Deadlock Happen on Same Table? - SQL Authority with Pinal Dave
  7. Lock Partitioning | Microsoft Learn
  8. How can SQL Server 2016 deadlock with a pagelock on two different tables? - Database Administrators Stack Exchange
  9. SQL Server 中WITH (NOLOCK)浅析 - 潇湘隐者 - 博客园
  10. 获取有关运行 SQL Server 的 RDS 数据库实例死锁的信息
  11. 实战解决sql server数据库死锁案例以及sql server死锁Deadlock的一些总结_51CTO博客_sql server死锁原因
  12. SQL Server死锁产生原因及解决办法 ._51CTO博客_oracle死锁的原因及解决方法
  13. Tracing a SQL Server Deadlock
  14. Understand and resolve blocking problems - SQL Server | Microsoft Learn
  15. sys.dm_exec_sql_text (Transact-SQL) - SQL Server | Microsoft Learn【获取 Session 或 连接的 SQL,一般需要配合其他表,结合 CROSS APPLY 使用】
  16. sys.dm_exec_connections (Transact-SQL) - SQL Server | Microsoft Learn