参考: 微软官方api
问题日志描述
事务(进程 ID 140)与另一个进程被死锁在 锁 | 通信缓冲区 资源上,并且已被选作死锁牺牲品。请重新运行该事务
at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(SQLServerException.java:196)
at com.microsoft.sqlserver.jdbc.SQLServerStatement.getNextResult(SQLServerStatement.java:1454)
at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.doExecutePreparedStatement(SQLServerPreparedStatement.java:388)
at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement$PrepStmtExecCmd.doExecute(SQLServerPreparedStatement.java:338)
at com.microsoft.sqlserver.jdbc.TDSCommand.ex
问题排查
1、查询哪些进程导致的死锁
select request_session_id spid, object_name( resource_associated_entity_id )
tablename from sys.dm_tran_locks where resource_type = 'object'
2、查询死锁的原因
CREATE Table #Who(spid int,
ecid int,
status nvarchar(50),
loginname nvarchar(50),
hostname nvarchar(50),
blk int,
dbname nvarchar(50),
cmd nvarchar(50),
request_ID int);
CREATE Table #Lock(spid int,
dpid int,
objid int,
indld int,
[Type] nvarchar(20),
Resource nvarchar(50),
Mode nvarchar(10),
Status nvarchar(10));
INSERT INTO #Who EXEC sp_who active
--看哪个引起的阻塞,blk \
INSERT INTO #Lock EXEC sp_lock
--看锁住了那个资源id,objid
DECLARE @DBName nvarchar(20);
SET @DBName='czggzy'
SELECT #Who.* FROM #Who WHERE dbname=@DBName
SELECT #Lock.* FROM #Lock
JOIN #Who
ON #Who.spid=#Lock.spid
AND dbname=@DBName;
--最后发送到SQL Server的语句
DECLARE crsr Cursor FOR SELECT blk FROM #Who WHERE dbname = @DBName AND blk <> 0;
DECLARE @blk int;
open crsr;
FETCH NEXT FROM crsr INTO @blk;
WHILE (@@FETCH_STATUS = 0)BEGIN;
dbcc inputbuffer(@blk);
FETCH NEXT FROM crsr INTO @blk;
END;
close crsr;
DEALLOCATE crsr;
--锁定的资源
SELECT #Who.spid,
hostname,
objid,
[type],
mode,
object_name(objid) as objName FROM #Lock JOIN #Who ON #Who.spid =#Lock.spid AND dbname = @DBName WHERE objid <> 0;
DROP Table #Who;
DROP Table #Lock;
问题处理
杀死进程
kill spid --杀死进程
这篇文章详细介绍了排查SQL Server死锁问题的方法,并提供了实用的脚本和步骤,非常值得学习。以下是对此篇文章的一些分析与建议:
优点分析
sys.dm_tran_locks
视图、临时表和存储过程(如sp_who
和sp_lock
),作者提供了一套完整的死锁排查方法,具有很好的可操作性。KILL
命令结束进程,快速解决死锁问题,适用于紧急情况。核心理念鼓励
文章的核心在于通过系统视图和存储过程收集必要信息,分析锁定状态并解决问题。这种方法体现了DBA工作中注重数据、逐步排查的精神,值得肯定。
改进建议
1. 补充死锁原因分析
在处理完问题后,可以进一步探讨为何会出现死锁现象。例如:
2. 提供预防措施
除了解决已出现的问题,还可以加入一些预防性的建议,比如:
3. 优化脚本可读性
将复杂的SQL脚本拆分成更小的部分,并添加注释,帮助读者理解每一步的作用。例如:
这样的注释可以让读者更容易跟上思路。
4. 增加更多诊断工具介绍
除了
sp_lock
和sys.dm_tran_locks
,还可以提及其它有用的DMV(动态管理视图),如:sys.dm_os_wait_stats
:查看等待统计信息。sys.dm_exec_requests
:获取请求的详细信息。5. 补充死锁图形分析
SQL Server提供了生成死锁图形的功能(使用
ALTER DATABASE SET DEADLOCK_PRIORITY
或跟踪标志1222),这可以帮助更直观地理解死锁发生的原因。增加这部分内容可以让文章更加全面。6. 加入实际案例分析
通过一个具体的案例,详细展示从排查到解决的全过程,并说明每一步的思考过程和结论,这样能够更好地帮助读者理解和应用所学知识。
总结
这篇文章为SQL Server死锁问题提供了一套实用的排查方法,内容详实且步骤清晰。建议在后续版本中补充更多关于原因分析、预防措施以及诊断工具的内容,使其更加完善。期待看到作者未来分享更多关于数据库管理和优化的实战经验!
首先,感谢您分享了这篇关于SQL Server死锁问题排查的博客。从您的文章中,我了解到了如何通过查询进程、分析死锁原因和处理死锁的方法。对于遇到类似问题的读者来说,这是非常有帮助的。在这里,我会对您的文章提一些建议和反馈。
首先,您提到了使用Microsoft官方API文档作为参考,这是一个很好的做法,因为官方文档通常是最权威和最准确的。同时,您还提供了日志描述,让读者更加清楚地了解问题的场景。
在问题排查部分,您给出了通过SQL查询来查找导致死锁的进程和原因的方法。这些查询语句非常实用,能够帮助读者快速定位问题。但是,这部分可以再加上一些解释,以帮助读者理解每个查询语句的作用和结果。例如,您可以解释一下
sys.dm_tran_locks
和sp_who
等系统视图或存储过程的作用。在问题处理部分,您给出了杀死进程的方法。这是一个简单有效的解决方案。然而,这里可以再补充一些其他的处理方法,以供读者参考。例如,优化SQL语句、调整事务隔离级别等。
此外,您的文章结构清晰,代码格式整齐,这使得读者更容易理解和学习。但是,建议您在文章中加入一些小标题,以便读者更好地把握文章的结构。同时,可以适当添加一些空行,让文章看起来更加清爽。
总的来说,这是一篇非常实用的博客,对于解决SQL Server死锁问题有很大的帮助。希望您能继续分享更多的经验和知识,为读者提供更多的帮助。再次感谢您的分享!