度量快速开发平台-专业、快速的软件定制快开平台
标题: 详解Sqlserver死锁检测的方法 [打印本页]
作者: 万望 时间: 2020-4-3 22:13
标题: 详解Sqlserver死锁检测的方法
死锁(deadlock)指进程之间互相永久阻塞的状态,SQL可以检测到死锁,并选择终止其中一个事务以干预sql server死锁状态。
第一步:首先创建两个测试表,表goods_sort和goods
表goods_sort:创建并写入测试数据。
- IF EXISTS(SELECT name FROM sysobjects WHERE name='goods_sort' AND xtype='U')
- DROP TABLE dbo.goods_sort
- --创建商品分类表
- CREATE TABLE dbo.goods_sort(
- iSortID int NOT NULL
- CONSTRAINT PK_iSortID PRIMARY KEY
- IDENTITY(1001,1),
- sSortName NVARCHAR(20) NOT NULL
- )
- GO
- INSERT INTO dbo.goods_sort VALUES('服饰')
- INSERT INTO dbo.goods_sort VALUES('女包')
- INSERT INTO dbo.goods_sort VALUES('鞋子')
- INSERT INTO dbo.goods_sort VALUES('首饰')
- INSERT INTO dbo.goods_sort VALUES('美容')
- GO
复制代码表goods:创建并写入测试数据:
- IF EXISTS(SELECT name FROM sysobjects WHERE name='goods' AND xtype='U')
- DROP TABLE dbo.goods;
- --创建商品表
- CREATE TABLE dbo.goods(
- iID int NOT NULL
- CONSTRAINT PK_iID PRIMARY KEY
- IDENTITY(1,1),
- iGoodsID varchar(20) NOT NULL,
- sGoodsName nvarchar(100) NOT NULL,
- iGoodTotal int NOT NULL
- CONSTRAINT DF_iGoodTotal DEFAULT(0),
- iPrice int NOT NULL
- CONSTRAINT DF_iPrice DEFAULT(0),
- iPriceTotal int NOT NULL,
- iSortID int NOT NULL,
- tAddDate smalldatetime NOT NULL
- CONSTRAINT DF_tAddDate DEFAULT getdate()
- )
- GO
- INSERT INTO dbo.goods
- (iGoodsID,sGoodsName,iGoodTotal,iPrice,iPriceTotal,iSortID)
- VALUES('YR6001','瘦身羽绒服',20,200,4000,1001)
- INSERT INTO dbo.goods
- (iGoodsID,sGoodsName,iGoodTotal,iPrice,iPriceTotal,iSortID)
- VALUES('YR6002','加厚羽绒服',20,300,6000,1001)
- INSERT INTO dbo.goods
- (iGoodsID,sGoodsName,iGoodTotal,iPrice,iPriceTotal,iSortID)
- VALUES('BB7001','小黄牛皮马鞍包',30,100,3000,1002)
- INSERT INTO dbo.goods
- (iGoodsID,sGoodsName,iGoodTotal,iPrice,iPriceTotal,iSortID)
- VALUES('BB7002','十字绣流苏包',50,150,7500,1002)
- GO
复制代码第二步:创建两个会产生死锁的事务
事务1:
- SET NOCOUNT ON;
- SET XACT_ABORT ON;
- GO
- --使用TRY-CATCH,使代码发生错误也继续运行
- BEGIN TRY
- BEGIN TRAN
- UPDATE dbo.goods_sort SET sSortName='女鞋' WHERE iSortID=1003;
- WAITFOR DELAY '00:00:05';
- UPDATE dbo.goods SET sGoodsName='胖子羽绒服' WHERE iID=2;
- COMMIT TRAN
- END TRY
- BEGIN CATCH
- IF (XACT_STATE()=-1)
- ROLLBACK TRAN;
- --ERROR_NUMBER()值为1205则表示发生了死锁
- IF (ERROR_NUMBER() = 1205)
- PRINT '事务1发生了死锁'
- --写SQL Server日志或者返回错误给应用程序
- END CATCH
- SELECT iID,sGoodsName FROM dbo.goods WHERE iID=2;
- SELECT iSortID,sSortName FROM dbo.goods_sort WHERE iSortID=1003;
- GO
复制代码事务二:
- SET NOCOUNT ON;
- SET XACT_ABORT ON;
- GO
- --使用TRY-CATCH,使代码发生错误也继续运行
- BEGIN TRY
- BEGIN TRAN
- UPDATE dbo.goods SET sGoodsName='瘦子羽绒服' WHERE iID=2;
- WAITFOR DELAY '00:00:05';
- UPDATE dbo.goods_sort SET sSortName='男鞋' WHERE iSortID=1003;
- COMMIT TRAN
- END TRY
- BEGIN CATCH
- IF (XACT_STATE()=-1)
- ROLLBACK TRAN;
- --ERROR_NUMBER()值为1205则表示发生了死锁
- IF (ERROR_NUMBER() = 1205)
- PRINT '事务2发生了死锁'
- --写SQL Server日志或者返回错误给应用程序
- END CATCH
- SELECT iID,sGoodsName FROM dbo.goods WHERE iID=2;
- SELECT iSortID,sSortName FROM dbo.goods_sort WHERE iSortID=1003;
- GO
复制代码然后运行事务1,接着马上运行事务2,这种情况下某一个事务会提示发生了死锁,修改不成功。另外一个事务则完成。
第一点:使用TRY.CATCH让产生异常的事务能继续完成后面的代码。
第二点:使用WAITFOR DELAY产生造成死锁的发生环境。
第三点:使用ERROR_NUMBER()来判断是否发生事务。
第四点:发生死锁,写SQL Server日志或者返回应用程序去写日志。便于检查日志的时候发现存在死锁并做相应的修改。
作者: 万望 时间: 2020-4-3 22:16
1. 死锁原理
根据操作系统中的定义:死锁是指在一组进程中的各个进程均占有不会释放的资源,但因互相申请被其他进程所站用不会释放的资源而处于的一种永久等待状态。
死锁的四个必要条件:
互斥条件(Mutual exclusion):资源不能被共享,只能由一个进程使用。
请求与保持条件(Hold and wait):已经得到资源的进程可以再次申请新的资源。
非剥夺条件(No pre-emption):已经分配的资源不能从相应的进程中被强制地剥夺。
循环等待条件(Circular wait):系统中若干进程组成环路,该环路中每个进程都在等待相邻进程正占用的资源。
作者: 万望 时间: 2020-4-3 22:17
作者: 陈晓龙 时间: 2020-4-4 15:05
很详细的嘛!
作者: 万望 时间: 2020-4-5 23:59
欢迎光临 度量快速开发平台-专业、快速的软件定制快开平台 (http://bbs.delit.cn/) |
Powered by Discuz! X3.2 |