1. 按锁粒度分类
1.1 全局锁
作用:锁定整个数据库实例,阻止所有写操作。
命令:
FLUSH TABLES WITH READ LOCK
(FTWRL)。使用场景:全库逻辑备份时,但InnoDB引擎推荐使用事务的
mysqldump --single-transaction
实现一致性读,避免阻塞。
1.2 表级锁
表锁:
命令:
LOCK TABLES ... READ/WRITE
,需手动释放(UNLOCK TABLES
)。影响:显式锁表会限制并发,InnoDB通常优先使用行锁。
元数据锁(MDL):
自动加锁:访问表时加MDL读锁(如SELECT),修改表结构时加MDL写锁(如ALTER)。
阻塞问题:长事务未提交会持有MDL读锁,导致后续DDL操作被阻塞。
1.3 行级锁(InnoDB特有)
记录锁(Record Locks):锁索引中的某条记录(若表无索引,则锁聚簇索引)。
间隙锁(Gap Locks):锁索引记录的间隙,防止幻读(如
WHERE id BETWEEN 10 AND 20
)。临键锁(Next-Key Locks):记录锁 + 间隙锁,锁定左开右闭区间(RR隔离级别默认)。
插入意向锁(Insert Intention Locks):插入前的间隙锁,表示插入意图,与其他间隙锁兼容。
2. 按锁类型分类
2.1 共享锁(S Lock)
特性:允许其他事务读,但阻塞写操作。
语法:
SELECT ... LOCK IN SHARE MODE
。
2.2 排他锁(X Lock)
特性:阻止其他事务的读写。
语法:
SELECT ... FOR UPDATE
,或自动加于UPDATE/DELETE操作。
2.3 意向锁(Intention Locks)
目的:快速判断表级锁是否冲突,避免逐行检查。
类型:
意向共享锁(IS):事务准备对行加S锁。
意向排他锁(IX):事务准备对行加X锁。
兼容性:表级锁的兼容性如下:
2.4 自增锁(AUTO-INC Locks)
作用:确保自增列(AUTO_INCREMENT)的连续性。
优化:MySQL 8.0使用轻量级互斥量替代自增锁,提升并发插入性能。
3. 锁与隔离级别
读未提交(RU):不加锁,直接读最新数据(可能脏读)。
读已提交(RC):不加间隙锁,可能幻读,仅锁定存在记录。
可重复读(RR)(默认):
通过临键锁解决幻读。
唯一索引等值查询退化为记录锁,范围查询使用临键锁。
串行化(Serializable):所有SELECT隐式转为
SELECT ... FOR SHARE
。
4. 死锁处理
检测机制:等待图(Wait-for Graph),发现循环依赖则触发回滚。
解决策略:终止代价小的事务,如事务大小、锁数量等决定。
避免方法:
按固定顺序访问资源。
减小事务粒度,尽快提交。
使用
SHOW ENGINE INNODB STATUS
分析死锁日志。
5. 锁优化建议
索引设计:合理使用索引,避免无索引导致行锁升级为表锁。
事务设计:避免长事务,减少锁持有时间。
监控工具:
information_schema.INNODB_LOCKS
和INNODB_LOCK_WAITS
表实时监控锁状态。
6. 示例场景
幻读预防:RR级别下,
SELECT * FROM t WHERE id > 100 FOR UPDATE
会加临键锁,阻止其他事务插入id>100的记录。MDL阻塞:长时间未提交的SELECT会阻塞ALTER TABLE,需监控
SHOW PROCESSLIST
处理。