在 SQL Server 中,锁是并发控制的关键机制,确保数据的完整性和一致性。然而,在高并发环境下,锁可能导致阻塞甚至死锁,影响系统性能。因此,理解 SQL Server 的锁机制,并掌握如何定位和解决锁问题,是 DBA 和开发人员的重要技能。
方法 1:查询被锁表和进程
SELECT
l.request_session_id AS session_id, -- 进程 ID
r.blocking_session_id AS blocking_session_id, -- 阻塞该进程的会话
o.name AS table_name, -- 被锁的表
l.resource_type, -- 资源类型(OBJECT、PAGE、KEY等)
l.request_mode, -- 锁模式(S 共享锁, X 排它锁等)
l.request_status -- 锁状态(GRANT 已授予, WAIT 等待等)
FROM sys.dm_tran_locks l
JOIN sys.partitions p ON l.resource_associated_entity_id = p.hobt_id
JOIN sys.objects o ON p.object_id = o.object_id
LEFT JOIN sys.dm_exec_requests r ON l.request_session_id = r.session_id
ORDER BY l.request_session_id;
这个查询能获取被锁住的表、锁定的进程 ID、阻塞的进程 ID、锁模式和状态。
方法 2:查看当前所有锁
如果你只想查看当前所有锁的状态:
SELECT
request_session_id AS session_id,
resource_type,
resource_description,
request_mode,
request_status
FROM sys.dm_tran_locks
ORDER BY request_session_id;
这个查询列出了 所有当前锁,包括 表锁、页锁、键锁 等。
方法 3:查找阻塞进程
SELECT
spid,
blocked,
waittype,
lastwaittype,
waitresource
FROM sys.sysprocesses
WHERE blocked <> 0;
方法 4:查看锁的 SQL 语句
SELECT
r.session_id,
r.blocking_session_id,
t.text AS sql_text,
o.name AS locked_table,
l.resource_type,
l.request_mode
FROM sys.dm_tran_locks AS l
JOIN sys.partitions AS p ON l.resource_associated_entity_id = p.hobt_id
JOIN sys.objects AS o ON p.object_id = o.object_id
JOIN sys.dm_exec_requests AS r ON l.request_session_id = r.session_id
CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) AS t;
方法 5:使用 sp_who2
快速查看进程
EXEC sp_who2;
方法 6:终止锁住的进程
如果确认某个进程占用了锁,可以终止它:
KILL <session_id>;
总结
方法 | 作用 |
---|---|
sys.dm_tran_locks + sys.objects | 查找被锁住的表及进程 |
sys.dm_exec_requests + sys.dm_exec_sql_text | 查看锁住表的 SQL 语句 |
sys.sysprocesses | 查找阻塞的进程 |
sp_who2 | 快速查看进程及阻塞情况 |
KILL <session_id> | 终止锁住的进程 |
NOLOCK 及 READ COMMITTED SNAPSHOT | 降低锁争用 |
索引优化 + 批量事务提交 | 降低锁升级风险 |
掌握 SQL Server 的锁机制,并结合监控和优化策略,可以有效减少表锁带来的性能问题,提高数据库的并发处理能力。