大表主键从int改为bigint的生产环境可行迁移策略
生产环境Int32主键迁移至BigInt的可行方案
针对大表(如你提到的15亿行级)直接执行ALTER COLUMN导致的长时间锁表、巨量日志问题,生产环境常用的低风险迁移方案如下:
方案一:影子列逐步迁移(推荐,低风险)
这是对业务影响最小的方案,适合无法长时间停服的场景:
- 在主表新增
NewId BIGINT列:如果原主键是自增类型,将NewId设为自增并设置初始值大于当前最大旧Id;若不是自增,先允许空,通过批量任务将旧Id值同步到NewId,同时创建触发器,确保新写入的行自动填充NewId。 - 在关联表新增
NewMainId BIGINT列:批量同步主表的NewId到该列,同样创建触发器,让新写入的关联数据自动同步NewMainId。 - 灰度切换应用代码:先修改读逻辑,优先使用新Id列;再逐步切换写逻辑,完全用
NewId和NewMainId进行数据操作。 - 收尾清理:确认所有流量都切换到新列后,删除旧的主键列、关联列及触发器,将
NewId设为主键,重建关联表的外键约束(关联NewId)。
优势:全程无锁表,日志量仅来自增量数据和批量同步的单条操作,对业务几乎无影响;劣势:需要修改应用代码,迁移周期较长。
方案二:分区交换迁移(适合支持分区的数据库)
如果你的数据库支持分区交换(如SQL Server、MySQL 8.0+),可以用这个方案快速完成迁移:
- 创建与原表结构一致的新表,将主键类型设为
BIGINT,并按旧Id范围预分区。 - 分批将原表数据导入新表:按旧Id的数值范围拆分批次,每导入一批就执行分区交换,将原表的分区数据直接切换到新表(无数据复制,速度极快)。
- 同步增量数据:通过CDC(变更数据捕获)或触发器,将迁移过程中原表的新增/修改数据同步到新表。
- 切换业务:将应用流量切换到新表,验证无误后删除旧表,将新表重命名为原表名,重建外键、索引等约束。
优势:迁移速度快,日志量极低;劣势:依赖数据库分区功能,操作复杂度较高,需要提前规划分区策略。
方案三:在线DDL工具迁移
利用成熟的在线DDL工具自动处理迁移,避免手动脚本的繁琐:
- 对于MySQL,使用
pt-online-schema-change工具,执行命令:
工具会自动创建临时表,逐步同步原表数据,通过触发器捕获增量变更,最后交换表名完成迁移。pt-online-schema-change --alter "MODIFY COLUMN Id BIGINT NOT NULL AUTO_INCREMENT" D=your_db,t=main_table - 对于SQL Server,使用
ALTER TABLE ... ALTER COLUMN时加上ONLINE = ON参数(需企业版),减少锁表时间。
优势:无需手动编写同步逻辑,工具自动处理增量,不锁表;劣势:需要安装第三方工具,大表迁移仍需一定时间,但日志量远低于直接执行ALTER。
针对你的两张表的具体建议
你的主表单条数据量小,关联表是int+varchar复合主键,优先选择影子列方案:
- 主表新增
NewId并同步数据,触发器同步增量; - 关联表新增
NewMainId,同步主表NewId,触发器同步增量; - 先修改关联表的查询逻辑,用
NewMainId关联主表NewId,再切换写逻辑; - 最后清理旧列,重建约束。
关键注意事项
- 迁移前必须做全量备份,且在测试库完整验证所有步骤;
- 批量同步时可临时调整数据库日志模式(如SQL Server改成简单恢复模式),减少日志生成;
- 增量同步阶段要定期校验数据一致性,避免新旧数据出现差异;
- 应用切换采用灰度发布,先切小流量验证,再逐步全量切换。
内容的提问来源于stack exchange,提问作者bearpro
相关产品推荐
相关产品推荐

