数据库锁机制核心原则
核心原则不过三条。
首要原则:锁的持有时间取决于"事务"与"隔离级别"的共舞
- 无显式事务(自动提交模式):即使是最强的锁(如UPDATE语句自带的锁),也只在语句执行完毕后立即释放
- 开启显式事务:锁的释放由隔离级别决定:
- 读已提交(RC):锁通常在语句执行完成后释放
- 可重复读(RR)或序列化级别:锁必须保持到事务结束(COMMIT或ROLLBACK)
其次:锁的添加方式有"隐"与"显"之分
-
隐式锁:InnoDB自动添加的锁
- UPDATE、DELETE、INSERT语句自动为操作数据添加排他锁(X锁)
- 由引擎自动管理,用户无法拒绝
-
显式锁:用户手动指定的锁
SELECT ... FOR UPDATE
:施加排他锁(X锁)SELECT ... LOCK IN SHARE MODE
:施加共享锁(S锁)- 需要用户主动请求,引擎才会执行
其三:显式锁凌驾于一切隔离级别之上
一旦使用显式锁(FOR UPDATE 或 LOCK IN SHARE MODE),无论当前处于何种隔离级别,这些锁都必须保持到事务结束。
锁的持有时间速查表
操作类型 | 没有事务 (自动提交) | 有事务 - RC级别 | 有事务 - RR/Serializable级别 |
---|---|---|---|
普通 SELECT | 无锁 (走MVCC) | 无锁 (走MVCC) | 无锁 (走MVCC) |
UPDATE / DELETE / INSERT | 语句结束释放 | 语句结束释放 | 事务结束释放 |
SELECT ... FOR UPDATE | 不常用 (等同语句结束释放) | 事务结束释放 | 事务结束释放 |
SELECT ... LOCK IN SHARE MODE | 不常用 (等同语句结束释放) | 事务结束释放 | 事务结束释放 |
锁的类型与添加方式
操作 | 锁类型 | 添加方式 |
---|---|---|
UPDATE / DELETE | 行级排他锁 (X锁) | 隐式 (自动) |
INSERT | 行级排他锁 (X锁) | 隐式 (自动) |
SELECT ... FOR UPDATE | 行级排他锁 (X锁) | 显式 (手动) |
SELECT ... LOCK IN SHARE MODE | 行级共享锁 (S锁) | 显式 (手动) |
记忆诀窍
-
首先判断是否开启事务
- 未开启事务:所有锁都是"语句结束释放"
-
已开启事务时,判断操作类型
- 普通SELECT:几乎无锁
- 写操作(UPDATE/INSERT/DELETE):锁释放时机由隔离级别决定
- RC:短暂持有
- RR:长期持有(直到事务结束)
- 显式加锁(FOR UPDATE等):不受隔离级别影响,锁必定持续到事务结束
只需辨明自己的操作属于以上何种情形,便能立刻知晓锁将于何时释放。