SQL Server2000中死锁经验总结 <转>

摘要:
虽然死锁无法完全避免,但死锁的数量可以最小化。使用低隔离级别。例如,如果两个并发事务获得了Supplier表上的锁,然后又获得了Part表上的锁定,那么在其中一个事务完成之前,另一个事务将在Supplier表中被阻止。这将降低系统的吞吐量,因为只有当事务提交或回滚时,事务持有的任何锁才会被释放。此时,我们可以使用以下存储过程来检测导致死锁的进程和SQL语句。SQL Server自己的系统存储过程sp_Who和sp_Lock也可以用于查找阻塞和死锁,但它不像这里描述的方法那样容易使用。

虽然不能完全避免死锁,但可以使死锁的数量减至最少。将死锁减至最少可以增加事务的吞吐量并减少系统开销,因为只有很少的事务:



  • 回滚,而回滚会取消事务执行的所有工作。
  • 由于死锁时回滚而由应用程序重新提交。

下列方法有助于最大限度地降低死锁:



  • 按同一顺序访问对象。
  • 避免事务中的用户交互。
  • 保持事务简短并在一个批处理中。
  • 使用低隔离级别。
  • 使用绑定连接。

按同一顺序访问对象


如果所有并发事务按同一顺序访问对象,则发生死锁的可能性会降低。例如,如果两个并发事务获得 Supplier 表上的锁,然后获得 Part 表上的锁,则在其中一个事务完成之前,另一个事务被阻塞在 Supplier 表上。第一个事务提交或回滚后,第二个事务继续进行。不发生死锁。将存储过程用于所有的数据修改可以标准化访问对象的顺序。

避免事务中的用户交互


避免编写包含用户交互的事务,因为运行没有用户交互的批处理的速度要远远快于用户手动响应查询的速度,例如答复应用程序请求参数的提示。例如,如果事务正在等待用户输入,而用户去吃午餐了或者甚至回家过周末了,则用户将此事务挂起使之不能完成。这样将降低系统的吞吐量,因为事务持有的任何锁只有在事务提交或回滚时才会释放。即使不出现死锁的情况,访问同一资源的其它事务也会被阻塞,等待该事务完成。


保持事务简短并在一个批处理中


在同一数据库中并发执行多个需要长时间运行的事务时通常发生死锁。事务运行时间越长,其持有排它锁或更新锁的时间也就越长,从而堵塞了其它活动并可能导致死锁。


保持事务在一个批处理中,可以最小化事务的网络通信往返量,减少完成事务可能的延迟并释放锁。


使用低隔离级别


确定事务是否能在更低的隔离级别上运行。执行提交读允许事务读取另一个事务已读取(未修改)的数据,而不必等待第一个事务完成。使用较低的隔离级别(例如提交读)而不使用较高的隔离级别(例如可串行读)可以缩短持有共享锁的时间,从而降低了锁定争夺。


使用绑定连接


使用绑定连接使同一应用程序所打开的两个或多个连接可以相互合作。次级连接所获得的任何锁可以象由主连接获得的锁那样持有,反之亦然,因此不会相互阻塞


检测死锁


如果发生死锁了,我们怎么去检测具体发生死锁的是哪条SQL语句或存储过程?


这时我们可以使用以下存储过程来检测,就可以查出引起死锁的进程和SQL语句。SQL Server自带的系统存储过程sp_who和sp_lock也可以用来查找阻塞和死锁, 但没有这里介绍的方法好用。

 


