资讯文章 资讯 · NEWS
给跑着的目录站加个字段:先问能不能 INSTANT,再谈别的工具
2026-10-23 约 1,317 字 预计阅读 3 分钟 yiyunkj
给
目录站做到一定规模,条目表加字段是家常便饭:要加个「是否付费」标记、要加个年审时间、要把简介字段从 200 字放宽到 500 字。开发在本地跑一条 ALTER 一秒钟完成,到了生产环境就变成另一回事。

图片来源:网络,版权归原作者所有,侵权请联系删除
第一问:这条 ALTER 能不能 INSTANT
MySQL 8.0 引入了 ALGORITHM=INSTANT,它的意思是只改数据字典、不动表数据,操作是常数时间,跟表多大没关系。8.0.12 起支持在末列加字段,8.0.29 起扩展到任意位置加列、删列、改列名等更多操作。
关键点是要显式写出来。不指定的话,不支持的操作会静默退化成 COPY 算法——整表重建、期间阻塞写入,你在监控上看到的就是一次不明原因的卡顿。
ALTER TABLE items ADD COLUMN annual_review_at DATETIME DEFAULT NULL, ALGORITHM=INSTANT;
显式写的好处是:做不到就报错,而不是悄悄变慢。这一条比什么都重要。
第二问:在线不等于不锁
就算能跑 INPLACE 甚至 INSTANT,一条 DDL 在开始和结束时都需要一个短暂的排他元数据锁。这个锁会被任何还开着的事务挡住——包括一个忘了提交的空闲连接、一条跑了五分钟的统计查询。
更麻烦的是,DDL 在等锁的时候,它自己那个待处理的排他请求会把后续所有查询都堵在后面。一个五秒钟的遗忘事务,能把一次「在线」操作变成整表停摆。
所以规矩是:改表前先查有没有长事务,并且把等待时间收短,拿不到锁就快速失败,换个时间再来。默认等待时间是一年,这个默认值在生产环境上就是陷阱。
重活才需要外部工具
改列类型、转字符集、改主键这类必须重建表的操作,INSTANT 和 INPLACE 都帮不上忙,这时才轮到两个工具:
| 方案 | 机制 | 适合什么 |
|---|---|---|
| 原生在线 DDL | 引擎自己做,INPLACE 不建影子表 | 加字段、加二级索引 |
| gh-ost | 不建触发器,靠读 binlog 追增量,可暂停可限速 | 有从库的大表重建 |
| pt-online-schema-change | 建影子表加三个触发器,分批拷贝后原子改名 | 单机无从库、有外键约束 |
gh-ost 的好处是不往原表加触发器,写入路径上没有同步开销,还能根据从库延迟自动限速;代价是要求行格式 binlog。pt-osc 是触发器方案,对老版本和有外键的表更友好,但触发器本身会给主库加同步负载。
目录站的实际规模其实用不到
说句实在话:绝大多数目录站的条目表在几万到几十万行,加个字段这种操作,8.0 上 INSTANT 就能秒完,根本不需要搬出工具。真正需要工具的是那种把访问日志、快照历史也塞进同一张表,攒到几千万行的设计。
所以第一反应应该是确认版本和算法,而不是抄一篇 gh-ost 教程。
改表顺序永远是:先改数据库结构,再发用上新字段的代码。反过来做,发布失败的时候你会同时面对旧结构和新代码。
收尾三件事
改完结构之后,别忘了下面三样:应用层的字段缓存要清,ORM 或模型定义要同步,站点里用到这个字段的搜索索引或导出模板要跟着改。这三处漏掉任何一处,表现都是「字段加上了但页面上没出现」。
另外,改表前那份备份要确认能恢复。备份存在和备份能恢复是两件事,改表这种操作,值得你先花十分钟验证一次。