row_format=dynamic是启用innodb_large_prefix的必要条件,仅当其与innodb_large_prefix=on同时满足时,单列索引上限才从767字节提升至3072字节;compact/redundant格式下该参数无效,强制执行767字节硬限制。

Row Format决定InnoDB是否允许启用innodb_large_prefix
根本原因不是Row Format本身“限制字节数”,而是InnoDB把ROW_FORMAT=DYNAMIC或COMPRESSED作为启用innodb_large_prefix的开关。只有在这两种格式下,且innodb_large_prefix=ON(5.7.7+默认开启),单列索引上限才能从767字节升到3072字节;用COMPACT或REDUNDANT时,哪怕参数开了也强制走767字节硬限制。
常见错误现象:
- MySQL 5.7.10建的表,
SHOW CREATE TABLE里写了ROW_FORMAT=DYNAMIC,但SHOW TABLE STATUS显示仍是COMPACT - 执行
ALTER TABLE t ROW_FORMAT=DYNAMIC后,索引创建仍报ERROR 1071: Specified key was too long; max key length is 767 bytes
为什么COMPACT格式死守767字节?
这是InnoDB早期为Antelope文件格式设计的兼容性约束:COMPACT和REDUNDANT属于Antelope体系,其B+树节点结构固定预留空间小,无法安全容纳过长键值——否则会导致页分裂异常、缓存命中率下降甚至崩溃。767字节 ≈ 16KB页大小 / 20,是工程上平衡存储密度与查询性能的保守值。
关键影响点:
-
utf8mb4字段定义为varchar(255)→ 实际最大占255×4=1020字节 → 超767 → 创建索引失败 - 即使只对前191字符建索引(
INDEX(col(191))),只要表是COMPACT,该限制依然生效 -
innodb_page_size改小(如8KB)会进一步压缩上限:此时767字节限制按比例缩为约384字节
怎么确认你的表真用了DYNAMIC?
别信建表语句或配置文件,查元数据才靠谱:
- 运行
SELECT ROW_FORMAT FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'your_table' AND TABLE_SCHEMA = 'your_db';—— 返回必须是DYNAMIC - 执行
SHOW CREATE TABLE your_table;—— 输出里必须同时含ROW_FORMAT=DYNAMIC和KEY_BLOCK_SIZE=0(后者表示未启用压缩) - 旧表迁移时,仅
ALTER TABLE ... ROW_FORMAT=DYNAMIC不够,还需确保innodb_file_format=BARRACUDA(5.6需手动设,5.7+默认已满足)
ALTER TABLE改行格式时最常踩的坑
大表执行ALTER TABLE t ROW_FORMAT=DYNAMIC默认触发COPY算法,锁表时间可能长达数小时。真正安全的做法是:
- 显式加
ALGORITHM=INPLACE:例如ALTER TABLE t ROW_FORMAT=DYNAMIC, ALGORITHM=INPLACE; - 但注意:INPLACE仅在满足条件时才生效,比如不能有全文索引、不能是虚拟列主键等
- 若提示
ALGORITHM=INPLACE is not supported,说明必须走COPY,建议在低峰期操作并提前备份
Row Format不是“设置就生效”的装饰性参数,它是InnoDB底层存储逻辑的入口开关——改错格式,等于关掉了长索引的唯一通道。











