SQLServer 的死锁问题,真的是搞数据库开发绕不开的一道坎。任务卡着不动,明明没写错语句,就是执行不了,十有八九就是死锁了。死锁的那四个条件——互斥、求保持、非剥夺、循环等待——说起来拗口,其实就是“我拿着你的资源,你拿着我的资源,谁也不让步”。
SQL Server 的 sp_who和sp_lock两个存储过程,排查死锁挺好用的。配合着dbcc inputbuffer
、object_name()
之类的命令,你能快速知道哪个会话锁了什么,卡在哪条 SQL 语句上。嗯,效率还是蛮高的。
建议你建两个临时表#Who
和#Lock
,分别存一下当前数据库的会话和锁信息,用sp_who
和sp_lock
填进去,一查就能看到哪两个任务“死掐”上了。这招我自己用得挺多,简单粗暴,响应也快。
再高级点,可以用sys.dm_os_waiting_tasks和sys.dm_exec_requests这些系统视图,信息更详细,但对新手稍微有点绕。如果你写的是长事务,别忘了加点超时控制,不然锁一旦打住,杀掉进程也容易出错。
实在不行,用ROLLBACK
或者KILL
强行释放锁,这就要小心了,一不小心把数据搞没,线上环境一定要慎重。如果你想做点死锁实验验证思路,可以看看这篇《SQLServer 数据库死锁原理实验》,思路还挺清晰的。
,排查死锁不是靠运气,靠的是工具熟练+经验积累。如果你老是遇到死锁,先别急着优化 SQL,先把排查的套路走一遍,说不定哪次你就秒定位了。