Administrator
发布于 2025-02-18 / 9 阅读
0
0

MySQL的锁机制

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锁。

  • 兼容性:表级锁的兼容性如下:

    X

    IX

    S

    IS

    X

    冲突

    冲突

    冲突

    冲突

    IX

    冲突

    兼容

    冲突

    兼容

    S

    冲突

    冲突

    兼容

    兼容

    IS

    冲突

    兼容

    兼容

    兼容

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_LOCKSINNODB_LOCK_WAITS表实时监控锁状态。


6. 示例场景

  • 幻读预防:RR级别下,SELECT * FROM t WHERE id > 100 FOR UPDATE会加临键锁,阻止其他事务插入id>100的记录。

  • MDL阻塞:长时间未提交的SELECT会阻塞ALTER TABLE,需监控SHOW PROCESSLIST处理。



评论