执行完ALTER TABLE后,查INFORMATION_SCHEMA.INNODB_TABLES中TOTAL_ROW_VERSIONS未变即为INSTANT生效;再查innodb_sys_columns新增记录、innodb_sys_tables flags第29位置位、innodb_sys_tablestats instant_cols递增,三者同时满足方可确认——否则静默降级。

怎么看ALGORITHM=INSTANT是否真的生效了
别只信自己写了ALGORITHM=INSTANT,MySQL会静默降级。执行完ALTER TABLE后,立刻查INFORMATION_SCHEMA.INNODB_TABLES确认真实行为:
-
SELECT NAME, TOTAL_ROW_VERSIONS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME = 'database/table_name'—— 如果TOTAL_ROW_VERSIONS没变,说明是INSTANT;变了就不是 - 同时查
SHOW CREATE TABLE table_name,确认ROW_FORMAT不是COMPRESSED,引擎是InnoDB,且无FULLTEXT索引 - 若报错
ERROR 1845 (0A000): ALGORITHM=INSTANT is not supported,大概率是隐式主键(8.0.12–8.0.27)、行格式不合规或混用了其他DDL操作
如何捕获Instant DDL在数据字典里的实际变更
INSTANT不改数据页,只改系统表。重点盯三个地方:
-
mysql.innodb_sys_columns:新列会立刻多一条记录,ord_part为0表示非主键列,mtype/prtype字段体现类型定义 -
mysql.innodb_sys_tables:检查flags字段,bit 29 置位表示该表启用了instant columns支持 -
mysql.innodb_sys_tablestats:instant_cols列会递增,每次INSTANT ADD/DROP都+1(注意:64次上限就在这里)
执行前后对比这三张表,就能确认“到底有没有动字典”,而不是靠SHOW PROCESSLIST里看不见锁就误判为成功。
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
为什么INSTANT加列后SELECT返回默认值,但磁盘上没这列
因为INSTANT不写老行,而是运行时合成。验证方法很直接:
- 用
SELECT * FROM table_name能看到新列和默认值,但SELECT HEX(data) FROM INNODB_BUFFER_PAGE WHERE TABLE_NAME='database/table_name'(需开启innodb_buffer_page)查缓存页,发现老行的二进制结构里根本没有这个字段 - 插入新行后,再查同一页的
HEX(data),会看到字段数据真实存在——说明新行才物理存储,老行靠字典元数据+默认值描述符动态拼接 - 删掉新列再加回来,
TOTAL_ROW_VERSIONS不变,但instant_cols会+1,证明是纯元数据操作
排查64次限制触发后的失败原因
INSTANT有硬性计数器,超限就彻底失效,且不报明确提示。排查步骤必须闭环:
- 先查
SELECT NAME, TOTAL_ROW_VERSIONS, INSTANT_COLS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME LIKE '%table%',确认INSTANT_COLS >= 64 - 注意:
TOTAL_ROW_VERSIONS是表级版本号,INSTANT_COLS才是瞬时列操作次数,二者不同步增长 - 一旦达上限,后续任何
ADD COLUMN ... ALGORITHM=INSTANT都会退回到INPLACE甚至COPY,且SHOW PROCESSLIST里State变成copy to tmp table或altering table,这时IO飙升就是信号 - 临时解法只有重建表:
CREATE TABLE t_new AS SELECT *, new_col DEFAULT 0 FROM t_old+RENAME,但会丢失INSTANT语义;长期需规划列变更频次或切分表
真正容易被忽略的是:这个64次限制是**每张表独立计数**,且不会因重启、flush或optimize重置。线上高频迭代的配置表、日志表最容易踩中,得提前监控INSTANT_COLS趋势。

















