数据迁移项目的踩坑复盘:亿级数据从 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/8/18 12:05:00 阅读更多 →
一周防潮专题总结:PTC加热器选型5步法与核心参数详解

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

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

2026/8/16 21:05:29 阅读更多 →
企业内部 AI Chat 的产品化之路:从技术 Demo 到合规可运营的产品

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

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

2026/8/11 2:26:14 阅读更多 →

最新新闻

基于STM32与USB2.0的自制虚拟示波器:从ADC采样到上位机显示全解析

基于STM32与USB2.0的自制虚拟示波器:从ADC采样到上位机显示全解析

1. 项目概述:为什么我们需要“另一个”USB示波器?“YetAnother USB Oscilloscope”,这个标题本身就带着一种自嘲和务实。在开源硬件和嵌入式开发社区,基于USB接口的简易示波器项目层出不穷,从早期的基于PC声卡的音频示…

2026/8/19 3:12:10 阅读更多 →
ESP32新手完全指南:从环境搭建到Web服务器实战

ESP32新手完全指南:从环境搭建到Web服务器实战

1. 项目概述:为什么是ESP32? 如果你对物联网、智能家居或者嵌入式开发感兴趣,但又被复杂的硬件选型和晦涩的开发环境劝退,那么ESP32几乎是你绕不开的“新手村神器”。我第一次接触ESP32是在几年前的一个智能灯项目里,当…

2026/8/19 3:12:10 阅读更多 →
多智能体LLM中KV缓存传递的因果审计与性能边界分析

多智能体LLM中KV缓存传递的因果审计与性能边界分析

1. 从“接力棒”到“绊脚石”:多智能体LLM中KV缓存的隐秘对话最近在折腾一个多智能体LLM的应用项目,几个模型像接力赛一样协同工作,处理一个复杂的推理任务。最初的设想很美好:前一个模型的输出,作为KV缓存&#xff08…

2026/8/19 3:12:10 阅读更多 →
搜索辅助联合智能体-环境强化学习:解决终身多智能体路径规划与旋转难题

搜索辅助联合智能体-环境强化学习:解决终身多智能体路径规划与旋转难题

1. 从“寻路”到“终身学习”:MAPF问题的现实挑战与演进在机器人、仓储物流和游戏AI等领域,让多个智能体(机器人、虚拟角色)在共享的复杂环境中,从各自的起点高效、无碰撞地移动到目标点,是一个经典且核心的…

2026/8/19 3:12:10 阅读更多 →
多智能体大模型潜在通信价值审计:接力KV缓存何时有效?

多智能体大模型潜在通信价值审计:接力KV缓存何时有效?

1. 项目概述:多智能体大模型中的潜在通信价值审计最近在折腾多智能体大语言模型(Multi-Agent LLMs)的推理优化,一个绕不开的瓶颈就是通信开销。当多个智能体协同工作时,它们之间需要交换信息,传统的做法是传…

2026/8/19 3:12:10 阅读更多 →
从Grill-Me项目看AI代码审查与领域驱动设计实践

从Grill-Me项目看AI代码审查与领域驱动设计实践

1. 项目概述:一个“招牌技能”的诞生与隐退最近在开发者社区里,一个话题引起了不小的讨论:Matt Pocock,这位在TypeScript和前端领域颇具影响力的开发者,将他个人GitHub上一个获得了超过17万颗星(star&#…

2026/8/19 3:11:10 阅读更多 →

日新闻

【单片机课程设计/毕业设计】基于 STM32 与 WiFi 模块的室内通风智能管控系统设计 基于 STM32 的人体存在感知自适应风扇控制系统设计(018503)

【单片机课程设计/毕业设计】基于 STM32 与 WiFi 模块的室内通风智能管控系统设计 基于 STM32 的人体存在感知自适应风扇控制系统设计(018503)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于嵌入式单片机,Java、小程序技术领域和毕业项目实战 ✌️…

2026/8/19 0:00:30 阅读更多 →
AI如何驱动数学猜想生成:从大语言模型到自动化数学发现

AI如何驱动数学猜想生成:从大语言模型到自动化数学发现

1. 项目概述:当AI开始“猜”数学定理 最近在AI研究圈里,一个名为“Moonshine”的项目引起了不小的讨论。这名字本身就挺有意思,直译是“月光”,但在数学史上,它特指一个神秘而美丽的联系——魔群月光猜想,连…

2026/8/19 0:00:30 阅读更多 →
WarcraftHelper 魔兽争霸3优化实战指南

WarcraftHelper 魔兽争霸3优化实战指南

WarcraftHelper 魔兽争霸3优化实战指南 【免费下载链接】WarcraftHelper Warcraft III Helper , support 1.20e, 1.24e, 1.26a, 1.27a, 1.27b 项目地址: https://gitcode.com/gh_mirrors/wa/WarcraftHelper 一台刚配的新电脑,跑《魔兽争霸3》却卡成 PPT——这…

2026/8/19 0:02:31 阅读更多 →

周新闻

基于阿里云与通义千问(Qwen)构建AI应用:从模型调用到生产部署的完整实践指南

基于阿里云与通义千问(Qwen)构建AI应用:从模型调用到生产部署的完整实践指南

如果你是一名开发者,最近可能已经感受到了AI大模型正在从“玩具”变成“生产力工具”的强烈信号。从代码补全到智能Agent,从本地部署到云端API,我们正处在一个技术栈快速重构的节点。然而,面对层出不穷的模型、框架和工具&#xf…

2026/8/18 9:15:35 阅读更多 →
工业通信系统底层逻辑:04 反射——高频能量撞墙之后会发生什么?

工业通信系统底层逻辑:04 反射——高频能量撞墙之后会发生什么?

第四篇:反射——高频能量撞墙之后会发生什么? —— 你以为信号已经过去了,其实它正在回来打你 老Q的现场笔记 第五季,我们正式进入工业神经系统层。这里不再是单个设备的战斗,而是整个工厂“经脉”层面的秩序之战。从这一篇开始,你将第一次看清:看似简单的信号传播,背…

2026/8/18 9:06:28 阅读更多 →
【文章复现】非线性值迭代自适应动态规划(ADP):离散时间非线性系统的策略迭代自适应动态规划算法研究附Matlab代码

【文章复现】非线性值迭代自适应动态规划(ADP):离散时间非线性系统的策略迭代自适应动态规划算法研究附Matlab代码

✅作者简介:热爱科研的Matlab仿真开发者,擅长毕业设计辅导、数学建模、数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。🍎 往期回顾关注个人主页:Matlab科研工作室👇 关注我领取海量matlab电子书和…

2026/8/18 9:04:56 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/17 18:54:37 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/17 18:55:16 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/17 18:55:55 阅读更多 →