笔记43-徐 锁资源模式和兼容性

笔记43-徐 锁资源模式和兼容性

  1 --锁资源模式和兼容性
  2 --SQLSERVER数据库引擎具有多粒度锁定,允许一个事务锁定不同类型的资源。为了尽量
  3 --减少锁定的开销,数据库引擎自动将资源锁定在适合任务的级别。锁定在较小的粒度
  4 --(例如:行)可以提高并发度,但开销较高,因为如果锁定了许多行,就需要维护
  5 --很多锁。锁定在较大的粒度(例如:表),会降低并发度,因为锁定整个表限制了
  6 --其他事务对表中任务部分的访问,但其开销比较低,因为需要维护的锁数目较小
  7 
  8 --数据库引擎通常必须获取多粒度级别上的锁,才能完整地保护资源。例如,
  9 --为了完整地保护对某一数据行的读取,SQL实例不但需要获取行上的共享锁
 10 --还有辅以页和表上的意向共享锁。否则,如果同时有人对这个行所在的页面
 11 --或表做了改动,也会妨碍事务的正常隔离
 12 
 13 --表 数据库引擎可以锁定的资源
 14 --资源                               说明
 15 --RID                        用于锁定堆(heap)中的某一行
 16 --KEY                        用于锁定索引上的某一行,或者某个索引键
 17 --PAGE                       锁定数据库中的一个8KB页,例如数据页或索引页
 18 --EXTENT                     一组连续的8页(区)
 19 --HOBT                       锁定整个堆或B树的锁
 20 --TABLE                      锁定包括所有数据和索引的整个表
 21 --FILE                       数据库文件
 22 --APPLICATION                应用程序专用的资源
 23 --METADATA                   元数据锁
 24 --ALLOCATION_UNIT            分配单元
 25 --DATABASE                   整个数据库
 26 
 27 
 28 --在此基础上,SQL使用不同的锁模式锁定资源,这些锁模式确定了并发事务访问资源
 29 --的方式
 30 
 31 --表 数据库引擎使用的资源锁模式
 32 --锁模式                                 说明
 33 --共享(S)                         用于不更改或不更新数据的读取操作 ,如select语句  在可重复读或可序列化事务中,一个修改需要先读取数据[获取资源(页或行)的共享锁]  
 34                   
 35 --更新(U)                         用于可更新的资源中,防止当多个会话在读取、锁定以及随后可能进行的资源更新时发生常见形式的死锁
 36 --排他(X)                         用于数据修改操作,例如insert update delete,确保不会同时对一个资源进行多重更新                
 37 --意向 (I)intent                  用于建立锁的层次结构,意向锁包含三种类型:意向共享(IS)意向排他(IX)意向排他共享(SIX)
 38 --架构   稳定stable                 在执行依赖于表架构的操作时使用,架构锁包含两种类型:架构修改(sch-m)和架构稳定性(sch-s)
 39 --大容量更新(BU) bulk insert ,bcp 在向表进行大容量数据复制并且指定了tablock提示时使用
 40 --键范围                            当使用可序列化事务隔离级别时保护查询读取的行的范围,确保再次运行查询时其他
 41 --事务无法插入符合可序列化事务的查询的行
 42 
 43 
 44 --共享锁:共享锁(S锁)允许并发事务在封闭式并发控制下读取select资源。资源上存在共享锁(S锁)时,任何其他事务都不能修改数据
 45 
 46 
 47 --更新锁:在可重复读或可序列化事务中,一个修改需要先读取数据[获取资源(页或行)的共享锁(S锁)],
 48 --然后修改数据[此操作要求锁转换为排他锁(X锁)。]如果两个事务获得了同一个资源上的共享模式锁,然后试图
 49 --同时更新数据,则事务会把共享锁转换为排他锁。由于两个事务都要转换为排他锁(X锁),并且每个事务都必须等待
 50 --另一个事务释放共享锁之后才能得到排他锁,以至于两个事务都无法完成转换,因此发生死锁
 51 --为了避免这种潜在的死锁问题,SQL使用更新锁(U锁)。一次只有一个事务可以获得资源的更新锁。事务真正修改数据
 52 --时,将更新锁(U锁)转换为排他锁(X锁)
 53 
 54 
 55 --排他锁:排他锁(X锁)可以防止并发事务对资源进行访问。使用排他锁(X锁)时,任何其他事务都无法读取或者修改数据;仅在
 56 --使用NOLOCK提示或未提交读隔离级别时才会进行读取操作
 57 --数据修改语句(如insert,update,delete)合并了修改和读取select操作。语句在执行所需的修改操作之前首先执行读取操作以获取数据。
 58 --因此,数据修改语句通常请求共享锁和排他锁。例如:update语句可能根据与一个表的联接修改另一个表中的行。在此情况下,除了请求
 59 --更新行上的排他锁之外,update语句还将请求在联接表中读取的行上的共享锁
 60 
 61 
 62 --意向锁:数据库引擎使用意向锁来保护锁层次结构的底层资源,以防止其他事务对自己锁住的资源造成伤害,提高锁冲突检测性能
 63 --例如:当读取表里的页面时,在请求页共享锁(S锁)之前,事务在表级请求共享意向锁。这样可以防止其他事务随后在表上获取
 64 --排他锁(X锁),修改整个表格。意向锁可以提高性能,因为数据库引擎仅在表级检查意向锁,确定事务是否能安全地获取该表上
 65 --的锁,而不需要检查表中的每行或每页上的锁以确定事务是否可以锁定整个表
 66 
 67 
 68 --架构锁:数据库引擎在表数据定义语言(DDL)操作(例如添加列或删除表)的过程中使用架构修改(sch-m)锁,阻止其他用户
 69 --对这个表格的访问
 70 --数据库引擎在编译和执行查询时使用架构稳定(sch-s)锁,稳定stable。sch-s锁不会阻止其他事务访问表格里的数据。但是,
 71 --会阻止对表格做修改性的DDL操作和DML操作
 72 
 73 
 74 --大容量更新锁:数据库引擎在将大容量复制到表中时使用大容量更新(BU)锁,并指定tablelock提示或使用sp_tableoption
 75 --设置table lock on bulk load表选项。大容量更新锁(BU)锁允许多个线程将数据并发地大容量加载到同一张表,同时
 76 --防止其他不进行大容量加载数据的进程访问该表 bulk insert ,bcp
 77 
 78 
 79 --键范围锁:在使用可序列化(serializable)事务隔离级别时,对于TSQL语句读取的记录集,键范围锁可以隐式包含该记录集中
 80 --包含的行范围。键范围锁可防止幻读。通过保护行之间键的范围,他还可防止对事务访问的记录集进行幻插入或删除
 81 
 82 
 83 
 84 ------------------------------------------------锁兼容性----------------------------------------------------------------------
 85 --锁兼容性控制多个事务能否同时获取同一资源上的锁。如果资源已经被另一事务锁定,则仅当请求锁的模式与现有锁的模式相兼容时,
 86 --才会授予新的锁请求。如果请求锁的模式与现有锁的模式不兼容,则请求新锁的事务将被迫进入等待状态,阻塞也就随之产生。例如
 87 --如果一个事务申请了在某个资源上的排他锁(X锁),则在他释放排他锁(X锁)之前,其他事务均无法获取该资源的任何类型(共享,更新,排他)
 88 --的锁。另一种情况是,如果一个事务已经获得了某个资源上的共享锁(S锁),则即使第一个事务尚未完成,其他事务也可以获取该项的共享锁,
 89 --更新锁(U锁)。但是,在第一个事务释放共享锁之前,其他事务无法获取排他锁
 90 
 91 
 92 --锁模式兼容性:
 93 --请求模式                     IS          S              U          IX         SIX           X
 94 --意向共享(IS)针对表,页面   是          是             是         是          是           否
 95 --共享(S)                    是          是             是         否          否           否
 96 --更新(U)                    是          是             否         否          否           否
 97 --意向排他((IX)              是          否             否         是          否           否
 98 --意向排他共享(SIX)          是          否             否         否          否           否
 99 --排他(X)                    否          否             否         否          否           否
100 
101 
102 
103 --锁的模式和兼容性是SQL预先定义好的,没有任何参数或者配置能够去修改他们。所以要做什么事情,SQL
104 --就会去申请什么类型的锁。出现了某种类型的锁,他就会带来预期的兼容性,也就是所谓的事务隔离行为。
105 --但是申请锁的粒度,是数据库设计能够影响的。如果应用申请的锁粒度都比较小,产生阻塞的几率就会很小。
106 --如果一个连接经常会申请页面级,表级,甚至是数据库一级的锁资源,程序产生阻塞的可能性就会很大
107 
108 --应用能够影响隔离的第二个行为,就是一个连接什么时候释放他申请的资源。如果一个连接总是能够非常
109 --快地把申请的锁释放掉,那阻塞就不容易发生。如果他总是长时间地持有某些锁资源,那么就很容易发生
110 --阻塞了
111 
112 
113 --什么行为会影响锁的粒度,以及持有锁的时间长短呢?这个当然和应用定义的事务性质有关系、
114 
115 --1、一个事务内部要访问或者修改的数据量越大,他所要申请的锁的数目越多,粒度也就可能越大
116 --例如,一个事务如果要修改一张表里面的大部分数据,那在他提交之前,可能其他的用户都无法
117 --访问这张表里的记录,而如果这个事务只对一两条记录进行修改,那么大部分用户访问可能不会
118 --受到影响
119 
120 
121 --2、一个事务做的事情越复杂,他要申请的锁的范围也就越大
122 --如果一个事务做的修改只在一个表上,那他只会申请这张表上的锁,访问其他表的用户不会受到影响
123 --如果一个事务先后对许多张表做了修改,那访问这些表的用户就都会受到影响
124 
125 
126 --3、一个事务延续的时间越长,他持有的锁的时间也会越长
127 --很多锁是要在事务提交的时候才会被释放的。如果事务能够很快结束,他申请的锁就不会延续
128 --很久,也就不容易阻塞住别人。如果这个事务里有很多句话,或者是某句话要运行很久,或者是
129 --语句都结束了,但是连接没有及时提交事务,那有些锁就会一直被这个连接所持有,别人就会很
130 --容易被他给阻塞住。
131 
132 --上面的因素是比较浅显的,但是和应用逻辑紧密相关。对于一个固定的应用逻辑,这些因素
133 --能够调整的余地可能不是很大。为了缓解阻塞问题,还有两大因素影响锁粒度跟持有锁时间
134 --
135 --1、事务的隔离级别能影响锁的申请以及释放时间
136 
137 --2、语句的执行计划,影响到锁的粒度和申请的数量
138 
139 --对于相同的逻辑,如果开发者选择合适的事务隔离级别,引导语句使用优化的执行计划,很多时候
140 --也能达到缓解阻塞的目的。

 

意向锁之间总是不会发生冲突,因为他们都只是“有意”要做什么,还没有真做,所以是可以兼容的
意向锁和其他非意向锁之间的关系和普通锁和普通锁之间的关系是相同的

 

 

f

posted @ 2013-07-27 16:16 桦仔 阅读(...) 评论(...)  编辑 收藏