mysql记录锁,间隙锁
时间: 2025-01-04 12:33:46 浏览: 5
### MySQL 中记录锁和间隙锁的概念
#### 记录锁 (Record Lock)
记录锁是最常见的行级锁,用于锁定特定的索引记录。当事务对某个具体的数据行执行更新或删除操作时会自动加上记录锁。
- **作用范围**: 锁定的是具体的索引条目。
- **应用场景**: 当需要确保同一时间只有一个事务能够修改某一条特定记录时使用此类型的锁。
例如,在`SELECT ... FOR UPDATE`语句中会对查询到的具体记录加排他锁[^3]:
```sql
BEGIN;
SELECT * FROM accounts WHERE id = 123 FOR UPDATE;
UPDATE accounts SET balance = balance - 100 WHERE id = 123;
COMMIT;
```
这段代码展示了如何通过显式的`FOR UPDATE`来获取记录上的排他锁,防止其他事务在此期间对该账户余额做出更改。
#### 间隙锁 (Gap Lock)
间隙锁并不是针对实际存在的数据行而是存在于两个相邻索引项之间、第一个索引之前以及最后一个索引之后的位置上。这种锁主要用于阻止新记录被插入到指定范围内从而避免发生幻读现象。
- **作用范围**: 不涉及任何真实的数据行;仅覆盖由现有索引定义出来的空白区域。
- **应用场景**: 主要是为了预防幻影问题而设计的一种机制,即在同一条件下再次运行相同的查询可能会返回不同的结果集大小。
下面的例子说明了怎样利用间隙锁保护一段连续编号的空间不被外部干扰:
假设有一个订单表orders按照order_id排序存储着客户提交的商品订购请求,并且现在想要批量处理一批新的订单但是又不想让别人在这段时间内插队,则可以通过如下方式实现:
```sql
START TRANSACTION;
-- 假设当前最大 order_id 是999, 新增订单将从1000开始
INSERT INTO orders VALUES (NULL,'pending', NOW()) /* 这里省略了一些字段 */;
SET @last_order_id := LAST_INSERT_ID();
-- 对即将使用的ID段施加间隔控制
SELECT MAX(order_id)+1 AS next_val FROM orders WHERE order_id < @last_order_id LOCK IN SHARE MODE;
/* 执行业务逻辑 */
...
COMMIT;
```
在这个例子里面,虽然并没有直接指明哪个确切位置应该受到保护,但确实有效地封锁住了可能影响后续流程的那个潜在空间内的所有可能性变化。
### 区别与联系
- 记录锁关注于单个已知实体对象本身的安全性保障;
- 而间隙锁则更侧重于维护某些未占用资源间的相对稳定性。
- **共同点**
- 都属于InnoDB引擎内部为了提高并发性能并保持ACID属性所采取的重要措施之一;
- 实际应用当中往往两者配合起来一起工作形成所谓的Next-Key Lock(临键锁),既包含了对于具体项目的独占权限同时也兼顾到了周围环境的影响因素考虑。
阅读全文