数据迁移项目的踩坑复盘:亿级数据从 MySQL 到 TiDB 的平滑迁移
数据迁移项目的踩坑复盘亿级数据从 MySQL 到 TiDB 的平滑迁移一、迁移背景与方案选择我们核心业务的订单表在过去三年中从 300 万行增长到 1.8 亿行MySQL 的分库分表方案逐渐力不从心。跨分片查询需要应用层聚合运维复杂度随着分片数量线性增长。同时业务需要实时数据分析能力而 MySQL 的 OLAP 查询在亿级数据量下经常超时。经过三个月的技术选型和 POC 验证我们决定将订单相关数据迁移到 TiDB。选择 TiDB 的核心考量有三点兼容 MySQL 协议和生态迁移改造成本最低原生分布式架构支持弹性扩缩容未来 3~5 年的增长无需担心HTAP 能力可以在一套集群中同时支撑 OLTP 和 OLAP 场景无需额外构建数据仓库。二、迁移工具链的选型与实践我们选择的工具链是 Dumpling全量导出 TiDB Lightning高速导入 TiCDC增量同步。这套组合是 TiDB 官方推荐的迁移方案但实际使用中仍有不少细节需要处理。Dumpling 导出环节配置了 16 个并发线程和 64MB 的文件大小分片。1.8 亿行数据导出为约 4200 个 SQL 文件总耗时 2.3 小时。需要注意的关键点是必须在业务低峰期执行并开启一致性快照--snapshot参数指定时间戳确保导出的数据是某个时间点的一致性视图。Lightning 导入环节选择 Local 模式以获取最大吞吐。16 个 TiKV 节点的集群配置下Lightning 的导入速度达到 38000 rows/s全量导入耗时约 80 分钟。这里踩过一个坑Lightning 导入期间如果 TiKV 的 compaction 跟不上写入会急剧下降。解决方法是在导入前手动触发一次全量 compaction并将region-split-size调整为 256MB。TiCDC 增量同步是最关键的环节。Lightning 完成全量导入后TiCDC 开始从 Dumpling 的快照时间点捕获 MySQL binlog 增量。我们的 binlog 格式设置为 ROW 模式确保 TiCDC 能正确解析每行变更。/** * 数据一致性校验服务——迁移后的行级比对 */ Service public class DataConsistencyChecker { private static final int BATCH_SIZE 50000; private static final int COMPARE_THREADS 8; Resource private JdbcTemplate mysqlTemplate; Resource private JdbcTemplate tidbTemplate; /** * 基于主键分片的行级数据比对 */ public ConsistencyReport checkTable(String tableName, long minId, long maxId) { ExecutorService executor Executors.newFixedThreadPool(COMPARE_THREADS); ListCompletableFutureSegmentResult futures new ArrayList(); long segmentSize (maxId - minId) / COMPARE_THREADS; for (int i 0; i COMPARE_THREADS; i) { long startId minId i * segmentSize; long endId (i COMPARE_THREADS - 1) ? maxId : startId segmentSize; futures.add(CompletableFuture.supplyAsync( () - compareSegment(tableName, startId, endId), executor)); } ConsistencyReport report new ConsistencyReport(); for (CompletableFutureSegmentResult future : futures) { try { SegmentResult result future.get(30, TimeUnit.MINUTES); report.merge(result); } catch (TimeoutException e) { log.error(比对超时tableName{}, tableName); report.markIncomplete(); } catch (Exception e) { log.error(比对异常tableName{}, tableName, e); report.markIncomplete(); } } executor.shutdown(); log.info(表{}比对完成: 一致{}, 差异{}, 缺失{}, tableName, report.getMatchCount(), report.getDiffCount(), report.getMissingCount()); return report; } private SegmentResult compareSegment(String tableName, long startId, long endId) { SegmentResult result new SegmentResult(); long lastId startId; while (lastId endId) { long batchEnd Math.min(lastId BATCH_SIZE, endId); // 从MySQL读取一个批次的数据 MapLong, String mysqlData loadBatch(mysqlTemplate, tableName, lastId, batchEnd); // 从TiDB读取同一批次的数据 MapLong, String tidbData loadBatch(tidbTemplate, tableName, lastId, batchEnd); // 逐行比对 for (Map.EntryLong, String entry : mysqlData.entrySet()) { Long id entry.getKey(); String mysqlValue entry.getValue(); String tidbValue tidbData.get(id); if (tidbValue null) { result.addMissing(id); } else if (!Objects.equals(mysqlValue, tidbValue)) { result.addDiff(id, mysqlValue, tidbValue); } else { result.addMatch(id); } } lastId batchEnd; } return result; } private MapLong, String loadBatch(JdbcTemplate template, String tableName, long startId, long endId) { String sql String.format( SELECT id, MD5(CONCAT_WS(|, %s)) AS row_hash FROM %s WHERE id ? AND id ?, getColumnList(tableName), tableName); MapLong, String result new LinkedHashMap(); template.query(sql, rs - { result.put(rs.getLong(id), rs.getString(row_hash)); }, startId, endId); return result; } }三、灰度切流与回滚预案切换阶段的设计原则是任何环节都必须可回滚。我们的切流方案分为四个阶段阶段一双写验证持续 3 天。应用层同时写入 MySQL 和 TiDB读操作仍走 MySQL。通过数据一致性校验工具对比两边的数据发现差异后立即修复。这一阶段发现了两个问题一是 TiDB 的事务隔离级别与 MySQL 的差异导致部分并发写入产生了轻微的顺序差异二是个别表的自增 ID 在 TiDB 上分配策略不同需要调整为 AUTO_RANDOM。阶段二10% 灰度读持续 1 天。随机选取 10% 的用户将查询路由到 TiDB监控延迟和错误率。如果出现异常如 P99 延迟超过 200ms 或错误率超过 0.1%自动切回 MySQL。阶段三逐步放量持续 2 天。按 10% → 50% → 100% 的节奏扩大读 TiDB 的比例每次放量后观察监控至少 2 小时。阶段四MySQL 停写下线。确认 TiDB 稳定运行 72 小时后停止对 MySQL 的写入完成最终的数据一致性校验正式下线 MySQL 源库。/** * 流量路由控制——支持动态切换MySQL/TiDB数据源 */ Component public class MigrationRouter { Resource Qualifier(mysqlDataSource) private DataSource mysqlDataSource; Resource Qualifier(tidbDataSource) private DataSource tidbDataSource; /** * 根据用户ID哈希决定读流量走向 */ public DataSource routeRead(Long userId) { MigrationConfig config getMigrationConfig(); if (config.isReadAllTiDB()) { return tidbDataSource; // 全量切换到TiDB } // 按用户ID取模实现灰度比例 int hash Math.abs(userId.hashCode()) % 100; if (hash config.getReadPercent()) { return tidbDataSource; } return mysqlDataSource; } /** * 写操作双写阶段同时写两端TiDB写入失败不影响主流程 */ public void dualWrite(Long userId, Runnable writeOperation) { // 主库写入当前仍为MySQL writeOperation.run(); // 副库异步写入TiDB异常不影响主流程 CompletableFuture.runAsync(() - { try { DataSourceHolder.set(tidbDataSource); writeOperation.run(); } catch (Exception e) { log.error(TiDB双写失败userId{}, userId, e); // 记录双写异常用于后续修复 dualWriteFailureRepository.record(userId, e.getMessage()); } finally { DataSourceHolder.clear(); } }); } }四、性能对比与踩坑记录迁移完成后我们对比了 MySQL 和 TiDB 在相同数据规模下的性能表现。在 TP 场景点查、小范围查询中TiDB 的 P99 延迟略高于 MySQL约高 15%~20%这是分布式数据库的固有开销但仍在业务可接受范围内 10ms。在 AP 场景聚合查询、跨月报表中TiDB 的性能提升显著月度营收报表的查询时间从 47 秒降至 2.3 秒。踩坑记录中最值得分享的几条TiDB 不支持存储过程和触发器迁移前需要将业务逻辑中的应用层代码替代AUTO_INCREMENT在 TiDB 中并非全局单调递增需要业务层不依赖 ID 的顺序语义大事务 100MB在 TiDB 中的性能远不如小批量提交建议事务大小控制在 10MB 以内。五、迁移复盘与经验提炼这次迁移从方案设计到最终下线 MySQL 源库历时 4 个月。核心经验归纳为三点第一充分验证是降低风险的关键双写验证阶段发现的 3 个兼容性问题如果进入生产后果严重第二渐进式切换比大爆炸式切换安全百倍灰度机制和自动回滚是底线保障第三迁移不只是数据搬家而是代码重构的契机存储过程到应用代码的迁移、自增 ID 到雪花 ID 的替换本质上是技术债清理。作者李然程序员鸭梨Java 架构师专注数据架构与企业级系统迁移实践。

相关新闻

(81页PPT)中小学智慧校园建设方案(附下载方式)

(81页PPT)中小学智慧校园建设方案(附下载方式)

篇幅所限,本文只提供部分资料内容,完整资料请看下面链接 https://download.csdn.net/download/2501_92808811/92962768 资料解读:中小学智慧校园建设方案 详细资料请看本解读文章的最后内容。本方案立足国家教育信息化发展战略,…

2026/7/22 10:11:36 阅读更多 →
一周防潮专题总结:PTC加热器选型5步法与核心参数详解

一周防潮专题总结:PTC加热器选型5步法与核心参数详解

本周系统探讨了PTC加热器在衣柜防潮和配电柜防结露场景的应用。选型看似复杂,其实只要掌握5个核心参数,小白也能选对产品。本文做一次技术性总结,涵盖选型方法论和参数计算公式。目录PTC加热器选型5步法5个核心参数详解功率计算公式本周场景应…

2026/7/22 10:11:36 阅读更多 →
企业内部 AI Chat 的产品化之路:从技术 Demo 到合规可运营的产品

企业内部 AI Chat 的产品化之路:从技术 Demo 到合规可运营的产品

企业内部 AI Chat 的产品化之路:从技术 Demo 到合规可运营的产品 一、技术 Demo 与真实产品之间的鸿沟 2025 年初,我们用两周时间搭建了一个基于 LangChain 企业知识库的内部问答 Demo。产品同事试用后评价:"回答准确率不太稳定&#x…

2026/7/22 10:11:36 阅读更多 →

最新新闻

汽车性能测试全流程:从新车基线到猎芯调校的技术解析

汽车性能测试全流程:从新车基线到猎芯调校的技术解析

在汽车性能测试领域,新车测试和猎芯测试是两种常见的评估方式,它们分别关注车辆出厂状态下的基础性能和经过特定调校后的极限表现。飞火通天单刷42.8秒和毒药猎芯榛名山49.7秒这两个成绩,通常出现在赛道计时或特定路段的性能对比中&#xff0…

2026/7/22 10:56:55 阅读更多 →
审计数据安全合规怎么落地?中注协准则、数据安全法、等保三级与留存期对比

审计数据安全合规怎么落地?中注协准则、数据安全法、等保三级与留存期对比

背景:审计数据合规不是"加个锁"就完事 会计师事务所手里是客户高度敏感的数据:财务、税务、流水、合同。近年监管对数据安全、个人信息保护、底稿留存的要求持续加码。把合规当成"技术部门的事"会出事——它是执业风险的一部分。 本…

2026/7/22 10:56:55 阅读更多 →
AI 审计评测基准怎么建?公开数据集、自建任务集与红队对抗的工程对比

AI 审计评测基准怎么建?公开数据集、自建任务集与红队对抗的工程对比

背景:AI 审计工具"好不好用"不能靠体感 团队引进一个 AI 审计工具,最常问的是"准不准、省不省事"。但"准"是个模糊词:勾稽检查准?底稿生成准?问答准?不定义清楚评测基准&…

2026/7/22 10:56:55 阅读更多 →
Unity地形渲染进阶:基于高度混合技术突破四层纹理限制

Unity地形渲染进阶:基于高度混合技术突破四层纹理限制

1. 项目概述:当四层纹理不再够用 在Unity地形系统的标准工作流里,美术和程序们对“四层纹理”这个限制应该都不陌生。无论是内置的Terrain系统,还是基于SplatMap的常见Shader方案,默认的纹理混合层数往往就卡在四层。对于一个小场…

2026/7/22 10:56:55 阅读更多 →
审计数据脱敏的工程实践:静态脱敏、动态脱敏、差分隐私与合成数据对比

审计数据脱敏的工程实践:静态脱敏、动态脱敏、差分隐私与合成数据对比

背景:审计数据"又要用、又不能泄露" 审计师拿到的数据是客户的"全副本":科目余额、序时账、客商明细、银行流水。这些数据既是分析原料,也是极高敏感度的商业机密。在把数据交给 AI 工具、外包团队或测试环境时&#xf…

2026/7/22 10:56:54 阅读更多 →
国内规格尺寸齐全的内存条测试治具厂商芯片检测利器

国内规格尺寸齐全的内存条测试治具厂商芯片检测利器

在芯片测试这个领域,内存条(DDR、LPDDR、HBM等)的检测一直是个老大难问题。封装规格多、尺寸变化快、技术迭代频繁,让不少工厂在选型测试治具时头疼不已。今天,我们就来聊聊这家深耕23年的国内厂商——深圳市谷易电子有…

2026/7/22 10:55:54 阅读更多 →

日新闻

TI DSP系统配置模块SYSCFG详解:中断机制与主设备优先级配置实战

TI DSP系统配置模块SYSCFG详解:中断机制与主设备优先级配置实战

1. 项目概述与SYSCFG模块的核心价值在嵌入式系统,尤其是像TI C6000系列这样的高性能DSP开发中,我们常常会与芯片手册里那些密密麻麻的寄存器打交道。很多开发者可能更关注算法实现、内存优化或者外设驱动,但对于一个稳定、高效的系统而言&…

2026/7/22 0:00:26 阅读更多 →
微信Server酱:高到达率的应急通知方案实践

微信Server酱:高到达率的应急通知方案实践

1. 为什么我们需要"最次"的通知方案? 在数字化协作环境中,消息通知系统的重要性不言而喻明。但现实情况是,企业级通知方案往往需要复杂的API对接(如企业微信、钉钉、飞书),个人开发者的小项目又经…

2026/7/22 0:00:26 阅读更多 →
甲方要的“简洁“PPT,到底是简洁还是省事?

甲方要的“简洁“PPT,到底是简洁还是省事?

甲方说"简洁一点",乙方听到的是"少做几页"。甲方说"不要太复杂",乙方理解成"别放图表了"。结果交过去,甲方说"我说的简洁不是这个意思"。"简洁"这个词在PPT语境里,是…

2026/7/22 0:00:26 阅读更多 →

周新闻

Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/22 8:58:19 阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/21 5:34:47 阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/21 8:25:39 阅读更多 →

月新闻