zoukankan      html  css  js  c++  java
  • 数据库死锁问题 及 解决方法 <收藏>

     

          什么是数据库死锁

         每个使用关系型数据库的程序都可能遇到数据死锁的情况。理解什么是死锁之前先要了解锁定的概念:如果需要“修改”一条数据,首先数据库管理系统会在上面加锁,以保证在同一时间只有一个事务能进行修改操作。锁定(Locking)发生在当一个事务获得对某一资源的“锁”时,这时,其他的事务就不能更改这个资源了,这种机制的存在是为了保证数据一致性。

         多数情况下,可以认为如果一个资源被锁定,它总会在以后某个时间被释放。而死锁发生在当多个进程访问同一数据库时,其中每个进程拥有的锁都是其他进程所需的,由此造成每个进程都无法继续下去。简单的说,进程A等待进程B释放他的资源,B又等待A释放他的资源,这样就互相等待就形成死锁。

    • 导致数据库死锁的原因

         一般情况只发生锁超时,就是一个进程需要访问数据库表或者字段的时候,另外一个程序正在执行带锁的访问(比如修改数据),那么这个进程就会等待,当等了很久锁还没有解除的话就会锁超时,报告一个系统错误,拒绝执行相应的SQL操作。

         发生死锁的情况比较少,比如一个进程需要访问两个资源(数据库表或者字段),当获取一个资源的时候进程就对它执行锁定,然后等待下一个资源空闲,这时候如果另外一个进程也需要两个资源,而已经获得并锁定了第二个资源,那么就会死锁,因为当前进程锁定第一个资源等待第二个资源,而另外一个进程锁定了第二个资源等待第一个资源,两个进程都永远得不到满足。

    • 数据库死锁的解决方案
    use 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
  • 相关阅读:
    Java实现 蓝桥杯 算法训练 Number Challenge(暴力)
    Java实现 蓝桥杯 算法训练 Number Challenge(暴力)
    Java实现 蓝桥杯 算法训练 Number Challenge(暴力)
    Java实现 蓝桥杯 算法训练 Rotatable Number(暴力)
    Java实现 蓝桥杯 算法训练 Rotatable Number(暴力)
    Java实现 蓝桥杯 算法训练 Rotatable Number(暴力)
    Java实现 蓝桥杯 算法训练 猴子吃包子(暴力)
    Java实现 蓝桥杯 算法训练 猴子吃包子(暴力)
    Java实现 蓝桥杯 算法训练 猴子吃包子(暴力)
    Python位运算符
  • 原文地址:https://www.cnblogs.com/wenjl520/p/1517003.html
Copyright © 2011-2022 走看看