SQL Server2000中死锁经验总结 <转>第1张use master
SQL Server2000中死锁经验总结 <转>第1张
go
SQL Server2000中死锁经验总结 <转>第1张
create procedure sp_who_lock
SQL Server2000中死锁经验总结 <转>第1张
as
SQL Server2000中死锁经验总结 <转>第1张
begin
SQL Server2000中死锁经验总结 <转>第1张
declare @spid int,@bl int,
SQL Server2000中死锁经验总结 <转>第1张 
@intTransactionCountOnEntry  int,
SQL Server2000中死锁经验总结 <转>第1张        
@intRowcount    int,
SQL Server2000中死锁经验总结 <转>第1张        
@intCountProperties   int,
SQL Server2000中死锁经验总结 <转>第1张        
@intCounter    int
SQL Server2000中死锁经验总结 <转>第1张
SQL Server2000中死锁经验总结 <转>第1张 
create table #tmp_lock_who (
SQL Server2000中死锁经验总结 <转>第1张 id 
int identity(1,1),
SQL Server2000中死锁经验总结 <转>第1张 spid 
smallint,
SQL Server2000中死锁经验总结 <转>第1张 bl 
smallint)
SQL Server2000中死锁经验总结 <转>第1张 
SQL Server2000中死锁经验总结 <转>第1张 
IF @@ERROR<>0 RETURN @@ERROR
SQL Server2000中死锁经验总结 &lt;转&gt;第1张 
SQL Server2000中死锁经验总结 &lt;转&gt;第1张 
insert into #tmp_lock_who(spid,bl) select  0 ,blocked
SQL Server2000中死锁经验总结 &lt;转&gt;第1张   
from (select * from sysprocesses where  blocked>0 ) a 
SQL Server2000中死锁经验总结 &lt;转&gt;第1张   
where not exists(select * from (select * from sysprocesses where  blocked>0 ) b 
SQL Server2000中死锁经验总结 &lt;转&gt;第1张   
where a.blocked=spid)
SQL Server2000中死锁经验总结 &lt;转&gt;第1张   
union select spid,blocked from sysprocesses where  blocked>0
SQL Server2000中死锁经验总结 &lt;转&gt;第1张
SQL Server2000中死锁经验总结 &lt;转&gt;第1张 
IF @@ERROR<>0 RETURN @@ERROR 
SQL Server2000中死锁经验总结 &lt;转&gt;第1张  
SQL Server2000中死锁经验总结 &lt;转&gt;第1张
-- 找到临时表的记录数
SQL Server2000中死锁经验总结 &lt;转&gt;第1张
 select  @intCountProperties = Count(*),@intCounter = 1
SQL Server2000中死锁经验总结 &lt;转&gt;第1张 
from #tmp_lock_who
SQL Server2000中死锁经验总结 &lt;转&gt;第1张 
SQL Server2000中死锁经验总结 &lt;转&gt;第1张 
IF @@ERROR<>0 RETURN @@ERROR 
SQL Server2000中死锁经验总结 &lt;转&gt;第1张 
SQL Server2000中死锁经验总结 &lt;转&gt;第1张 
if @intCountProperties=0
SQL Server2000中死锁经验总结 &lt;转&gt;第1张  
select '现在没有阻塞和死锁信息' as message
SQL Server2000中死锁经验总结 &lt;转&gt;第1张
SQL Server2000中死锁经验总结 &lt;转&gt;第1张
-- 循环开始
SQL Server2000中死锁经验总结 &lt;转&gt;第1张
while @intCounter <= @intCountProperties
SQL Server2000中死锁经验总结 &lt;转&gt;第1张
begin
SQL Server2000中死锁经验总结 &lt;转&gt;第1张
-- 取第一条记录
SQL Server2000中死锁经验总结 &lt;转&gt;第1张
  select  @spid = spid,@bl = bl
