1. 使用percona-toolkit
原理是创建一个影子表,在影子表上执行 ALTER,然后通过 触发器(Triggers) 同步增量数据,最后完成替换。
命令
# 测试运行,返回很多OK即可
docker run --rm -it percona/percona-toolkit \
pt-online-schema-change \
--host=172.18.0.1 \
--user=root \
--port=13306 \
--password='123456' \
--alter "MODIFY COLUMN isp_group VARCHAR(20) GENERATED ALWAYS AS (CASE WHEN isp LIKE '%gmail%' THEN 'Gmail' WHEN isp LIKE '%outlook%' THEN 'Outlook' WHEN isp LIKE '%163%' THEN '163' WHEN isp LIKE '%126%' THEN '126' WHEN isp LIKE '%qq%' THEN 'QQ' WHEN isp LIKE '%sina%' THEN 'Sina' WHEN isp LIKE '%yahoo%' THEN 'Yahoo' WHEN isp LIKE '%hotmail%' THEN 'Hotmail' WHEN isp LIKE '%aol%' THEN 'AOL' WHEN isp LIKE '%foxmail%' THEN 'Foxmail' WHEN isp LIKE '%softbank%' THEN 'Softbank' WHEN isp LIKE '%naver%' THEN 'Naver' WHEN isp LIKE '%icloud%' THEN 'iCloud' WHEN isp LIKE '%hanmail%' THEN 'Hanmail' WHEN isp LIKE '%docomo%' THEN 'Docomo' WHEN isp LIKE '%.au.com%' THEN 'AU' WHEN isp LIKE 'au.com%' THEN 'AU' WHEN isp LIKE '%ezweb.ne.jp%' THEN 'AU' ELSE 'other' END) VIRTUAL" \
D=stats,t=email_isp_stats \
--dry-run
# 执行
docker run --rm -it percona/percona-toolkit \
pt-online-schema-change \
--host=172.18.0.1 \
--user=root \
--port=13306 \
--password='123456' \
--alter "MODIFY COLUMN isp_group VARCHAR(20) GENERATED ALWAYS AS (CASE WHEN isp LIKE '%gmail%' THEN 'Gmail' WHEN isp LIKE '%outlook%' THEN 'Outlook' WHEN isp LIKE '%163%' THEN '163' WHEN isp LIKE '%126%' THEN '126' WHEN isp LIKE '%qq%' THEN 'QQ' WHEN isp LIKE '%sina%' THEN 'Sina' WHEN isp LIKE '%yahoo%' THEN 'Yahoo' WHEN isp LIKE '%hotmail%' THEN 'Hotmail' WHEN isp LIKE '%aol%' THEN 'AOL' WHEN isp LIKE '%foxmail%' THEN 'Foxmail' WHEN isp LIKE '%softbank%' THEN 'Softbank' WHEN isp LIKE '%naver%' THEN 'Naver' WHEN isp LIKE '%icloud%' THEN 'iCloud' WHEN isp LIKE '%hanmail%' THEN 'Hanmail' WHEN isp LIKE '%docomo%' THEN 'Docomo' WHEN isp LIKE '%.au.com%' THEN 'AU' WHEN isp LIKE 'au.com%' THEN 'AU' WHEN isp LIKE '%ezweb.ne.jp%' THEN 'AU' ELSE 'other' END) VIRTUAL" \
D=stats,t=email_isp_stats \
--execute \
--progress
优缺点
- 优点:非常成熟,自动处理主从延迟监控。
- 注意:原表上不能已有触发器(Triggers),否则无法运行。
2. 使用 gh-ost (GitHub 开源,更安全)
gh-ost 的原理是不使用触发器,而是通过 解析二进制日志(Binlog) 来同步数据。它对系统负载的影响更小,且可以随时暂停。
前提条件
- MySQL 开启了 binlog。
- binlog_format 必须设置为 ROW。
该工具需要连接到实例并具有副本(Replica)或直接在主库上运行(需指定 --allow-on-master)。
下载
# 下载 wget https://gh-proxy.org/https://github.com/github/gh-ost/releases/download/v1.1.7/gh-ost-binary-linux-amd64-20241219160321.tar.gz # 解压 tar -zxvf gh-ost-binary-linux-amd64-20241219160321.tar.gz # 移动到可执行目录 sudo mv gh-ost /usr/local/bin/命令
# 测试执行 gh-ost \ --host=172.18.0.1 \ --user=root \ --port=13306 \ --password='123456' \ --database="stats" \ --table="email_isp_stats" \ --verbose \ --alter="MODIFY COLUMN isp_group VARCHAR(20) GENERATED ALWAYS AS (CASE WHEN isp LIKE '%gmail%' THEN 'Gmail' WHEN isp LIKE '%outlook%' THEN 'Outlook' WHEN isp LIKE '%163%' THEN '163' WHEN isp LIKE '%126%' THEN '126' WHEN isp LIKE '%qq%' THEN 'QQ' WHEN isp LIKE '%sina%' THEN 'Sina' WHEN isp LIKE '%yahoo%' THEN 'Yahoo' WHEN isp LIKE '%hotmail%' THEN 'Hotmail' WHEN isp LIKE '%aol%' THEN 'AOL' WHEN isp LIKE '%foxmail%' THEN 'Foxmail' WHEN isp LIKE '%softbank%' THEN 'Softbank' WHEN isp LIKE '%naver%' THEN 'Naver' WHEN isp LIKE '%icloud%' THEN 'iCloud' WHEN isp LIKE '%hanmail%' THEN 'Hanmail' WHEN isp LIKE '%docomo%' THEN 'Docomo' WHEN isp LIKE '%.au.com%' THEN 'AU' WHEN isp LIKE 'au.com%' THEN 'AU' WHEN isp LIKE '%ezweb.ne.jp%' THEN 'AU' ELSE 'other' END) VIRTUAL" \ # 正式执行 gh-ost \ --host=172.18.0.1 \ --user=root \ --port=13306 \ --password='123456' \ --database="stats" \ --table="email_isp_stats" \ --verbose \ --alter="MODIFY COLUMN isp_group VARCHAR(20) GENERATED ALWAYS AS (CASE WHEN isp LIKE '%gmail%' THEN 'Gmail' WHEN isp LIKE '%outlook%' THEN 'Outlook' WHEN isp LIKE '%163%' THEN '163' WHEN isp LIKE '%126%' THEN '126' WHEN isp LIKE '%qq%' THEN 'QQ' WHEN isp LIKE '%sina%' THEN 'Sina' WHEN isp LIKE '%yahoo%' THEN 'Yahoo' WHEN isp LIKE '%hotmail%' THEN 'Hotmail' WHEN isp LIKE '%aol%' THEN 'AOL' WHEN isp LIKE '%foxmail%' THEN 'Foxmail' WHEN isp LIKE '%softbank%' THEN 'Softbank' WHEN isp LIKE '%naver%' THEN 'Naver' WHEN isp LIKE '%icloud%' THEN 'iCloud' WHEN isp LIKE '%hanmail%' THEN 'Hanmail' WHEN isp LIKE '%docomo%' THEN 'Docomo' WHEN isp LIKE '%.au.com%' THEN 'AU' WHEN isp LIKE 'au.com%' THEN 'AU' WHEN isp LIKE '%ezweb.ne.jp%' THEN 'AU' ELSE 'other' END) VIRTUAL" \ --allow-on-master \ --execute优缺点
- 优点:不需要触发器,不锁表,可以动态调整迁移速度,迁移过程可监控(通过监听 TCP 端口)。
缺点:配置相对比 pt-osc 复杂一点。
核心参数说明
- --allow-on-master: 允许直接在主库上操作(不推荐生产环境这样做,但如果没有从库,必须加这个)。
- --serve-socket-file=/tmp/gh-ost.sock: 允许你通过交互式命令查看进度。
- --panic-flag-file=/tmp/ghost.panic.flag: 非常有用! 如果你发现服务器压力太大,只需在桌面上创建一个这个文件,gh-ost 会立即停止操作并清理现场。
- --max-lag-millis=1000: 如果从库延迟超过 1 秒,自动暂停同步。
--chunk-size=1000: 每次拷贝多少行数据。
监控进度
# 查看详细进度 echo "status" | nc -U /tmp/gh-ost.sock # 甚至可以动态调整速度(不需要重启任务) echo "throttle" | nc -U /tmp/gh-ost.sock # 暂停任务 echo "no-throttle" | nc -U /tmp/gh-ost.sock # 恢复任务总结:选 pt-osc 还是 gh-ost?
- 如果你已经跑通了 pt-osc 的 --dry-run:建议直接用 pt-osc。因为它更简单,不依赖 Binlog 权限。
- 如果你的表上有触发器(Triggers):必须用 gh-ost。
- 如果你非常担心业务压力:用 gh-ost,因为你可以随时在不停止任务的情况下让它“慢一点”。
暂无评论