
之前的文章《SQL Server 意向锁》已经介绍过意向锁是怎么形成的。SQL Server 数据库引擎通常必须获取多个级别的锁才能完全保护资源。这组多粒度级别上的锁称为锁层次结构(如下图)。

图一
当我们通过索引查询某一行数据的时候,该行数据将分配共享锁(S)。而行所在的页级和表级将分配意向共享锁(IS),表明其更小粒度存在共享锁,能快速检测锁冲突,如行级别共享锁(如下图)。意向更新锁(IU)与意向排他锁(IX)的形成原理也类似。

图二
以下是2个事务访问同一个底层资源的加锁情况。当2个事务访问低粒度级别的资源时,其加锁过程及上层资源意向锁分配情况。

图三
除了上面提到的3种意向锁,SQL Server 中还有另外3种意向锁:意向排他共享(SIX)、共享意向更新(SIU)、更新意向排他(UIX)。这3种意向锁对大家比较陌生,以下是对这6种锁的描述。
| 锁模式 | 说明 |
共享意向更新 (SIU) | S 锁和 IU 锁的组合,作为分别获取这些锁并且同时持有两种锁的结果。例如,事务执行带有 PAGLOCK 提示的查询,然后执行更新操作。带有 PAGLOCK 提示的查询将获取 S 锁,更新操作将获取 IU 锁。 |
更新意向排他 (UIX) | U 锁和 IX 锁的组合,作为分别获取这些锁并且同时持有两种锁的结果。 |
光看文字可能不好理解,看看英文原译:
shared with intent exclusive (SIX),即共享锁+意向排他锁
shared with intent update (SIU) ,即共享锁+意向更新锁
Update with intent exclusive (UIX) ,即更新锁+意向排他锁
现在,我们就测试意向排他共享(SIX)、共享意向更新(SIU)、更新意向排他(UIX)是怎么形成的。
--准备测试数据create table tab(id int,name varchar(50))goinsert into tabselect [object_id],namefrom sys.objectsgocreate clustered index ix_tab on tab(id)go
意向排他共享 (SIX)
BEGIN TRAN--页面级设置共享锁(S)SELECT * FROM TAB WITH(PAGLOCK,HOLDLOCK) WHERE id = 98--同一个连接,使页面再加上意向排他锁(IX)UPDATE tab SET name = 'Test' WHERE id = 98--查看锁请求情况SELECT resource_type,resource_description,request_mode,request_statusFROM sys.dm_tran_locksWHERE resource_database_id=DB_ID()AND request_session_id=@@SPIDORDER BY request_mode,resource_typeROLLBACK TRAN

图四
意向排他共享锁(SIX)是共享锁(S)与意向排他锁(IX)的结合,上图种 SIX 出现在页面级别上。其中,行级别 key 请求排他锁,是update语句最后的锁。页面级别 page 请求意向排他共享锁(SIX),是select请求的共享锁(S)与update行请求所在页面的意向排他锁(IX)结合而成。表级别 object 请求意向排他锁(IX),是select请求的意向共享锁(IS)与update请求的向排他锁(IX)结合而成(IX是IS的超集,因此只显示IX)。数据库 database 通常请求共享锁(S),不会阻止 DML 操作。
共享意向更新 (SIU)
BEGIN TRAN--页面级设置意向更新锁IUSELECT * FROM TAB WITH(UPDLOCK,HOLDLOCK) WHERE id = 98--同一个连接,使页面级加上共享锁(S)SELECT * FROM TAB WITH(PAGLOCK,HOLDLOCK) WHERE id = 98--查看锁请求情况SELECT resource_type,resource_description,request_mode,request_statusFROM sys.dm_tran_locksWHERE resource_database_id=DB_ID()AND request_session_id=@@SPIDORDER BY request_mode,resource_typeROLLBACK TRAN

图五
共享意向更新 (SIU)的理解请参考上面的意向排他共享锁(SIX)说明。
更新意向排他 (UIX)
BEGIN TRAN--页面级设置意向更新锁IUSELECT * FROM TAB WITH(UPDLOCK,HOLDLOCK) WHERE id = 98--同一个连接,使页面级加上共享锁(S)SELECT * FROM TAB WITH(PAGLOCK,HOLDLOCK) WHERE id = 98--查看锁请求情况SELECT resource_type,resource_description,request_mode,request_statusFROM sys.dm_tran_locksWHERE resource_database_id=DB_ID()AND request_session_id=@@SPIDORDER BY request_mode,resource_typeROLLBACK TRAN

图六
更新意向排他 (UIX)的理解请参考上面的意向排他共享锁(SIX)说明。
意向锁有两种用途:
防止其他事务以较低级别的锁通过无效的方式修改较高级别资源。
提高 SQL Server 数据库引擎在更高粒度级别检测锁冲突的效率。
意向锁不能用锁提示的方法进行设置,它是系统自动维护的。用户在访问的资源时,受到系统20多种锁访问控制,更多的锁冲突情况,可看官方的锁矩阵图了解。不仅如此,SQL Server 还有自旋锁(Spinlock)与闩锁(latch),这些锁保证了数据库系统高效地运行着。
最近文章推荐:
历史文章推荐:





