SQL Server搞出的写死锁:解决之道?(sqlserver写死锁)
SQL Server 是一种关系型数据库管理系统,处理记录的规则是每个记录在一个会话内只能被一个用户处理,如果另一个用户也想处理同一记录,应等待之前的操作 结束才能进行。但有时会发生“写死锁”,即一个事务锁定了一个记录,并且保持该记录处于锁定状态,而其它用户无法处理这条记录。这种情况将封锁数据库,影响其它应用程序的运行,因此有必要及时处理写死锁问题。
首先,检测是否有写死锁发生。可以在“管理 > 监视器 > 死锁”中查看当前存在的死锁情况;另外,也可以采用 SQL 语句“ SELECT * FROM sys.dm_tran_locks ”查询当前死锁情况,以便找出发生死锁的操作与用户。
其次,找出死锁发生的原因,一般有三种可能性:
(1)应用程序或查询对对象请求高级锁,且超时期限较长;
(2)存在循环引用关系,即事务A获取B对象,同时事务B获取A对象;
(3)死锁代码缺乏有效的释放步骤,出现无法释放死锁的情况。
最后,针对不同的写死锁情况采取相应的解决措施:
(1)应该在获取锁之前设置一个较短的超时期限;
(2)应尽量避免形成循环引用,比如采用先deny再request的模式;
(3)正确按照步骤释放锁,比如采用“try/catch/finally”结构,在finally中确保释放锁。
例如:
BEGIN TRANSACTION
UPDATE Table1
SET Col1 = ‘X’
WHERE Col2 = ‘Y’
WAITFOR DELAY ’00:00:10’表示等待10秒
UPDATE Table2
SET Col1 = ‘X’
WHERE Col2 = ‘Y’
COMMIT TRANSACTION
可修改为:
BEGIN TRANSACTION
BEGIN TRY
UPDATE Table1
SET Col1 = ‘X’
WHERE Col2 = ‘Y’
WAITFOR DELAY ’00:00:05′
UPDATE Table2
SET Col1 = ‘X’
WHERE Col2 = ‘Y’
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION //确保释放锁
END CATCH
COMMIT TRANSACTION
总的来说,可以采取以上方法检测及解决 SQL Server 写死锁问题,有效避免写死锁影响程序正常运行。