Skip to content

INSTANT DDL次数上限

版本位宽可表示范围INSTANT DDL 上限每行额外开销
MySQL 8.06 bit0–6364 次实际占 1 字节
MySQL 9.1.08 bit0–255256 次同样 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 拿行里的版本号对比数据字典里每一列的”加入版本”,就知道这行有没有该列、默认值是什么,不需要真正改过历史数据。

行版本号被设计为 6 位整数,可表示的范围是 0–63,共 64 个不同的值

  • 版本 0 表示”建表时的原始结构”
  • 每做一次 INSTANT DDL,版本号 +1
  • 版本号到 63 后,6 位已经用尽,再往上就溢出了

MySQL 选 6 位是在行头空间开销和可用次数之间的权衡——放在 extra bytes 里,尽量小,但又能支持合理次数的变更。

执行一次表重建,版本号归零:

-- 任选一种,都会触发全表重建并重置版本计数器
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