SQL Server2000中死锁经验总结 &lt;转&gt;第1张  
from #tmp_lock_who where Id = @intCounter 
SQL Server2000中死锁经验总结 &lt;转&gt;第1张 
begin
SQL Server2000中死锁经验总结 &lt;转&gt;第1张  
if @spid =0 
SQL Server2000中死锁经验总结 &lt;转&gt;第1张            
select '引起数据库死锁的是: '+ CAST(@bl AS VARCHAR(10)) + '进程号,其执行的SQL语法如下'
SQL Server2000中死锁经验总结 &lt;转&gt;第1张 
else
SQL Server2000中死锁经验总结 &lt;转&gt;第1张            
select '进程号SPID:'+ CAST(@spid AS VARCHAR(10))+ '' + '进程号SPID:'+ CAST(@bl AS VARCHAR(10)) +'阻塞,其当前进程执行的SQL语法如下'
SQL Server2000中死锁经验总结 &lt;转&gt;第1张 
DBCC INPUTBUFFER (@bl )
SQL Server2000中死锁经验总结 &lt;转&gt;第1张 
end 
SQL Server2000中死锁经验总结 &lt;转&gt;第1张
SQL Server2000中死锁经验总结 &lt;转&gt;第1张
-- 循环指针下移
SQL Server2000中死锁经验总结 &lt;转&gt;第1张
 set @intCounter = @intCounter + 1
SQL Server2000中死锁经验总结 &lt;转&gt;第1张
end
SQL Server2000中死锁经验总结 &lt;转&gt;第1张
SQL Server2000中死锁经验总结 &lt;转&gt;第1张
drop table #tmp_lock_who
SQL Server2000中死锁经验总结 &lt;转&gt;第1张
SQL Server2000中死锁经验总结 &lt;转&gt;第1张
return 0
SQL Server2000中死锁经验总结 &lt;转&gt;第1张
end
SQL Server2000中死锁经验总结 &lt;转&gt;第1张

 


杀死锁和进程


如何去手动的杀死进程和锁?最简单的办法,重新启动服务。但是这里要介绍一个存储过程,通过显式的调用,可以杀死进程和锁。



SQL Server2000中死锁经验总结 &lt;转&gt;第1张use master
SQL Server2000中死锁经验总结 &lt;转&gt;第1张
go
SQL Server2000中死锁经验总结 &lt;转&gt;第1张
SQL Server2000中死锁经验总结 &lt;转&gt;第1张
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[p_killspid]'and OBJECTPROPERTY(id, N'IsProcedure'= 1)
SQL Server2000中死锁经验总结 &lt;转&gt;第1张
drop procedure [dbo].[p_killspid]
SQL Server2000中死锁经验总结 &lt;转&gt;第1张
GO
SQL Server2000中死锁经验总结 &lt;转&gt;第1张
SQL Server2000中死锁经验总结 &lt;转&gt;第1张
create proc p_killspid
SQL Server2000中死锁经验总结 &lt;转&gt;第1张
@dbname varchar(200)    --要关闭进程的数据库名
SQL Server2000中死锁经验总结 &lt;转&gt;第1张
as  
SQL Server2000中死锁经验总结 &lt;转&gt;第1张    
declare @sql  nvarchar(500)  
SQL Server2000中死锁经验总结 &lt;转&gt;第1张    
declare @spid nvarchar(20)
SQL Server2000中死锁经验总结 &lt;转&gt;第1张
SQL Server2000中死锁经验总结 &lt;转&gt;第1张    
declare #tb cursor for
SQL Server2000中死锁经验总结 &lt;转&gt;第1张        
select spid=cast(spid as varchar(20)) from master..sysprocesses where dbid=db_id(@dbname)
SQL Server2000中死锁经验总结 &lt;转&gt;第1张    
open #tb
SQL Server2000中死锁经验总结 &lt;转&gt;第1张    
fetch next from #tb into @spid
SQL Server2000中死锁经验总结 &lt;转&gt;第1张    
while @@fetch_status=0
SQL Server2000中死锁经验总结 &lt;转&gt;第1张    
begin  
SQL Server2000中死锁经验总结 &lt;转&gt;第1张        
exec('kill '+@spid)
SQL Server2000中死锁经验总结 &lt;转&gt;第1张        
fetch next from #tb into @spid
SQL Server2000中死锁经验总结 &lt;转&gt;第1张    
end  
SQL Server2000中死锁经验总结 &lt;转&gt;第1张    
close #tb
SQL Server2000中死锁经验总结 &lt;转&gt;第1张    
deallocate #tb
SQL Server2000中死锁经验总结 &lt;转&gt;第1张
go
SQL Server2000中死锁经验总结 &lt;转&gt;第1张
SQL Server2000中死锁经验总结 &lt;转&gt;第1张
--用法  
SQL Server2000中死锁经验总结 &lt;转&gt;第1张
exec p_killspid  'newdbpy'
SQL Server2000中死锁经验总结 &lt;转&gt;第1张

 


