INSTANT DDL次数上限
| 版本 | 位宽 | 可表示范围 | INSTANT DDL 上限 | 每行额外开销 |
|---|---|---|---|---|
| MySQL 8.0 | 6 bit | 0–63 | 64 次 | 实际占 1 字节 |
| MySQL 9.1.0 | 8 bit | 0–255 | 256 次 | 同样 1 字节 |
一、MySQL8 INSTANT DDL可用次数上限为什么不能超过63次
Section titled “一、MySQL8 INSTANT DDL可用次数上限为什么不能超过63次”这个限制来自 InnoDB 物理行格式的存储设计。
1. 根本原因:行版本号(Row Version)的位宽限制
Section titled “1. 根本原因:行版本号(Row Version)的位宽限制”MySQL 8.0 的 INSTANT DDL 能快速执行的核心原理是:不重建整张表,只在数据字典里记录新列的元数据,然后在每行物理记录里额外存一个很小的”行版本号”(Row Version),用来告诉引擎”这行数据是按哪一个版本的表结构写入的”。
读取行时,InnoDB 拿行里的版本号对比数据字典里每一列的”加入版本”,就知道这行有没有该列、默认值是什么,不需要真正改过历史数据。
2. 为什么偏偏是 64
Section titled “2. 为什么偏偏是 64”行版本号被设计为 6 位整数,可表示的范围是 0–63,共 64 个不同的值:
- 版本
0表示”建表时的原始结构” - 每做一次 INSTANT DDL,版本号 +1
- 版本号到
63后,6 位已经用尽,再往上就溢出了
MySQL 选 6 位是在行头空间开销和可用次数之间的权衡——放在 extra bytes 里,尽量小,但又能支持合理次数的变更。
3. 超出后怎么办
Section titled “3. 超出后怎么办”执行一次表重建,版本号归零:
-- 任选一种,都会触发全表重建并重置版本计数器ALTER TABLE order_info FORCE;-- 或ALTER TABLE order_info ALGORITHM=INPLACE;-- 或OPTIMIZE TABLE order_info;重建之后所有历史行都被改写成当前最新结构,版本号重置为 0,64 次 INSTANT DDL 的配额重新开始计算。
| 关键点 | 说明 |
|---|---|
| 版本号位宽 | 6 bit → 最大值 63 → 64 种状态 |
| 每次 INSTANT DDL | 版本号 +1 |
| 达到上限后 | 不报错建议,直接拒绝 INSTANT,需手动重建 |
| 重置方式 | ALTER TABLE ... FORCE 或等价重建操作 |
二、MySQL9 INSTANT DDL可用次数上限为什么不能超过255次
Section titled “二、MySQL9 INSTANT DDL可用次数上限为什么不能超过255次”同样是行版本号的位宽变化,不过这次的逻辑更直接。
1. 从 6 位扩展到 8 位(一个完整字节)
Section titled “1. 从 6 位扩展到 8 位(一个完整字节)”MySQL 8.0 用 6 位存储行版本号,能表示 0–63 共 64 个值,0 是建表原始状态,所以 INSTANT DDL 上限是 63 次。
9.1.0 把行版本号扩展到 8 位(1 个字节),可表示 0–255 共 256 个值,0 保留给原始结构,所以 INSTANT DDL 可用次数变成 255 次。
2. 为什么偏偏是 256,而不是 128 或 512?
Section titled “2. 为什么偏偏是 256,而不是 128 或 512?”关键在于存储对齐。
6 位在内存里并不能单独存放——实际上还是要占用一个完整的字节边界空间。既然无论如何都要”用掉”一个字节,MySQL 9.1.0 干脆把版本号字段对齐到 1 字节,把 6 位扩展到 8 位,零额外存储成本,版本号容量直接翻 4 倍。
选 8 位而不是 16 位,是因为:
- 8 位已经足够绝大多数业务场景(正常表很少会 INSTANT DDL 超过 255 次而不做一次重建)
- 每行多存一个字节和多存两个字节,对大表的总存储影响差异可观
- 1 字节是最自然的字节对齐单位,实现最简洁
本质上是一次”既不花存储成本、又让上限翻倍”的改进——以前 6 位就已经占了一个字节的空间,那 2 位就别浪费了。
基于Starlight构建 | 主题色: Flexoki | 构建日期: 2026.09.10 | Change Log | Ko-fi