虽然升级
可序列化隔离级别下的锁升级可能与其他隔离级别发生的情况相同。
- 正确的索引可以帮助避免将锁升级到一个点
- 锁定许多索引将增加锁定升级的可能性;单个语句的对象之间的计数累计
一些使用单个表和单个索引的快速示例。Id是表上的主键和聚集索引。
一排
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRAN
UPDATE c
SET c.Score = 2147483647
FROM dbo.Comments AS c
WHERE c.Id = 138; --One value
ROLLBACK
对于单个Id值,锁定是最小的。
+--------------+---------------+---------------+-------------+
| request_mode | locked_object | resource_type | total_locks |
+--------------+---------------+---------------+-------------+
| RangeX-X | Comments | KEY | 1 |
| IX | Comments | OBJECT | 1 |
| IX | Comments | PAGE | 1 |
+--------------+---------------+---------------+-------------+
多行
但是,如果我们开始在范围内工作,锁将上升:
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRAN
UPDATE c
SET c.Score = 2147483647
FROM dbo.Comments AS c
WHERE c.Id BETWEEN 1 AND 5000; -- Small range
ROLLBACK
现在,我们在更多键上拥有更多排他锁:
+--------------+---------------+---------------+-------------+
| request_mode | locked_object | resource_type | total_locks |
+--------------+---------------+---------------+-------------+
| RangeX-X | Comments | KEY | 2429 |
| IX | Comments | OBJECT | 1 |
| IX | Comments | PAGE | 97 |
+--------------+---------------+---------------+-------------+
更多行
这将一直持续到我们达到临界点:
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRAN
UPDATE c
SET c.Score = 2147483647
FROM dbo.Comments AS c
WHERE c.Id BETWEEN 1 AND 11655; --Larger range
ROLLBACK
尝试进行锁升级并成功:
+--------------+---------------+---------------+-------------+
| request_mode | locked_object | resource_type | total_locks |
+--------------+---------------+---------------+-------------+
| X | Comments | OBJECT | 1 |
+--------------+---------------+---------------+-------------+
请注意
在这里分开两个概念很重要:隔离级别将是可序列化的,无论采取哪种类型的锁。查询选择隔离级别,存储引擎选择锁。可序列化并不总是会导致范围锁定-存储引擎可以选择仍然符合隔离级别的任何一种锁定。