MySQL表迁移

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/micro_hz/article/details/82837650

在互联网应用中需求快速迭代,很多时候可能需要对DB进行变更操作,例如增删字段,当然一般来说不会删除字段,因为这存在极大的风险,相比较添加字段风险会小很多,但是也要注意避开流量高峰进行操作,因为虽然MySQL5.6之后支持Online DDL一般情况不会锁表,但是对于大数据量的字段仍然会存在锁表风险,因此需要注意。


此次我遇到的是新老表主子分表的迁移问题。

  • 主要迁移的背景是:

老表的字段不够通用,很难覆盖多个场景,分表字段不合理存在而己分表。这两个条件导致需要迁移到新的表。
迁移的思路基本上就是先保证新老表双写
Id采用了公用一个表来自增,保证新表与老表的逻辑字段一致.
重新分表后新表的唯一键不存在冲突,例如老表的id在新表不能哈希到一张表。
最后开关切换读写新表,并替换到后面新的模型。到后面所有场景都验证过后,就可以下线新表了。
如果历史数据是有意义的,还需要写个定时任务去同步历史数据.同步完毕才能读新表。最好能灰度发布,充分验证。

  1. 读写老表
    在这里插入图片描述
    2.双写
    在这里插入图片描述

3.同步历史数据
在这里插入图片描述

4.读写新表
在这里插入图片描述


  • 存在的风险:
    1.框架风险
    还有需要注意的是SQL里面的SELECT * 可能会读到ORM框架的缓存,阿里的TDDL缓存就有类似的问题,由于物理分库分表会导致部分物理表有新字段,部分没有,这个时候TDDL会拿第一张表的meta信息去替换*,然后实际执行SQL的时候会读未添加字段的表,查出来没对应字段报错。
    2.外键风险,例如该表的id关联到外域的DB也是其他表的外键,新表的id如果不与老表一致,会导致外键重复,存在不可预知的风险,例如根据id去查关系表可能查出历史数据。
    3.切换风险,避免流量高峰,开关保证,验证工具,日志记录都应该保证,避免高峰需要分析业务特点不必多说,开关保证能够模拟线上迁移报错之后避免回滚不及时能够立马切换代码逻辑,日志记录是记录每次关键的操作,才上线可以打印的很详细,验证过后其实没必要再记录,为了避免磁盘空间的紧张,可以增加日志开关,避免不必要的空间浪费。验证工具是基本的一些核心数据能够迅速的去批量扫描数据的完整性。
    4.业务兼容风险,因为切换到新表需要关心历史数据,需要同步老数据到新表,老的数据是否完全同步,在新表的模型下能否顺利走下去,这个都需要充分验证,否则整个系统会卡住。

  • 业务模型迁移问题

一般情况下如果以上的解决方案基本可以完成平滑稳定的表迁移,但是我这次迁移的更具挑战性的是底层模型是兼容多个TDD模型设计的物理表,简单来说就是同一个字段在不同的业务场景下可能存的字段不一样,并且还是一个主子表的结构。A表与A’,A的主键为A’外键。此时迁移的过程出现了一些新的问题。为了降低迁移的风险,我们分步去迁移,第一步是底层使用类似适配器的模式去读新表,但是转换的模型仍然是老表,这样为了方便加开关,这样就涉及到不同场景的新老表字段映射问题,这里可以使用抽象的模板去管理这些转换关系。


总结

整个表的迁移总的来说风险大于技术挑战,当然风险也依赖于技术方案,我的意思是这个一旦出问题,轻则数据不一致,重则整个系统不可用,因此对于风险的管理
要放在非常重要的位置上,例如日志+开关就是完全为了风险管控。由于预发与线上公用一套DB导致预发无法验证,只能发布上线验证,这也带来了挑战。

猜你喜欢

转载自blog.csdn.net/micro_hz/article/details/82837650