Skip to content

键范围锁 (Key-Range Lock) ​

📋 概述 ​

键范围锁(Key-Range Lock)是 SQL Server 在 Serializable 隔离级别下使用的一种锁机制。它锁定索引键值的范围,防止其他事务在该范围内插入、更新或删除记录,从而避免幻读现象。

核心特点 ​

✅ 优点:

  • 防止幻读: 完全阻止范围内的修改
  • 精确控制: 基于索引键值范围
  • 自动管理: SQL Server 自动处理
  • 理论完备: 严格的串行化保证

❌ 缺点:

  • 并发度低: 阻塞范围内的所有操作
  • 仅 SQL Server: SQL Server 特有机制
  • 性能影响: Serializable 级别性能较低
  • 依赖索引: 需要合适的索引才能生效

适用场景 ​

  • Serializable 隔离级别: SQL Server 的最高隔离级别
  • 范围查询: WHERE id BETWEEN ... AND ...
  • 防止幻读: 确保多次查询结果一致
  • 关键业务: 金融、医疗等要求强一致性的场景

🔧 工作原理 ​

锁的范围 ​

键范围锁锁定的是索引键值的范围:

sql
-- 假设表中有 id = 1, 5, 10 的记录

-- Serializable 级别的范围查询
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN TRANSACTION;
SELECT * FROM users WHERE id BETWEEN 3 AND 7;

锁定范围:

  • 锁定键值在 [3, 7] 范围内的所有记录
  • 锁定间隙,防止插入新记录

锁的模式 ​

键范围锁有多种模式:

模式说明
RangeS-S范围共享锁 + 记录共享锁
RangeS-U范围共享锁 + 记录更新锁
RangeX-X范围排他锁 + 记录排他锁

💻 SQL Server 实现 ​

基本用法 ​

sql
-- 设置 Serializable 隔离级别
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;

BEGIN TRANSACTION;
    -- 范围查询自动加键范围锁
    SELECT * FROM users WHERE id BETWEEN 3 AND 7;
    
    -- 其他事务无法在此范围内插入或修改
    -- INSERT INTO users VALUES (5, 'test');  -- 被阻塞
    
COMMIT TRANSACTION;

查看键范围锁 ​

sql
-- 查看当前的键范围锁
SELECT 
    request_session_id,
    resource_type,
    resource_database_id,
    resource_associated_entity_id,
    request_mode,
    request_status
FROM sys.dm_tran_locks
WHERE request_mode LIKE 'Range%';

输出示例:

request_mode
-------------
RangeS-S
RangeX-X

📊 与临键锁对比 ​

SQL Server 键范围锁 vs MySQL 临键锁 ​

特性键范围锁临键锁
数据库SQL ServerMySQL InnoDB
隔离级别SerializableREPEATABLE READ
锁定对象索引键值范围索引记录+间隙
实现方式范围锁记录锁+间隙锁
目的防止幻读防止幻读

🎯 最佳实践 ​

✅ 推荐做法 ​

1. 仅在必要时使用 Serializable ​

sql
-- ✅ 关键业务使用
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;

-- ✅ 一般业务使用 READ COMMITTED(默认)
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;

2. 确保有合适的索引 ​

sql
-- ✅ 为范围查询添加索引
CREATE INDEX idx_id ON users(id);

-- 键范围锁依赖索引工作
SELECT * FROM users WHERE id BETWEEN 3 AND 7;

❌ 避免陷阱 ​

1. 避免长时间持有键范围锁 ​

sql
-- ❌ 不推荐
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN TRANSACTION;
SELECT * FROM users WHERE id BETWEEN 1 AND 100;
-- 大量无关操作
COMMIT;

-- ✅ 推荐:快速完成
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN TRANSACTION;
SELECT * FROM users WHERE id BETWEEN 1 AND 10;
-- 快速处理
COMMIT;

🚨 常见问题 ​

Q1: 键范围锁只在 SQL Server 中存在吗? ​

答: 是的,键范围锁是 SQL Server Serializable 隔离级别的特有实现。


Q2: 键范围锁会影响性能吗? ​

答: 会,特别是在高并发和大范围查询场景。建议仅在必要时使用。


📚 相关资源 ​

内部链接 ​

外部资源 ​


最后更新: 2026-04-12
维护状态: ✅ 完整

Released under MIT License.