首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SQL Server中密钥范围的RangeI锁兼容性

SQL Server中密钥范围的RangeI锁兼容性
EN

Database Administration用户
提问于 2019-11-02 14:36:37
回答 1查看 982关注 0票数 9

文档声明,RangeI锁(插入范围,空资源锁;用于在将新密钥插入索引之前测试范围)与自身兼容(参见兼容性矩阵),因此即使一个事务已经在特定密钥上获得了RangeI锁,另一个事务也可以获得这样的锁。

在下面,它说

在事务中插入值时,在执行insert操作的事务期间不必锁定值落入的范围。将插入的键值锁定到事务结束为止,就足以保持可序列化。例如,给定以下INSERT语句: INSERT mytable值('Dan');在与名称David对应的索引条目上放置RangeI模式键-范围锁,以测试范围。如果授予该锁,则插入Dan,并在值Dan上放置一个排他(X)锁。RangeI模式的密钥范围锁仅用于测试范围,而不是在执行insert操作的事务期间保持。其他事务可以在插入值Dan之前或之后插入或删除值。但是,任何试图读取、插入或删除值Dan的事务都将被锁定,直到插入事务提交或回滚为止。

引用另一个来源 - Microsoft 2008内部程序:事务和并发:

例如,当Server试图使用可序列化隔离插入会话中的键之间的范围时,将获得RangeIn锁。这种类型的锁并不常见,因为它通常是非常短暂的。只有在找到正确的插入位置之后,锁才会被保存,然后将锁转换为X锁。

我的理解是,这种类型的锁是在确定新插入的键应该放置的范围的过程中(我假设这就是“测试范围”的意思)。在这种情况下,锁被释放,新的键被插入,X锁被放在上面。

但是,我不明白为什么两个RangeI锁据说是相互兼容的。如果事务A和B都在相同的键上放置了一个RangeI-N锁,因为它们都希望将一个新键插入到范围中,并且事务A首先执行插入,则B确定的密钥插入位置可能已经不正确,因为范围已经更改(A在那里插入了一个新值)。有人能解释一下吗?

EN

回答 1

Database Administration用户

回答已采纳

发布于 2019-11-11 02:06:04

我的理解是,这种类型的锁是在确定新插入的键应该放置的范围的过程中(我假设这就是“测试范围”的意思)。在这种情况下,锁被释放,新的键被插入,X锁被放在上面。

请求RangeI-N锁来测试插入键范围不会干扰可能执行与插入不兼容的可序列化操作的另一个事务(例如读取)。

在将记录插入索引的过程中,数据库引擎将定位页面,其中应该插入要插入的键。目前还没有使用页锁和键锁,只有闩锁。一旦找到页面,引擎就会开始获取执行将记录插入到页面所必需的锁。这些是位于页面的IX锁,然后是插入键旁边的键的RangeI-N锁。获取RangeI-N后,将不保存该锁,并请求插入密钥的下一个X锁。在获得必要的锁后,开始插入记录。

假设我们有表和数据

代码语言:javascript
复制
CREATE TABLE T
(
    K int NOT NULL,
    CONSTRAINT UQ_T UNIQUE CLUSTERED (K)
);

INSERT INTO T (K)
VALUES (1), (2), (9), (10);

让我们获取以下查询的结果

代码语言:javascript
复制
SELECT K, %%lockres%% AS lockres
FROM T;

这就是

代码语言:javascript
复制
K    lockres
---- ---------------
1    (8194443284a0)
2    (61a06abd401c)
9    (30b7763ed433)
10   (d08358b1108f)

(我们将在接下来的事情中提到它)。

那么,假设我们有一个查询

代码语言:javascript
复制
SELECT COUNT(*)
FROM T
WHERE K BETWEEN 1 AND 9;

SERIALIZABLE隔离级别下运行它将导致以下锁定占用

为了保护密钥范围,数据库引擎使用RangeS-S锁锁定此范围内的每个密钥。此外,范围旁边的键被锁定(这对于非唯一索引是必要的,但是引擎也是为唯一索引所做的)。在这种情况下,将锁放在与键1、2、9和10相对应的资源上(根据先前的查询结果)。

对表的非并发插入

代码语言:javascript
复制
INSERT INTO T (K)
VALUES (3);

后续锁定足迹的结果

表中不存在键3,因此数据库引擎请求RangeI-N锁定与键9对应的资源(30b7763ed433),该资源目前位于3旁边。获取RangeI-N意味着没有不兼容的可序列化活动正在执行,因此引擎继续并获取对应于键3的资源(98ec012a510)的X锁,然后实际插入并释放锁。注意,没有释放RangeI-N锁。

SELECTINSERT之上同时运行会导致INSERT等待,直到执行的可序列化SELECT处于活动状态。

因为RangeI-NRangeS-S不兼容。一旦执行了事务,SELECT就结束了,INSERT将继续进行。

这就是“测试范围”的意思。

但是,我不明白为什么两个RangeI锁据说是相互兼容的。

RangeI-N锁的兼容性很好,因为它允许并发插入密钥范围。

想象一下我们在做什么

代码语言:javascript
复制
INSERT INTO T (K)
VALUES (4);

代码语言:javascript
复制
INSERT INTO T (K)
VALUES (6);

同时。

可能在某个时候,这两个语句都在对应于键9的资源(30b7763ed433)上获取RangeI-N,但这是很好的,因为这样就可以通过键上的X和页面锁存来进一步控制并发性。

票数 4
EN
页面原文内容由Database Administration提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://dba.stackexchange.com/questions/252430

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档