在实际引用当中,数据库阻塞和死锁在程序开发过程经常出现,下面通过介绍数据库阻塞和数据库死锁,并提供查看和解决阻塞和死锁的方法

数据库发生阻塞和死锁的现象:

一、数据库阻塞的现象:第一个连接占有资源没有释放,而第二个连接需要获取这个资源。如果第一个连接没有提交或者回滚,第二个连接会一直等待下去,直到第一个连接释放该资源为止。对于阻塞,数据库无法处理,所以对数据库操作要及时地提交或者回滚。
二、数据库死锁的现象:第一个连接占有资源没有释放,准备获取第二个连接所占用的资源,而第二个连接占有资源没有释放,准备获取第一个连接所占用的资源。这种互相占有对方需要获取的资源的现象叫做死锁。对于死锁,数据库处理方法:牺牲一个连接,保证另外一个连接成功执行。

例如,一个客户端应用程序线程有两个开放式连接。该线程异步启动事务并在第一个连接上发出查询。应用程序随后启动其它事务,在另一个连接上发出查询并等待结果。当 SQL   Server   返回其中一个连接的结果时,应用程序开始处理这些结果。应用程序就这样处理结果,直到生成结果的查询被另一个连接上执行的查询阻塞而导致再没有可用的结果为止。此时第一个连接阻塞,无限期等待处理更多的结果。第二个连接没有在锁上阻塞,但仍试图将结果返回给应用程序。然而,由于应用程序阻塞而在第一个连接上等待结果,第二个连接的结果将得不到处理。  

下面是查看并处理sql server 2000阻塞和死锁的方法:

USE [master]
 --p_lockinfo
 GO
 /****** Object:  StoredProcedure [dbo].[p_lockinfo]    Script Date: 07/03/2019 09:08:17 ******/
 SET ANSI_NULLS ON
 GO
 SET QUOTED_IDENTIFIER ON
 GO
 /* 
 在SQL Query Analyzer 如何执行:  
 exec master.dbo.p_lockinfo 0,0  ---显示死锁的进程,不显示正常的进程 
 exec master.dbo.p_lockinfo 1,0  ---杀死死锁的进程,不显示正常的进程 
 */
  
 /* 在master数据库中建立如下的procedure,并赋予某些用户执行权限 */
 ALTER proc  [dbo].[p_lockinfo] 
     @kill_lock_spid bit=0,        --是否杀掉死锁的进程,1 杀掉, 0 仅显示 
     @show_spid_if_nolock bit=1    --如果没有死锁的进程,是否显示正常进程信息,1 显示,0 不显示 
 as
     declare @count int,@s nvarchar(4000),@i int 
     select id=identity(int,1,1),标志, 
         进程ID=spid,线程ID=kpid,块进程ID=blocked,数据库ID=dbid, 
         数据库名=db_name(dbid),用户ID=uid,用户名=loginame,累计CPU时间=cpu, 
         登陆时间=login_time,打开事务数=open_tran, 进程状态=status, 
         工作站名=hostname,应用程序名=program_name,工作站进程ID=hostprocess, 
         域名=nt_domain,网卡地址=net_address 
     into #t from( 
         select 标志='死锁的进程', 
             spid,kpid,a.blocked,dbid,uid,loginame,cpu,login_time,open_tran, 
             status,hostname,program_name,hostprocess,nt_domain,net_address, 
             s1=a.spid,s2=0 
         from master..sysprocesses a join ( 
         select blocked from master..sysprocesses group by blocked 
         )b on a.spid=b.blocked where a.blocked=0 
      union all 
      select '|_牺牲品_>', 
         spid,kpid,blocked,dbid,uid,loginame,cpu,login_time,open_tran, 
         status,hostname,program_name,hostprocess,nt_domain,net_address, 
         s1=blocked,s2=1 
      from master..sysprocesses a where blocked<>0 
     )a order by s1,s2
      
     select @count=@@rowcount,@i=1
     if @count=0 and @show_spid_if_nolock=1 
     begin 
         insert #t 
         select 标志='正常的进程', 
             spid,kpid,blocked,dbid,db_name(dbid),uid,loginame,cpu,login_time, 
             open_tran,status,hostname,program_name,hostprocess,nt_domain,net_address 
         from master..sysprocesses 
         set @count=@@rowcount 
     end 
      
     if @count>0 
     begin 
         create table #t1(id int identity(1,1),a nvarchar(30),b Int,EventInfo nvarchar(3255)) 
         if @kill_lock_spid=1 
         begin 
             declare @spid varchar(10),@标志 varchar(10) 
             while @i<=@count 
             begin 
                 select @spid=进程ID,@标志=标志 from #t where id=@i 
                 insert #t1 exec('dbcc inputbuffer('+@spid+')') 
                 if @标志='死锁的进程' exec('kill'+@spid) 
                 set @i=@i+1 
             end 
         end 
         else 
         while @i<=@count 
         begin 
            select @s='dbcc inputbuffer('+cast(进程ID as varchar(1250))+')' from #t where id=@i 
            insert #t1 exec(@s) 
            set @i=@i+1 
         end 
         select 进程的SQL语句=b.EventInfo ,a.*
         from #t a join #t1 b on a.id=b.id 
     end set nocount off
go