查看锁信息


如何查看系统中所有锁的详细信息?在企业管理管理器中,我们可以看到一些进程和锁的信息,这里介绍另外一种方法。



SQL Server2000中死锁经验总结 &lt;转&gt;第1张--查看锁信息
SQL Server2000中死锁经验总结 &lt;转&gt;第1张
create table #t(req_spid int,obj_name sysname)
SQL Server2000中死锁经验总结 &lt;转&gt;第1张
SQL Server2000中死锁经验总结 &lt;转&gt;第1张
declare @s nvarchar(4000)
SQL Server2000中死锁经验总结 &lt;转&gt;第1张    ,
@rid int,@dbname sysname,@id int,@objname sysname
SQL Server2000中死锁经验总结 &lt;转&gt;第1张
SQL Server2000中死锁经验总结 &lt;转&gt;第1张
declare tb cursor for 
SQL Server2000中死锁经验总结 &lt;转&gt;第1张    
select distinct req_spid,dbname=db_name(rsc_dbid),rsc_objid
SQL Server2000中死锁经验总结 &lt;转&gt;第1张    
from master..syslockinfo where rsc_type in(4,5)
SQL Server2000中死锁经验总结 &lt;转&gt;第1张
open tb
SQL Server2000中死锁经验总结 &lt;转&gt;第1张
fetch next from tb into @rid,@dbname,@id
SQL Server2000中死锁经验总结 &lt;转&gt;第1张
while @@fetch_status=0
SQL Server2000中死锁经验总结 &lt;转&gt;第1张
begin
SQL Server2000中死锁经验总结 &lt;转&gt;第1张    
set @s='select @objname=name from ['+@dbname+']..sysobjects where id=@id'
SQL Server2000中死锁经验总结 &lt;转&gt;第1张    
exec sp_executesql @s,N'@objname sysname out,@id int',@objname out,@id
SQL Server2000中死锁经验总结 &lt;转&gt;第1张    
insert into #t values(@rid,@objname)
SQL Server2000中死锁经验总结 &lt;转&gt;第1张    
fetch next from tb into @rid,@dbname,@id
SQL Server2000中死锁经验总结 &lt;转&gt;第1张
end
SQL Server2000中死锁经验总结 &lt;转&gt;第1张
close tb
SQL Server2000中死锁经验总结 &lt;转&gt;第1张
deallocate tb
SQL Server2000中死锁经验总结 &lt;转&gt;第1张
SQL Server2000中死锁经验总结 &lt;转&gt;第1张
select 进程id=a.req_spid
SQL Server2000中死锁经验总结 &lt;转&gt;第1张    ,数据库
=db_name(rsc_dbid)
SQL Server2000中死锁经验总结 &lt;转&gt;第1张    ,类型
=case rsc_type when 1 then 'NULL 资源(未使用)'
SQL Server2000中死锁经验总结 &lt;转&gt;第1张        
when 2 then '数据库'
SQL Server2000中死锁经验总结 &lt;转&gt;第1张        
when 3 then '文件'
SQL Server2000中死锁经验总结 &lt;转&gt;第1张        
when 4 then '索引'
SQL Server2000中死锁经验总结 &lt;转&gt;第1张        
when 5 then ''
SQL Server2000中死锁经验总结 &lt;转&gt;第1张        
when 6 then ''
SQL Server2000中死锁经验总结 &lt;转&gt;第1张        
when 7 then ''
SQL Server2000中死锁经验总结 &lt;转&gt;第1张        
when 8 then '扩展盘区'
SQL Server2000中死锁经验总结 &lt;转&gt;第1张        
when 9 then 'RID(行 ID)'
SQL Server2000中死锁经验总结 &lt;转&gt;第1张        
when 10 then '应用程序'
SQL Server2000中死锁经验总结 &lt;转&gt;第1张    
end
SQL Server2000中死锁经验总结 &lt;转&gt;第1张    ,对象id
=rsc_objid
SQL Server2000中死锁经验总结 &lt;转&gt;第1张    ,对象名
=b.obj_name
SQL Server2000中死锁经验总结 &lt;转&gt;第1张    ,rsc_indid
SQL Server2000中死锁经验总结 &lt;转&gt;第1张 
from master..syslockinfo a left join #t b on a.req_spid=b.req_spid
SQL Server2000中死锁经验总结 &lt;转&gt;第1张
SQL Server2000中死锁经验总结 &lt;转&gt;第1张
go
SQL Server2000中死锁经验总结 &lt;转&gt;第1张
drop table #t
SQL Server2000中死锁经验总结 &lt;转&gt;第1张

