MySQL死锁概述
- 定义:多个操作相互等待对方释放资源,导致无法继续执行的情况。
- 场景:通常发生在多个事务同时试图锁定对方已锁定的资源时。
MySQL锁的分类
-
粒度分类:
- 表级锁:锁定整个表,简单但并发能力低。
- 行级锁:锁定特定行,开销大,可能死锁,但并发度高。
- 页级锁:锁定数据库页,介于表级和行级之间。
-
操作类型分类:
- 读锁(S锁):允许读取,阻止写操作。
- 写锁(X锁):排他锁,阻止其他事务读写。
-
意向锁:表明事务对数据行加锁的意图。
-
性能分类:
- 乐观锁:假设冲突少,通过版本号或时间戳检查冲突。
- 悲观锁:假设冲突多,保持数据锁定直到事务完成。
InnoDB存储引擎行锁模式
- 记录锁:锁定具体数据,防止其他事务修改。
- 间隙锁:锁定范围但不包括记录,解决幻读问题。
- 临键锁:结合记录锁和间隙锁,锁定记录及其前空隙。
事务隔离级别与锁的关系
- 隔离级别:READ UNCOMMITTED, READ COMMITTED, REPEATABLE READ, SERIALIZABLE。
- MySQL默认:可重复读(REPEATABLE READ)。
- 隔离级别与锁:封装了锁机制和MVCC技术,简化并发控制。
死锁产生原因和解决方案
-
表级锁死锁:不同事务按不同顺序锁定资源。
- 解决方案:保持一致的锁定顺序,避免同时锁定两个资源。
-
行级锁死锁:
- 原因1:无索引条件查询导致全表扫描,行锁膨胀为表锁。
- 原因2:事务互相等待对方持有的锁。
- 解决方案:优化SQL语句,建立索引,避免复杂关联查询。
预防死锁优化实践
- 维持一致的锁定顺序。
- 使用最小的锁粒度,优先使用行级锁。
- 减少事务持续时间,优化查询语句。
- 使用锁超时,自动回滚等待超时的事务。
- 死锁检测和回滚,数据库自动检测并解决死锁。
- 避免不必要的锁,审查和优化事务逻辑。
- 使用乐观并发控制,适用于读多写少的场景。
- 避免无索引行锁升级为表锁,确保数据检索通过索引完成。
- 监控和日志记录,跟踪死锁和性能瓶颈。
总结
- 解决死锁:通过日志分析找到死锁并处理。
- 分析死锁原因:优化以避免死锁再次发生。