0029. MySQL 8.0 新特性 - InnoDB 增强功能
1. 📝 概述
- MySQL 8.0 对 InnoDB 的增强主要集中在 提高数据一致性、恢复能力和性能调优灵活性 上,特别是在自增主键、索引损坏识别和死锁控制方面提供了更稳定可靠的机制。
- 自增主键持久化:自增值写入 redo log,重启后可恢复。
- 索引损坏标志持久化:损坏标志写入 redo log 和系统表,提高恢复准确性。
- 死锁检测开关:动态变量
innodb_deadlock_detect
可关闭死锁检测,提升高并发性能。
功能 | MySQL 8.0 之前 | MySQL 8.0 |
---|---|---|
自增主键持久化 | 不支持,重启可能丢失当前计数 | 支持,计数器写入 Redo Log |
索引损坏标志持久化 | 不支持,重启后丢失损坏信息 | 支持,写入 Redo Log 和系统表 |
死锁检测控制 | 无法关闭,始终启用 | 支持动态开关 innodb_deadlock_detect |
2. 📒 自增主键(AUTO_INCREMENT)持久化
- MySQL 8.0 之前的问题
- 自增主键的计数器只保存在内存中。
- 如果数据库异常重启或宕机,InnoDB 可能会重复使用已经分配过的自增值,导致主键冲突或数据不一致。
- MySQL 8.0 的改进
- 自增计数器被写入 Redo Log(重做日志)
- 每次计数器发生改变,都会将其写入重做日志中。
- 数据库重启时,InnoDB 会从 Redo Log 中读取最后一次记录的自增值,重新初始化内存中的计数器。
- 不会立即刷新 Redo Log(为减少性能影响)
- 为了尽量减小对系统性能的影响,计数器写入重做日志时,并不会马上刷新数据库系统。
- 在事务提交时异步写入 Redo Log,不影响插入性能。
- 自增计数器被写入 Redo Log(重做日志)
- 示例:即使数据库崩溃重启,也不会丢失当前的最大自增值。
3. 📒 索引损坏标志持久化
- MySQL 8.0 之前的问题
- 当索引损坏时,InnoDB 仅将损坏标志保留在内存中。
- 如果数据库重启:
- 内存中的损坏信息丢失。
- InnoDB 无法准确判断哪些索引是真正损坏的,可能导致误修复或数据恢复失败。
- MySQL 8.0 的改进
- 损坏标志写入 Redo Log 和系统表
- 每次检查点(Checkpoint)时,InnoDB 将损坏标志写入专用系统表和 Redo Log,从而使得损坏标志更安全,更持久。
- 恢复时合并两个位置的信息
- 在恢复期间,InnoDB 从两个位置读取损坏标志并在将内存表和索引对象标记为损坏之前合并结果。
- 确保数据库重启后能准确识别哪些索引已损坏,避免错误访问。
- 损坏标志写入 Redo Log 和系统表
- 示例:即使服务器意外断电,也能正确识别并标记损坏的索引对象。
4. 📒 死锁检测控制开关(innodb_deadlock_detect)
- MySQL 8.0 之前的问题
- 死锁检测是 硬编码开启的,无法关闭。
- 在高并发场景下:
- 大量线程等待同一个锁时,死锁检测频繁运行,反而影响性能。
- 特别是在 OLTP 高负载系统中,可能导致性能下降。
- MySQL 8.0 的改进
- 引入动态变量
innodb_deadlock_detect
可用于禁用死锁检测- 默认值为
ON
,即启用死锁检测 - 可通过配置设置为
OFF
,禁用死锁检测
- 默认值为
- 在高并发系统上,当许多线程等待同一个锁时,死锁检测会导致速度减慢,此时禁用死锁检测可能更有效。
- 引入动态变量
sql
-- 关闭死锁检测
SET GLOBAL innodb_deadlock_detect = OFF;
1
2
2
- 注意:关闭死锁检测后,死锁不会自动回滚,需要应用层处理超时机制。
- 示例:适用于高并发写入、短事务为主的系统,如秒杀、队列等场景。