sql server的UPDLOCK、HOLDLOCK试验

在这里插入图片描述

-- 2个tran都查询id = 1000001数据,然后尝试更新
-- 结果2边都能在10s内结束
BEGIN TRAN
SELECT * FROM content_article where id = '1000001';
WAITFOR DELAY '00:00:10'
UPDATE content_article SET weighted = 2 where id = '1000001';
COMMIT TRAN

-- 查询时都加上HOLDLOCK, 左边先运行
-- 结果:左边18s结束,右边12s结束
-- 右边报错:事务(进程 ID 58)与另一个进程被死锁在 锁 资源上,并且已被选作死锁牺牲品。请重新运行该事务。
BEGIN TRAN
SELECT * FROM content_article with (HOLDLOCK) where id = '1000001';
WAITFOR DELAY '00:00:10'
UPDATE content_article SET weighted = 2 where id = '1000001';
COMMIT TRAN

-- 左边不变,右边加上UPDLOCK
-- 结果:同上-----------应该说明右边并没有活动UPDLOCK吧
BEGIN TRAN
SELECT * FROM content_article with (HOLDLOCK) where id = '1000001';
WAITFOR DELAY '00:00:10'
UPDATE content_article SET weighted = 2 where id = '1000001';
SELECT * FROM op_content_article where id = '1000001';
COMMIT TRAN

推测:
1.因为数据库默认 隔离级别 读已提交,故select语句只是S锁,不加HOLDLOCK,二边事务正常运行;
2.加了HOLDLOCK,首次select的语句会获得UPDLOCK, 故发生死锁时,未获得UPDLOCK报错了,即右边后面2次都无法获得UPDLOCK

实际:如官方文档所示,sql server 死锁监视器会定期检查 陷入死锁的任务,检测到了循环依赖关系,选择其中一个任务作为牺牲品,终止并提示错误
在这里插入图片描述
再举一个具体的例子详细说明:

-- 事务1先获得row1共享锁
-- 事务2获得row2共享锁
-- 事务2尝试获得row1排他锁---但事务1的共享锁阻止了
-- 事务1尝试获得row2排他锁---但事务2的共享锁阻止了

-- 事务1和事务2互相死锁,被死锁监视器检测到,故10s左右 两边都会执行完毕;
BEGIN TRAN
SELECT * FROM content_article (HOLDLOCK) where id = '1000001';
WAITFOR DELAY '00:00:10'
UPDATE content_article SET weighted = 2 where id = '1000002';
COMMIT TRAN

ROLLBACK TRAN
BEGIN TRAN
SELECT * FROM content_article with (HOLDLOCK) where id = '1000002';
UPDATE content_article SET weighted = 2 where id = '1000001';
COMMIT TRAN
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值