MySQL中查看当前表行格式应执行SHOW TABLE STATUS LIKE 'table_name'查Row_format列,全局默认用SELECT @@innodb_default_row_format;5.7.9+默认DYNAMIC,但升级老表仍可能为COMPACT;ALTER TABLE修改ROW_FORMAT会重建整表并锁表。

确认当前行格式和默认配置
直接查表比猜配置更可靠:SHOW TABLE STATUS LIKE 'table_name' 看 Row_format 列;查全局默认用 SELECT @@innodb_default_row_format。MySQL 5.7 默认是 DYNAMIC,但老表可能还是 COMPACT,尤其从 5.6 升级上来的。别依赖 my.ini 里有没有配 innodb_default_row_format——它只影响新表,对已有表无效。
ALTER TABLE 修改行格式的实际效果
ALTER TABLE table_name ROW_FORMAT=DYNAMIC; 这条语句会重建整张表,不是元数据更新。这意味着:
- 会锁表(
LOCK=DEFAULT时是LOCK=EXCLUSIVE),写入阻塞,大表操作务必选低峰期 - 触发一次全量页重组:B+Tree 叶子节点重排、二级索引重建、undo log 增长,磁盘 IO 和 buffer pool 压力明显升高
- 如果表有
FULLTEXT索引,且 MySQL 版本 DYNAMIC 不支持,会报错ERROR 1214 (HY000) - 修改后必须运行
ANALYZE TABLE table_name;,否则优化器统计信息滞后,可能导致执行计划劣化
想在线改?得满足硬性条件
MySQL 5.7 支持 ALGORITHM=INPLACE, LOCK=NONE 的在线 DDL,但仅限部分操作。行格式变更不在此列——它始终需要 ALGORITHM=COPY 或隐式重建。所谓“在线”只是指你可以加 ALGORITHM=INPLACE 让 MySQL 检查是否支持,但它会立刻报错:
ERROR 1845 (0A000): ALGORITHM=INPLACE is not supported for this operation.
所以别试了。真要减少停机时间,只能:
- 用
mysqldump --single-transaction导出 + 重建表(适合中小表) - 用 pt-online-schema-change(需 Perl 环境,主从延迟敏感)
- 业务层双写+灰度切流(最稳妥,但开发成本高)
改完之后容易被忽略的坑
行格式变更是物理结构变更,影响不止于存储空间:
-
DYNAMIC下 BLOB/TEXT 字段只存 20 字节指针,大幅降低聚簇索引页压力,但若字段频繁更新,会导致额外的二次查找开销 -
COMPRESSED需要innodb_file_per_table=ON且文件系统支持压缩,否则启动报错;压缩率受数据重复度影响极大,不是所有表都受益 - 备份工具(如 xtrabackup)对不同行格式的处理路径略有差异,升级前先在测试环境跑通全链路恢复
- 如果开启了
innodb_strict_mode=ON(5.7 默认开启),某些非法组合(比如ROW_FORMAT=COMPRESSED+KEY_BLOCK_SIZE=0)会直接拒绝建表或改表


















