ms sqlerver 锁实践

近日在工作中碰到数据并发问题,查了很多资料,网上的内容大同小异,亲身实践了一把,供大家参考:

我的问题是首先要读取数据库里的一行记录,判断其标志,如果没有改过则进行一些业务处理并在最后修改此记录标志为已修改;如果已经改过则直接退出。


实际操作过程中经常会有两个人同时操作,导致重复操作。


解决方法:

把所有操作放在一个事务里,包括一开始的读取标记语句:

begin tran

if exists (select * from table1 where status=0   and id=222 --判断语句

...

update table1 set status=1 where ....

end tran


在判断语句前加行级排它锁,可以防止另一个事务并发读取:

if exists (select * from table1 with(RowLock,XLock) where status=0  and id=222

但据说行级锁占资源多,我测试了一下,如果id上有索引,用EXEC SP_LOCK 查看了一下,锁资源比原来多了5行;如果没有索引,居然多了6000多行!估计是把每一页都加上锁了!于是想了另一个方法,建立一个空表:查询锁表,语句改为针对这个空表作全表锁定

select * from查询锁表 with(tablockx) where 1=0,这样另一个并发事务执行到此即阻塞,直到commit才可执行下去,在事务过程用EXEC SP_LOCK 查看,只比原来多1行。

缺点是只是同时只能允许一个人操作,由于这个操作并不要求实现很高的并发性,所以这个方案应该最合适的了


另外补充的一点:如果在事务中执行了一条update语句,那么其它事务是否能查询这个表呢?这个跟查询的字段是否有索引有关:如果有索引,则可以查询;没有则不能查。大概是没有索引要全表扫描,就和当前事务起了冲突



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值