免责声明:文章转载自《SQL Server2000中死锁经验总结 &amp;lt;转&amp;gt;》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Python 并发总结,多线程,多进程,异步IOSQL学习02-SQL 2019安装部署下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

SQL数据库设计的命名规范

< DOCTYPE html PUBLIC -WCDTD XHTML StrictEN httpwwwworgTRxhtmlDTDxhtml-strictdtd> 1 相关的设计规范:1.1 采用有意义的字段名尽可能地把字段描述的清楚些。当然,也别做过头了,比如CustomerShippingAddressStreetLine1 虽然很富有说...

提升SQLite数据插入效率低、速度慢的方法

前言 SQLite数据库由于其简单、灵活、轻量、开源,已经被越来越多的被应用到中小型应用中。甚至有人说,SQLite完全可以用来取代c语言中的文件读写操作。因此我最近编写有关遥感数据处理的程序的时候,也将SQLite引入进来,以提高数据的结构化程度,并且提高大数据的处理能力(SQLite最高支持2PB大小的数据)。但是最开始,我发现,直接使用SQL语句...

Oracle之PL/SQL编程

PL/SQL(ProceduralLanguage/SQL,过程语言/SQL) 是结合了Oracel过程语言和结构化查询语言(SQL)的一种扩展语言。 优点: (1)PL/SQL具有编程语言的特点,它能把一组SQL语句放到一个模块中,使其更具模块化种序的特点。 (2)PL/SQL可以采用过程性语言控制程序的结构。 (3)PL/SQL有自动处理的异常处理机制...

RabbitMQ消息可靠性传输

消息的可靠性投递是使用消息中间件不可避免的问题,不管是使用kafka、rocketMQ或者rabbitMQ,那么在RabbitMQ中如何保证消息的可靠性投递呢? 先再看一下RabbitMQ消息传递的流程图: 从上面的图可以看到,消息的投递有三个对象参与: 生产者 RabbitMQ(broker) 消费者 那么消息的可靠性传输也主要是针对以上三个对象来...

Java程序员从笨鸟到菜鸟之(五十二)细谈Hibernate(三)Hibernate常用API详解及源码分析--csdn 曹胜欢

新接触一个框架的目的就是想利用这个框架来为我们做一些工作,或者是让他来简化我们的工作,利用这个框架无非就是要利用这个框架所给我们提供的API去操作我们的数据,所以利用一个框架的好坏很大一部分取决于你对这个框架API的理解程度,所以在此篇博客中我们就一起来看一下Hibernate的API和配置文件的相信情况。下面我们一一来看一下: 一:使用SchemaExp...

分享我们项目中基于EF事务机制的架构

分享我们项目中基于EF事务机制的架构写在前面: 1. 本文中单元测试用到的数据库,在执行测试之前,会被清空,即使用空数据库。 2. 本文中的单元测试都是正确通过的。 要理解EF的事务机制,首先要理解这2个类:TransactionScope和DbContext。 DbContext是我们的数据库,通常我们会建一个类MyProjectDbContext继承自...