Skip to content

数据库锁 - 快速参考手册 ​

📊 锁粒度对比 ​

锁类型并发度开销适用场景典型数据库
表级锁⭐⭐低DDL、批量操作MySQL MyISAM, PostgreSQL
行级锁⭐⭐⭐⭐⭐高高并发 OLTPMySQL InnoDB, Oracle
页级锁⭐⭐⭐中折中方案MySQL BDB
库级锁⭐极低备份、维护所有数据库

🔐 锁模式对比 ​

锁模式符号读兼容写兼容使用场景
共享锁S✅❌SELECT ... LOCK IN SHARE MODE
排他锁X❌❌UPDATE, DELETE, INSERT
意向共享IS✅❌准备在行上加 S 锁
意向排他IX❌❌准备在行上加 X 锁

锁兼容性矩阵 ​

        | S    | X    | IS   | IX
--------|------|------|------|-----
S       | ✅   | ❌   | ✅   | ❌
X       | ❌   | ❌   | ❌   | ❌
IS      | ✅   | ❌   | ✅   | ✅
IX      | ❌   | ❌   | ✅   | ✅

🔧 MySQL InnoDB 锁算法 ​

算法锁定范围防止问题隔离级别要求
记录锁单个索引记录更新冲突所有级别
间隙锁索引间的间隙幻读REPEATABLE READ
临键锁记录 + 前间隙幻读 + 更新冲突REPEATABLE READ

⚖️ 锁策略对比 ​

策略假设优点缺点适用场景
悲观锁冲突必然发生数据安全性能较低,可能死锁高冲突场景
乐观锁冲突很少发生高性能需要重试机制低冲突场景

实现方式对比 ​

悲观锁

sql
-- SELECT FOR UPDATE
SELECT * FROM accounts WHERE id = 1 FOR UPDATE;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;

乐观锁

sql
-- 版本号机制
UPDATE accounts SET balance = balance - 100, version = version + 1 
WHERE id = 1 AND version = 5;
-- 检查影响行数,如果为 0 则重试

🔒 特殊锁类型速查 ​

锁名称作用触发条件数据库
元数据锁(MDL)保护表结构DDL/DML 自动加锁MySQL 5.5+
自增锁保证 AUTO_INCREMENT 唯一性INSERT 自增列MySQL InnoDB
插入意向锁INSERT 前的间隙检查INSERT 操作MySQL InnoDB
谓词锁基于条件的逻辑锁Serializable 隔离级别PostgreSQL
键范围锁锁定键值范围Serializable 隔离级别SQL Server

🎛️ 锁管理方式 ​

方式特点灵活性风险示例
隐式锁数据库自动管理低低普通 UPDATE
显式锁用户手动指定高高(可能死锁)SELECT FOR UPDATE

📈 性能影响评估 ​

并发度排序(从高到低) ​

乐观锁 > 行级锁 > 页级锁 > 表级锁 > 库级锁 > 悲观锁

开销排序(从低到高) ​

库级锁 < 表级锁 < 页级锁 < 行级锁 < 间隙锁 < 临键锁

🚨 常见问题速查 ​

死锁 ​

症状: 事务互相等待对方释放锁
解决:

  • 设置超时: innodb_lock_wait_timeout
  • 固定加锁顺序
  • 使用 TRY...CATCH 重试

锁等待 ​

症状: 查询长时间阻塞
排查:

sql
-- MySQL
SELECT * FROM performance_schema.data_lock_waits;
SHOW ENGINE INNODB STATUS;

幻读 ​

症状: 同一查询在不同时间返回不同行数
解决: 使用 REPEATABLE READ + 临键锁

活锁 ​

症状: 事务不断重试但无法完成
解决: 引入随机退避或优先级队列

🎯 最佳实践清单 ​

✅ 推荐做法 ​

  • [ ] 尽量使用行级锁提高并发
  • [ ] 事务尽可能短小,快速释放锁
  • [ ] 为频繁查询的字段添加索引,避免锁升级
  • [ ] 使用乐观锁处理低冲突场景
  • [ ] 设置合理的锁超时时间
  • [ ] 监控和分析锁等待日志

❌ 避免陷阱 ​

  • [ ] 避免在大事务中持有锁
  • [ ] 避免在事务中进行网络调用
  • [ ] 避免不一致的加锁顺序
  • [ ] 避免忽略死锁异常
  • [ ] 避免过度使用显式锁
  • [ ] 避免在循环中执行带锁的查询

📊 各数据库锁特性对比 ​

特性MySQL InnoDBPostgreSQLSQL ServerOracle
默认锁粒度行级行级行级行级
MVCC✅✅✅ (快照隔离)✅
间隙锁✅❌ (用谓词锁)✅ (范围锁)❌
表级锁支持支持支持支持
死锁检测✅✅✅✅
锁升级❌❌✅❌
SELECT FOR UPDATE✅✅✅✅
NOWAIT✅✅✅✅
SKIP LOCKED✅ (8.0+)✅✅✅

🔍 诊断命令速查 ​

MySQL ​

sql
-- 查看锁信息 (5.7+)
SELECT * FROM performance_schema.data_locks;

-- 查看锁等待
SELECT * FROM performance_schema.data_lock_waits;

-- InnoDB 状态
SHOW ENGINE INNODB STATUS\G

-- 当前事务
SELECT * FROM information_schema.innodb_trx;

-- 锁等待超时设置
SHOW VARIABLES LIKE 'innodb_lock_wait_timeout';

PostgreSQL ​

sql
-- 查看所有锁
SELECT * FROM pg_locks;

-- 查看锁等待
SELECT blocked_locks.pid AS blocked_pid,
       blocking_locks.pid AS blocking_pid
FROM pg_catalog.pg_locks blocked_locks
JOIN pg_catalog.pg_locks blocking_locks
  ON blocking_locks.locktype = blocked_locks.locktype
  AND blocking_locks.relation = blocked_locks.relation;

-- 活动会话
SELECT * FROM pg_stat_activity WHERE wait_event_type = 'Lock';

SQL Server ​

sql
-- 查看锁
SELECT * FROM sys.dm_tran_locks;

-- 查看阻塞
EXEC sp_who2;

-- 详细锁信息
SELECT request_session_id, resource_type, resource_description,
       request_mode, request_status
FROM sys.dm_tran_locks;

Oracle ​

sql
-- 查看锁
SELECT * FROM v$lock;

-- 查看锁等待
SELECT * FROM v$session_wait WHERE event LIKE 'enq%';

-- 查看持有锁的会话
SELECT s.sid, s.serial#, l.type, l.lmode, l.request
FROM v$session s, v$lock l
WHERE s.sid = l.sid;

📚 相关资源 ​


提示: 此速查表会随知识库更新而同步演进,建议定期查看最新版本。

Released under MIT License.