键范围锁 (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 Server | MySQL InnoDB |
| 隔离级别 | Serializable | REPEATABLE 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
维护状态: ✅ 完整