经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 数据库/运维 » MS SQL Server » 查看文章
MS SQL 锁与事务
来源:cnblogs  作者:停车坐爱枫林晚  时间:2019/4/24 9:58:14  对本文有异议

加锁的主要目的是为了防止并发操作时导致的数据不一致等问题,锁分为共享锁(S)、更新锁(U)、排他锁(X),共享锁与更新只是单向兼容?传说中的单相思?

事务

事务能保证数据操作的原子性,要么内部操作都提交,要么都回退。事务内部某个地方出错时,可以回滚前面的操作,比如更新、删除等。

  1. BEGIN TRAN
  2.  
  3. ---报错时回滚
  4. IF @@ERROR<>0
  5. ROLLBACK TRAN
  6.  
  7. --执行完后提交
  8. COMMIT TRAN

 

 

共享锁

共享锁允许并发事务读取一个资源,资源上存在共享锁时,任何其他事务不能修改数据,但是允许同时读取。

HoldLock 在表上保持共享锁,直到整个事务结束。

执行查询时会默认加上共享锁。

  1. BEGIN TRAN EE
  2. SELECT * FROM AA(HOLDLOCK)
  3. WAITFOR DELAY '0:0:30'
  4. COMMIT TRAN EE
  1. BEGIN TRAN RR
  2. SELECT * FROM AA(HOLDLOCK)
  3. COMMIT TRAN RR

上面的例子,都在表AA上加了共享锁,运行结果表明,即使第一个事务没有执行完,第二个事务仍然可以直接查询出结果。这就说明,共享锁是可以同时存在多个的,多个事务可以同时获取同一资源的共享锁。

 

排他锁

XLOCK 其他事务不能读也不能修改它锁定的资源。

执行更新时会自动添加排他锁。

共享锁与排他锁不能同时存在。

  1. BEGIN TRAN EE
  2. SELECT * FROM AA(HOLDLOCK)
  3. WAITFOR DELAY '0:0:30'
  4. COMMIT TRAN EE
  1. BEGIN TRAN RR
  2. UPDATE AA SET TT='33' WHERE DD='44'
  3. COMMIT TRAN RR

第一个事务在执行完成之前,第二个事务的更新一直没有进行,直到第一个事务完成之后,第二个事务中执行的更新操作才能进行。这就表明,共享锁与排他锁时不能同时存在的。一旦一个事务获取到了一个资源的共享锁,那么只有等到共享锁释放之后,才能被其他事务获取排他锁。

 

 

更新锁

UPDLOCK 一次只有一个事务可以获得资源的更新锁,获取了更新锁意味着获取了从共享锁到排他锁的资格。但是不会影响其他的查询,只会阻止那些试图加更新锁的操作。同一时间在同一个资源上不能有两个更新锁,同时加共享锁时允许的。

共享锁与更新锁是兼容的,允许同时在一个资源上。

排他锁与更新锁是不兼容的,不能同时加在一个资源上。

  1. BEGIN TRAN RR
  2. SELECT * FROM AA(UPDLOCK)
  3. WAITFOR DELAY '0:0:30'
  4. COMMIT TRAN RR
  1. BEGIN TRAN EE
  2. SELECT * FROM AA(HOLDLOCK)
  3. COMMIT TRAN EE

以上代码测试结果表明,在资源上加了更新锁之后,还可以继续加共享锁,也就说并不影响查询。但是,看下面的例子。

  1. BEGIN TRAN EE
  2. SELECT * FROM AA(HOLDLOCK)
  3. WAITFOR DELAY '0:0:30'
  4. COMMIT TRAN EE
  1. BEGIN TRAN RR
  2. SELECT * FROM AA(UPDLOCK)
  3. COMMIT TRAN RR

上面的例子是先加共享锁,然后再加更新锁,测试结果表明,在第一个事务结束之前,第二个事务并不能获取到更新锁。所以,是不是可以说更新锁与共享锁的兼容是单向的。

  1. BEGIN TRAN EE
  2. SELECT * FROM AA(UPDLOCK)
  3. WAITFOR DELAY '0:0:30'
  4. COMMIT TRAN EE
  1. BEGIN TRAN RR
  2. SELECT * FROM AA(UPDLOCK)
  3. COMMIT TRAN RR

上面的测试结果表明,不能同时获取同一个资源的更新锁。

  1. BEGIN TRAN EE
  2. SELECT * FROM AA(UPDLOCK)
  3. WAITFOR DELAY '0:0:30'
  4. COMMIT TRAN EE
  1. BEGIN TRAN RR
  2. --SELECT * FROM AA(XLOCK)
  3. UPDATE AA SET TT='44'
  4. COMMIT TRAN RR

上面测试表明,加了更新锁,就不能获得排他锁。

 

原文链接:http://www.cnblogs.com/zyskr/p/10755524.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号