什么是SIX锁?官方文档锁模式中说到:意向排他共享 (SIX):保护针对层次结构中某些(而并非所有)低层资源请求或获取的共享锁以及针对某些(而并非所有)低层资源请求或获取的意向排他锁。 顶级资源允许使用并发 IS 锁。 例如,获取表上的 SIX 锁也将获取正在修改的页上的意向排他 ...
什么是SIX锁?
官方文档锁模式中说到:
意向排他共享 (SIX):保护针对层次结构中某些(而并非所有)低层资源请求或获取的共享锁以及针对某些(而并非所有)低层资源请求或获取的意向排他锁。 顶级资源允许使用并发 IS 锁。 例如,获取表上的 SIX 锁也将获取正在修改的页上的意向排他锁以及修改的行上的排他锁。 虽然每个资源在一段时间内只能有一个 SIX 锁,以防止其他事务对资源进行更新,但是其他事务可以通过获取表级的 IS 锁来读取层次结构中的低层资源。
官方说明比较晦涩难懂,我尝试用一种易懂的方式说明SIX是什么。
关于锁有几个概念:粒度、层次结构和锁之间的兼容性。锁是用来锁定资源,而资源是包括很多种的,而这些不同的资源代表着不同的粒度。不同的资源间存在着层次结构,如表、分区、页、行、键等。锁的类型用很多种,粗略的分类包括共享锁(S)、更新锁(U)、排他锁(X)和架构锁(Sch)等,而不同类型的锁,有些是互斥的,有些是兼容的。如共享锁与其它类型的锁相互兼容,排他锁与其它的锁类型互斥。
SQL Server分配锁时,会沿着层次结构,从表级别开始分配锁,然后到最下层的行和键。在分配锁时,上级的资源会被分配意向锁(I),用来表示这个资源的下级某个资源已经被锁定了。意向锁也可以分为IS,IX,IU等类型。例如,更新表中某一行,需要在在行上分配X锁,而在行所属的数据页中分配意向锁IX,数据页所属的表上分配IX锁。
如果一个会话的事务当前持有了某个表或者数据页的S锁,而它接下来又要去修改表中的某一个行。这种情况下,事务需要获取行上的X锁和表或数据页上的IX锁,但是SQL Server只允许一个会话在一个资源上获取一个锁。也就是说没有办法在已经获得表或者页级别的S锁之后又分配IX给它。为了解决这个问题,于是就出现了两者的结合体:S+IX=SIX。 同理,如果先持有IX,再去获取S,也会得到SIX。
另外SQL Server中还有类似的锁类型UIX(U+IX),SIU(S+IU),机理也是一样的。这三种锁被称为转换锁。
什么是锁分区?
首先不要把锁分区(Lock Partitioning)和分区锁(Partition Lock)搞混了。
官方文档锁分区:
对于大型计算机系统,在经常被引用的对象上放置的锁可能会变成性能瓶颈,因为获取和释放锁对内部锁资源造成了争用。锁分区通过将单个锁资源拆分为多个锁资源而提高了锁性能。此功能只适用于拥有 16 个或更多 CPU 的系统,它是自动启用的,而且无法禁用。只有对象锁可以分区。
锁任务访问几个共享资源,其中两个通过锁分区进行优化:
调节锁(Spinlock)。它控制对锁资源(例如行或表)的访问。
不进行锁分区,一个调节锁就得管理单个锁资源的所有锁请求。在具有大量活动的系统上,在锁请求等待释放调节锁时会出现资源争用的现象。在这种情况下,获取锁可能变成了一个瓶颈,并且可能会对性能造成负面影响。
为了减少对单个锁资源的争用,锁分区将单个锁资源拆分成多个锁资源,以便将负荷分布到多个调节锁上。
内存。它用于存储锁资源结构。
获取调节锁后,锁结构将存储在内存中,然后即可对其进行访问和可能的修改。将锁访问分布到多个资源中有助于消除在 CPU 之间传输内存块的需要,这有助于提高性能。
获取已分区资源的锁时:
只能获取单个分区的 NL、SCH-S、IS、IU 和 IX 锁模式。
对于以分区 ID 0 开始并且按照分区 ID 顺序排列的所有分区,必须获取非 NL、SCH-S、IS、IU 和 IX 模式的共享锁 (S)、排他锁 (X) 和其他锁。已分区资源的这些锁将比相同模式中未分区资源的锁占用更多的内存,因为每个分区都是一个有效的单独锁。内存的增加由分区数决定。Windows 性能监视器中 SQL Server 锁计数器将显示已分区和未分区锁所使用内存信息。
启动一个事务时,它将被分配给一个分区。对于此事务,可以分区的所有锁请求都使用分配给该事务的分区。按照此方法,不同事务对相同对象的锁资源的访问被分布到不同的分区中。
通过一个示例观察一下SIX和锁分区:
create table t2 (id int identity(1,1) ,col1 int,col2 int)goinsert into t2values (floor(rand()*100),floor(rand()*100))go 20set transaction isolation level serializablebegin traninsert into t2 values (floor(rand()*100),floor(rand()*100))select id from t2 where @@ROWCOUNT>0 and id=SCOPE_IDENTITY()SELECT resource_type, request_mode, resource_description,resource_lock_partitionFROM sys.dm_tran_locksWHERE resource_type <> 'database' and request_session_id=@@SPIDrollback
原标题:分析SIX锁和锁分区导致的死锁
关键词:
*特别声明:以上内容来自于网络收集,著作权属原作者所有,如有侵权,请联系我们:
admin#shaoqun.com
(#换成@)。