SQL Server中的事务与锁

发表于:2014-6-10 10:16

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:张龙豪    来源:51Testing软件测试网采编

  锁定从数据库系统的角度大致可以分为6种:
  共享锁(S):还可以叫他读锁。可以并发读取数据,但不能修改数据。也就是说当数据资源上存在共享锁的时候,所有的事务都不能对这个资源进行修改,直到数据读取完成,共享锁释放。
  排它锁(X):还可以叫他独占锁、写锁。就是如果你对数据资源进行增删改操作时,不允许其它任何事务操作这块资源,直到排它锁被释放,防止同时对同一资源进行多重操作。
  更新锁(U):防止出现死锁的锁模式,两个事务对一个数据资源进行先读取在修改的情况下,使用共享锁和排它锁有时会出现死锁现象,而使用更新锁则可以避免死锁的出现。资源的更新锁一次只能分配给一个事务,如果需要对资源进行修改,更新锁会变成排他锁,否则变为共享锁。
  意向锁:SQL Server需要在层次结构中的底层资源上(如行,列)获取共享锁,排它锁,更新锁。例如表级放置了意向共享锁,就表示事务要对表的页或行上使用共享锁。在表的某一行上上放置意向锁,可以防止其它事务获取其它不兼容的的锁。意向锁可以提高性能,因为数据引擎不需要检测资源的每一列每一行,就能判断是否可以获取到该资源的兼容锁。意向锁包括三种类型:意向共享锁(IS),意向排他锁(IX),意向排他共享锁(SIX)。
  架构锁:防止修改表结构时,并发访问的锁。
  大容量更新锁:允许多个线程将大容量数据并发的插入到同一个表中,在加载的同时,不允许其它进程访问该表。
  这些锁之间的相互兼容性,也就是,是否可以同时存在。
  锁兼容性具体参见:http://msdn.microsoft.com/zh-cn/library/ms186396.aspx
  锁粒度和层次结构参见:http://msdn.microsoft.com/zh-cn/library/ms189849(v=sql.105).aspx
  死锁
  什么是死锁,为什么会产生死锁。我用 “事务把死锁给整出来啦” 标题下的两个事务产生的死锁来解释应该会更加生动形象点。
  例子是这样的:
  第一个事务(称为A):先更新lives表 --->>停顿5秒---->>更新earth表
  第二个事务(称为B):先更新earth表--->>停顿5秒---->>更新lives表
  先执行事务A----5秒之内---执行事务B,出现死锁现象。
  过程是这样子的:
  A更新lives表,请求lives的排他锁,成功。
  B更新earth表,请求earth的排他锁,成功。
  5秒过后
  A更新earth,请求earth的排它锁,由于B占用着earth的排它锁,等待。
  B更新lives,请求lives的排它锁,由于A占用着lives的排它锁,等待。
  这样相互等待对方释放资源,造成资源读写拥挤堵塞的情况,就被称为死锁现象,也叫做阻塞。而为什么会产生,上例就列举出来啦。
  然而数据库并没有出现无限等待的情况,是因为数据库搜索引擎会定期检测这种状况,一旦发现有情况,立马选择一个事务作为牺牲品。牺牲的事务,将会回滚数据。有点像两个人在过独木桥,两个无脑的人都走在啦独木桥中间,如果不落水,必定要有一个人给退回来。这种相互等待的过程,是一种耗时耗资源的现象,所以能避则避。
  哪个人会被退回来,作为牺牲品,这个我们是可以控制的。控制语法:
  set deadlock_priority  <级别>
  死锁处理的优先级别为 low<normal<high,不指定的情况下默认为normal,牺牲品为随机。如果指定,牺牲品为级别低的。
  还可以使用数字来处理标识级别:-10到-5为low,-5为normal,-5到10为high。
  减少死锁的发生,提高数据库性能
  死锁耗时耗资源,然而在大型数据库中,高并发带来的死锁是不可避免的,所以我们只能让其变的更少。
  按照同一顺序访问数据库资源,上述例子就不会发生死锁啦
  保持是事务的简短,尽量不要让一个事务处理过于复杂的读写操作。事务过于复杂,占用资源会增多,处理时间增长,容易与其它事务冲突,提升死锁概率。
  尽量不要在事务中要求用户响应,比如修改新增数据之后在完成整个事务的提交,这样延长事务占用资源的时间,也会提升死锁概率。
  尽量减少数据库的并发量。
  尽可能使用分区表,分区视图,把数据放置在不同的磁盘和文件组中,分散访问保存在不同分区的数据,减少因为表中放置锁而造成的其它事务长时间等待。
  避免占用时间很长并且关系表复杂的数据操作。
  使用较低的隔离级别,使用较低的隔离级别比使用较高的隔离级别持有共享锁的时间更短。这样就减少了锁争用。
  可参考:http://msdn.microsoft.com/zh-cn/library/ms191242(v=sql.105).aspx
  查看锁活动情况:
  --查看锁活动情况
  select * from sys.dm_tran_locks
  --查看事务活动情况
  dbcc opentran
  可参考:http://msdn.microsoft.com/zh-cn/library/ms190345.aspx
  为事务设置隔离级别
  所谓事物隔离级别,就是并发事务对同一资源的读取深度层次。分为5种。
  read uncommitted:这个隔离级别最低啦,可以读取到一个事务正在处理的数据,但事务还未提交,这种级别的读取叫做脏读。
  read committed:这个级别是默认选项,不能脏读,不能读取事务正在处理没有提交的数据,但能修改。
  repeatable read:不能读取事务正在处理的数据,也不能修改事务处理数据前的数据。
  snapshot:指定事务在开始的时候,就获得了已经提交数据的快照,因此当前事务只能看到事务开始之前对数据所做的修改。
  serializable:最高事务隔离级别,只能看到事务处理之前的数据。
  --语法
  set tran isolation level <级别>
43/4<1234>
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号