多数情况下,可以认为如果一个资源被锁定,它总会在以后某个时间被释放。而死锁发生在当多个进程访问同一数据库时,其中每个进程拥有的锁都是其他进程所需的,由此造成每个进程都无法继续下去。简单的说,进程A等待进程B释放他的资源,B又等待A释放他的资源,这样就互相等待就形成死锁。
- 导致数据库死锁的原因
一般情况只发生锁超时,就是一个进程需要访问数据库表或者字段的时候,另外一个程序正在执行带锁的访问(比如修改数据),那么这个进程就会等待,当等了很久锁还没有解除的话就会锁超时,报告一个系统错误,拒绝执行相应的SQL操作。
发生死锁的情况比较少,比如一个进程需要访问两个资源(数据库表或者字段),当获取一个资源的时候进程就对它执行锁定,然后等待下一个资源空闲,这时候如果另外一个进程也需要两个资源,而已经获得并锁定了第二个资源,那么就会死锁,因为当前进程锁定第一个资源等待第二个资源,而另外一个进程锁定了第二个资源等待第一个资源,两个进程都永远得不到满足。
- 数据库死锁的解决方案

1use master --必须在master数据库中创建
2go
3
4if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[p_lockinfo]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
5drop procedure [dbo].[p_lockinfo]
6GO
7
8/**//*--处理死锁
9
10 查看当前进程,或死锁进程,并能自动杀掉死进程
11
12 因为是针对死锁的,所以如果有死锁进程,只能查看死锁进程
13 当然,你可以通过参数控制,不管有没有死锁,都只查看死锁进程
14
15 感谢: caiyunxia,jiangopen 两位提供的参考信息
16
17--邹建 2004.04(引用请保留此信息)--*/
18
19/**//*--调用示例
20
21 exec p_lockinfo
22--*/
23create proc p_lockinfo
24@kill_lock_spid bit=1, --是否杀掉死锁的进程,1 杀掉, 0 仅显示
25@show_spid_if_nolock bit=1 --如果没有死锁的进程,是否显示正常进程信息,1 显示,0 不显示
26as
27set nocount on
28declare @count int,@s nvarchar(1000),@i int
29select id=identity(int,1,1),标志,
30 进程ID=spid,线程ID=kpid,块进程ID=blocked,数据库ID=dbid,
31 数据库名=db_name(dbid),用户ID=uid,用户名=loginame,累计CPU时间=cpu,
32 登陆时间=login_time,打开事务数=open_tran, 进程状态=status,
33 工作站名=hostname,应用程序名=program_name,工作站进程ID=hostprocess,
34 域名=nt_domain,网卡地址=net_address
35into #t from(
36 select 标志='死锁的进程',
37 spid,kpid,a.blocked,dbid,uid,loginame,cpu,login_time,open_tran,
38 status,hostname,program_name,hostprocess,nt_domain,net_address,
39 s1=a.spid,s2=0
40 from master..sysprocesses a join (
41 select blocked from master..sysprocesses group by blocked
42 )b on a.spid=b.blocked where a.blocked=0
43 union all
44 select '|_牺牲品_>',
45 spid,kpid,blocked,dbid,uid,loginame,cpu,login_time,open_tran,
46 status,hostname,program_name,hostprocess,nt_domain,net_address,
47 s1=blocked,s2=1
48 from master..sysprocesses a where blocked<>0
49)a order by s1,s2
50
51select @count=@@rowcount,@i=1
52
53if @count=0 and @show_spid_if_nolock=1
54begin
55 insert #t
56 select 标志='正常的进程',
57 spid,kpid,blocked,dbid,db_name(dbid),uid,loginame,cpu,login_time,
58 open_tran,status,hostname,program_name,hostprocess,nt_domain,net_address
59 from master..sysprocesses
60 set @count=@@rowcount
61end
62
63if @count>0
64begin
65 create table #t1(id int identity(1,1),a nvarchar(30),b Int,EventInfo nvarchar(255))
66 if @kill_lock_spid=1
67 begin
68 declare @spid varchar(10),@标志 varchar(10)
69 while @i<=@count
70 begin
71 select @spid=进程ID,@标志=标志 from #t where id=@i
72 insert #t1 exec('dbcc inputbuffer('+@spid+')')
73 if @@rowcount=0 insert #t1(a) values(null)
74 if @标志='死锁的进程' exec('kill '+@spid)
75 set @i=@i+1
76 end
77 end
78 else
79 while @i<=@count
80 begin
81 select @s='dbcc inputbuffer('+cast(进程ID as varchar)+')' from #t where id=@i
82 insert #t1 exec(@s)
83 if @@rowcount=0 insert #t1(a) values(null)
84 set @i=@i+1
85 end
86 select a.*,进程的SQL语句=b.EventInfo
87 from #t a join #t1 b on a.id=b.id
88 order by 进程ID
89end
90set nocount off
91go
92
2go
3
4if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[p_lockinfo]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
5drop procedure [dbo].[p_lockinfo]
6GO
7
8/**//*--处理死锁
9
10 查看当前进程,或死锁进程,并能自动杀掉死进程
11
12 因为是针对死锁的,所以如果有死锁进程,只能查看死锁进程
13 当然,你可以通过参数控制,不管有没有死锁,都只查看死锁进程
14
15 感谢: caiyunxia,jiangopen 两位提供的参考信息
16
17--邹建 2004.04(引用请保留此信息)--*/
18
19/**//*--调用示例
20
21 exec p_lockinfo
22--*/
23create proc p_lockinfo
24@kill_lock_spid bit=1, --是否杀掉死锁的进程,1 杀掉, 0 仅显示
25@show_spid_if_nolock bit=1 --如果没有死锁的进程,是否显示正常进程信息,1 显示,0 不显示
26as
27set nocount on
28declare @count int,@s nvarchar(1000),@i int
29select id=identity(int,1,1),标志,
30 进程ID=spid,线程ID=kpid,块进程ID=blocked,数据库ID=dbid,
31 数据库名=db_name(dbid),用户ID=uid,用户名=loginame,累计CPU时间=cpu,
32 登陆时间=login_time,打开事务数=open_tran, 进程状态=status,
33 工作站名=hostname,应用程序名=program_name,工作站进程ID=hostprocess,
34 域名=nt_domain,网卡地址=net_address
35into #t from(
36 select 标志='死锁的进程',
37 spid,kpid,a.blocked,dbid,uid,loginame,cpu,login_time,open_tran,
38 status,hostname,program_name,hostprocess,nt_domain,net_address,
39 s1=a.spid,s2=0
40 from master..sysprocesses a join (
41 select blocked from master..sysprocesses group by blocked
42 )b on a.spid=b.blocked where a.blocked=0
43 union all
44 select '|_牺牲品_>',
45 spid,kpid,blocked,dbid,uid,loginame,cpu,login_time,open_tran,
46 status,hostname,program_name,hostprocess,nt_domain,net_address,
47 s1=blocked,s2=1
48 from master..sysprocesses a where blocked<>0
49)a order by s1,s2
50
51select @count=@@rowcount,@i=1
52
53if @count=0 and @show_spid_if_nolock=1
54begin
55 insert #t
56 select 标志='正常的进程',
57 spid,kpid,blocked,dbid,db_name(dbid),uid,loginame,cpu,login_time,
58 open_tran,status,hostname,program_name,hostprocess,nt_domain,net_address
59 from master..sysprocesses
60 set @count=@@rowcount
61end
62
63if @count>0
64begin
65 create table #t1(id int identity(1,1),a nvarchar(30),b Int,EventInfo nvarchar(255))
66 if @kill_lock_spid=1
67 begin
68 declare @spid varchar(10),@标志 varchar(10)
69 while @i<=@count
70 begin
71 select @spid=进程ID,@标志=标志 from #t where id=@i
72 insert #t1 exec('dbcc inputbuffer('+@spid+')')
73 if @@rowcount=0 insert #t1(a) values(null)
74 if @标志='死锁的进程' exec('kill '+@spid)
75 set @i=@i+1
76 end
77 end
78 else
79 while @i<=@count
80 begin
81 select @s='dbcc inputbuffer('+cast(进程ID as varchar)+')' from #t where id=@i
82 insert #t1 exec(@s)
83 if @@rowcount=0 insert #t1(a) values(null)
84 set @i=@i+1
85 end
86 select a.*,进程的SQL语句=b.EventInfo
87 from #t a join #t1 b on a.id=b.id
88 order by 进程ID
89end
90set nocount off
91go
92
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理