把单机MySQL迁移到TiDB,本质上不是简单的数据搬运,而是一次架构升级。很多人以为只要把数据导过去就完事了,结果上线后碰到各种兼容性问题,甚至性能还不如原来的单机MySQL。核心难点在于,MySQL是单机数据库,而TiDB是分布式数据库,两者在SQL行为、事务模型、执行计划、索引设计思路上有本质差异。迁移的起点不是工具选型,而是先搞清楚哪些地方会踩坑,再规划步骤。
迁移前的兼容性检查清单动手之前,必须做一次全量的兼容性评估。TiDB兼容MySQL 5.7协议,但并不是100%兼容。最常出问题的是存储过程、触发器、函数、视图这些对象。TiDB从较新版本开始逐步支持存储过程,但复杂游标、多层嵌套调用仍然有限制。如果你的业务重度依赖存储过程,迁移前要逐个测试,必要时需要把逻辑拆到应用层。触发器在TiDB中虽然支持,但性能开销比MySQL大得多,因为分布式环境下每个触发器执行都涉及额外的协调开销。建议在迁移前梳理所有触发器的使用场景,能用应用逻辑替代的就替代掉。
外键是另一个重灾区。TiDB支持外键语法,但默认不强制检查,需要显式开启。即便开启了,分布式环境下的外键约束检查也会带来明显的性能损耗。大多数从MySQL迁移过来的团队,最终选择在应用层维护数据一致性,而不是依赖数据库层的外键。字符集和排序规则也要仔细核对,TiDB默认使用utf8mb4,排序规则与MySQL存在细微差异,尤其是涉及多语言排序和大小写敏感的场景。建议在测试环境用真实数据跑一遍全量SQL,用TiDB自带的工具检查不兼容的语句。
数据迁移工具的选择与使用细节目前最成熟的迁移工具是TiDB Data Migration,也就是DM。DM的核心能力是把MySQL作为上游,通过解析binlog实现全量加增量的实时同步。实际使用中,全量阶段用Dumpling导出数据,再通过TiDB Lightning导入,增量阶段用DM持续同步binlog。这里有个容易被忽略的细节:Dumpling导出时默认的并发度和分片策略需要根据MySQL服务器的IO能力调整,如果MySQL是生产环境,导出时要控制并发避免影响业务。TiDB Lightning导入时,建议开启本地排序模式,能大幅提升导入速度,但需要足够的磁盘空间做临时排序。
对于数据量在几百GB以内的库,直接用Dumpling加Lightning的全量导入,然后切源停写,把增量追平后切换,是最稳妥的方案。对于TB级的大库,则必须走全量加增量的在线迁移模式。在线迁移的关键在于增量同步的延迟控制。DM的同步延迟取决于binlog的解析速度和下游TiDB的写入能力。如果MySQL的binlog产生速度很快,比如秒杀场景的瞬时高峰,DM的同步延迟会瞬间拉大。这种情况下需要提前对TiDB集群做写入压测,确保下游能扛住峰值流量。另外,DM的同步任务需要配置合理的worker数量和batch大小,默认配置在大多数场景下够用,但遇到大事务时需要调整,否则同步会卡在单个大事务上。
还有一个容易踩坑的点是自增主键。MySQL的自增ID是单机生成的,TiDB的AUTO_INCREMENT默认是全局唯一的,但分配方式不同,可能导致ID不连续,或者在不同节点上产生ID空洞。如果你的业务逻辑强依赖自增ID的连续性和有序性,迁移前要评估是否改用AUTO_RANDOM或者Snowflake方案。AUTO_RANDOM能避免写热点,但ID不再是严格递增的,对依赖ID排序的业务有影响。
表结构与索引的适配改造把MySQL的表结构原样搬到TiDB,通常不是最优解。TiDB是分布式数据库,数据按照主键或者指定的分片键分散在多个节点上。如果主键是自增ID,写入热点会集中在最后一个Region,导致单点瓶颈。解决方案是把自增主键改为AUTO_RANDOM,或者把业务中的写入热点字段作为分片键。分片键的选择直接影响读写性能,需要根据实际的查询和写入模式来决定。比如订单表,如果大部分查询都是按用户ID过滤,那么用用户ID做分片键比用订单ID更合理。
索引设计也要重新思考。MySQL里一个复合索引可能解决多个查询,但在TiDB中,索引是全局的,跨节点的索引回表开销比MySQL大得多。覆盖索引的价值在TiDB里更高,因为能避免回表带来的网络开销。迁移前建议分析慢查询日志,把高频查询的索引都改成覆盖索引。另外,TiDB的统计信息收集机制和MySQL不同,默认会自动更新,但在数据量巨大且变更频繁的表上,统计信息可能不准确,导致执行计划走偏。迁移后要定期检查慢查询,必要时手动执行ANALYZE TABLE,或者调整统计信息的采样比例。
事务与SQL行为的差异处理TiDB的事务模型是乐观事务加悲观事务可选,默认是悲观事务。但即便开了悲观锁,TiDB的锁机制和MySQL的InnoDB行锁也有差异。TiDB的锁是在事务提交时才真正加锁,而不是在语句执行时。这意味着在高并发冲突场景下,TiDB的锁等待和死锁表现和MySQL不同。如果你的业务有大量并发更新同一行记录的场景,迁移后可能会遇到更多的锁冲突。解决办法是尽量缩短事务长度,把读和写拆开,或者用SELECT FOR UPDATE显式加锁。另外,TiDB的事务大小有上限,默认单事务不能超过100MB的KV数据,大事务需要拆分成小批量提交。
SQL语法层面,TiDB兼容大部分MySQL 5.7的语法,但有些函数和特性的行为不同。比如窗口函数、CTE在较新版本中才完全支持,部分字符串函数在处理NULL时的返回值与MySQL有差异。迁移前要用TiDB的兼容性检查工具扫描所有SQL,重点看报错和警告。对于不兼容的SQL,要么改写,要么在应用层做适配。还有一点容易被忽视,就是TiDB的查询优化器和MySQL的优化器不同,同一个SQL在TiDB上可能生成不同的执行计划。迁移后必须对核心SQL做执行计划对比,确保性能不退化。
迁移步骤的实战拆解第一步,搭建TiDB测试集群,配置与生产环境一致的拓扑结构。在测试环境用DM建立上游MySQL到下游TiDB的全量加增量同步,观察同步延迟和资源消耗。这一步能暴露大部分兼容性问题和性能瓶颈。第二步,在测试环境跑全量业务回归测试,重点验证SQL兼容性、事务正确性、查询性能。用生产环境的慢查询日志回放,对比执行时间和执行计划。第三步,制定正式迁移方案。对于允许停机的业务,选择低峰期停MySQL写,等DM追平增量后切换。对于不能停机的业务,采用双写方案,应用层同时写MySQL和TiDB,数据校验通过后再切读流量到TiDB,最后下掉MySQL的写。
第四步,正式迁移前做一次全量备份,无论是MySQL侧还是TiDB侧都要有回滚方案。TiDB的备份用BR工具,可以做到全量加增量的快速备份恢复。第五步,切换后进入观察期,重点监控TiDB的慢查询、Region分布、写入热点、TiKV的CPU和IO。前三天是关键窗口,大部分隐藏问题会在这个阶段暴露。观察期内保留MySQL的源数据至少一周,确保紧急情况下能回滚。
迁移后的性能调优与监控迁移完成只是开始,后续的调优工作决定了TiDB能否真正扛住生产流量。首先要关注Region的分布是否均衡。如果数据写入集中在少数Region,PD会自动分裂和调度,但在调度完成前,写入热点会导致延迟抖动。可以通过预切分Region的方式,在建表时就指定分片键的预切分数,让数据从一开始就均匀分布。其次要监控TiKV的写入放大和compaction压力,TiKV底层是RocksDB,写入高峰后会触发compaction,如果磁盘IO跟不上,会出现写入延迟飙升。解决办法是使用NVMe SSD,或者调整compaction的并发度和速率。
SQL调优方面,TiDB的慢查询日志格式和MySQL类似,但多了分布式相关的信息,比如copr任务耗时、Region数量等。分析慢查询时,要关注copr任务的执行时间,如果copr耗时占比高,说明计算下推到TiKV的效率不够,可能需要调整索引或者改写SQL。TiDB的SQL绑定功能可以在不修改应用代码的情况下,强制指定执行计划,对于无法改写的慢SQL非常有用。另外,TiDB的Plan Cache功能能减少执行计划生成的开销,对于高并发的点查场景提升明显。
整个迁移过程中,最大的成本往往不是工具和技术的使用,而是对分布式数据库行为差异的理解和适配。把单机MySQL的思维直接套到TiDB上,一定会碰到问题。只有理解了分布式数据库的底层逻辑,才能做出合理的架构调整,让迁移后的系统真正发挥出分布式架构的优势。
