--死锁
/******************************************************************************************************************************************************
死锁指两个以上事务相互阻塞相互等待对方释放它们的锁,SQL Server会通过回滚其中一个事务并返回一个错误来自已解决阻塞问题,让其他事务完成它们的工作。
整理人:中国风(Roy)
日期:2008.07.20
******************************************************************************************************************************************************/
set nocount on ;
if object_id('T1') is not null
drop table T1
go
create table T1(ID int primary key,Col1 int,Col2 nvarchar(20))
insert T1 select 1,101,'A'
insert T1 select 2,102,'B'
insert T1 select 3,103,'C'
go
if object_id('T2') is not null
drop table T2
go
create table T2(ID int primary key,Col1 int,Col2 nvarchar(20))
insert T2 select 1,201,'X'
insert T2 select 2,202,'Y'
insert T2 select 3,203,'Z'
go
生成表数据:
/*
T1:
ID Col1 Col2
----------- ----------- --------------------
1 101 A
2 101 B
3 101 C
T2:
ID Col1 Col2
----------- ----------- --------------------
1 201 X
2 201 Y
3 201 Z
*/
防止死锁:
1、 最少化阻塞。阻塞越少,发生死锁机会越少
2、 在事务中按顺序访问表(以上例子:死锁2)
3、 在错误处理程式中检查错误1205并在错误发生时重新提交事务
4、 在错误处理程式中加一个过程将错误的详细写入日志
5、 索引的合理使用(以上例子:死锁1、死锁3)
当发生死锁时,事务自动提交,可通过日志来监视死锁
死锁1(索引):
--连接窗口1
--1步:
begin tran
update t1 set col2=col2+'A' where col1=101
--3步:
select * from t2 where col1=201
commit tran
--连接窗口2
--2步:
begin tran
update t2 set col2=col2+'B' where col1=203
--4步:
select * from t1 where col1=103
commit tran
--连接窗口1:收到死锁错误,连接窗口2得到结果:
/*
讯息 1205,层级 13,状态 51,行 3
交易 (处理序识别码 53) 在 锁定 资源上被另一个处理序锁死并已被选择作为死结的牺牲者。请重新执行该交易。
*/
--连接窗口2:得到结果