2026/03/102026/05/06技术约 2 分钟606 字

千万级 Mysql 表结构变更实战

在生产环境中,对千万级数据表直接执行 ALTER TABLE 进行结构修改,往往会导致表被锁定,从而阻塞写入操作,可能造成数据不一致或业务停顿。为了安全、无感知地变更大表结构,gh-ost 提供了一种高效、零停机的解决方案。

它通过创建镜像表全量+增量同步数据,最终使用原子级别的表重命名切换完成变更。整个过程可以随时暂停,对业务几乎无影响,非常适合 500 万条以上的大表操作。

gh-ost

生产环境最常用, 适用于 500 万条数据以上

https://github.com/github/gh-ost

工作原理

  1. 创建镜像表
t_dir_gho
  1. 同步原表数据(t_dir)
copy data
  1. binlog 增量同步
实时同步变更
  1. 最终 原子切换, 将 t_dir 重命名为 t_dir_old, 将 t_dir_gho 重命名为 t_dir
rename table

优点:

  • rename 表是原子操作
  • 不停写, 因为是镜像表的缘故,除了全量同步,同时通过 binlog 订阅原表对镜像表进行增量同步
  • 可随时暂停
  • 对业务无感

实际上在表切换的过程中,执行的以下 Sql 语句

RENAME TABLE t_dir TO t_dir_old,t_dir_new TO t_dir;

切换的时间< 1ms,在这 1msRename会锁表,假如说这一瞬间对原表(t_dir)进行写操作,那么会短暂停顿等待切换后的”t_dir”释放锁, 所以并不会造成数据丢失, 而且这1ms很短,对业务无感

常见使用示例

添加索引

gh-ost \
--host=127.0.0.1 \
--user=root \
--password=123456 \
--database=db \
--table=t_dir \
--alter="ADD INDEX idx_uid(uid)" \
--allow-on-master \
--execute

修改字段类型

例如:

INTBIGINT
gh-ost \
--host=127.0.0.1 \
--user=root \
--password=123456 \
--database=db \
--table=t_dir \
--alter="MODIFY COLUMN uid BIGINT" \
--allow-on-master \
--execute

添加字段

gh-ost \
--host=127.0.0.1 \
--user=root \
--password=123456 \
--database=db \
--table=t_dir \
--alter="ADD COLUMN status INT NOT NULL DEFAULT 0" \
--allow-on-master \
--execute

删除字段

gh-ost \
--host=127.0.0.1 \
--user=root \
--password=123456 \
--database=db \
--table=t_dir \
--alter="DROP COLUMN temp_field" \
--allow-on-master \
--execute

重命名字段

gh-ost \
--host=127.0.0.1 \
--user=root \
--password=123456 \
--database=db \
--table=t_dir \
--alter="CHANGE old_name new_name VARCHAR(255)" \
--allow-on-master \
--execute

添加 NOT NULL 字段

gh-ost \
--host=127.0.0.1 \
--user=root \
--password=123456 \
--database=db \
--table=t_dir \
--alter="ADD COLUMN status INT NOT NULL DEFAULT 0" \
--allow-on-master \
--execute

常用参数说明

参数说明示例
--hostMySQL 地址127.0.0.1
--portMySQL 端口3306
--user数据库用户名root
--password数据库密码123456
--database目标数据库db
--table目标表t_dir
--alter要执行的 DDLADD COLUMN size BIGINT
--execute真正执行变更不加则为 dry-run
--allow-on-master允许在主库执行常用
--chunk-size每批迁移行数1000
--max-load负载阈值Threads_running=20
--critical-load临界负载Threads_running=100
--cut-over切换策略default
--initially-drop-ghost-table若存在 ghost 表先删除安全
--initially-drop-old-table若存在 old 表先删除安全
--exact-rowcount精确统计行数避免误差
--verbose输出详细日志调试用

评论区