使用Sqlserver更新锁防止数据脏读

Posted 大西瓜3721

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用Sqlserver更新锁防止数据脏读相关的知识,希望对你有一定的参考价值。

有时候我们需要控制某条记录在程序读取后就不再进行更新,直到事务执行完释放后才可以。这时候我们就可以将所有要操作当前记录的查询加上更新锁,以防止查询后被其它事务修改。这种操作只锁定表中某行而不会锁定整个表,体验更好。

  测试sql代码如下:

  在一个查询中执行如下语句

begin tran
 SELECT InvestState FROM InvestOrdersABC WITH (UPDLOCK) where id=10005
 waitfor delay ‘00:00:10‘ 
 update InvestOrdersABC set InvestState=‘2‘ where id=10005
commit tran

  1、在另外的一个查询中执行以下语句

SELECT InvestState FROM InvestOrdersABC  where id=10005

  发现在第一个事务执行完以前查到的数值还是原来的数值0,直到更新完成后才会变成2,如果加上锁,代码如下:

SELECT InvestState FROM InvestOrdersABC WITH (UPDLOCK) where id=10005

  发现sql语句必须等到第一个连接里的事务完成才执行完成,这是因为这个sql的连接的更新锁认为第一个事务里的更新锁可能会对数据进行修改,因此必须等事务执行完成才执行。此时更新锁变为排他锁。

  2、如果执行更新操作:

begin tran
 update InvestOrders set InvestState=‘3‘ where id=10005
commit tran

   发现无法更改,只能等到第一个查询完成后才会进行修改。其实和加锁不加锁已经没什么关系,为什么呢?因为SQL Server在执行INSERT、 UPDATE 或DELETE 命令时,会自动使用独占锁。

  3、上文的事务未加隔离级别,事务的默认隔离级别为READ  committed,不加锁因此在第1点里还可以进行查询。当数据库事务的隔离级别为REPEATABLE READ,SERIALIZABLE时,如果查询需要加共享锁:

SELECT InvestState FROM InvestOrdersABC WITH (HoldLOCK) where id=10005

以上是关于使用Sqlserver更新锁防止数据脏读的主要内容,如果未能解决你的问题,请参考以下文章

SQLServer并发问题,先SELECT后UPDATE,避免并发脏读情况解决

事务的隔离级别,乐观锁,悲观锁

SQL Server 锁详解

sqlserver数据库select操作会造成锁表吗

小白知识:事务+ACID+更新丢失+脏读+幻读+隔离级别+锁

平时使用oracle时,为啥会锁表