从 MySQL 迁移到 GoldenDB,上来就踩了一个坑。
大家好,我是君哥。
最近从 MySQL 迁移 GoldenDB,遇到了一个奇怪的问题,今天来分享一下。
问题回放
我们先创建一张表 test_1,SQL 如下:
CREATE TABLE`test_1` (
`id`int(8) NOTNULL AUTO_INCREMENT,
`column1`varchar(1) COLLATE utf8_bin DEFAULTNULL,
`date_time` datetime DEFAULTNULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=11DEFAULTCHARSET=utf8 COLLATE=utf8_bin
往 test_1 插入 1 条数据,如下图:
INSERT INTO test_1(column1,date_time)VALUES ('a',NOW());
然后我们创建一张跟 test1 表结构一样的表 test2,
CREATE TABLE test_2 LIKE test_1;
执行下面 SQL,
insert into test_2(column1,date_time) select "column1", now() from test_1;
这条 SQL 并不复杂,从 test1 表查出数据写到 test2 表。但不知道写代码的小伙伴出于什么考虑在 column1 上加了双引号。这个 SQL 在 MySQL(8.0 版本)上执行是没有问题的,但是放到了 GoldenDB 上就报错了,因为双引号包着的字段返回的是 column1 这个字符串,最终字段超长报错(Data too long for column 'column1' at row 1)。
迁移注意
近年来,国内不少公司都在做信创改造,也难免会遇到一些坑。那么涉及数据库迁移改造的,需要注意哪些方面呢?
1. 语法兼容
这可能是首要考虑的点,也是特别关键的一步,语法不兼容直接会导致业务上的失败,就像上面我遇到的问题。
一些主流的分布式数据库会有兼容性扫描工具,可以帮助开发人员避开大多数的坑。而对于老系统,经历过多个开发人员之手,现有开发人员没人能对存量代码非常熟悉,也没有测试同事知道要测试哪些点。除了工具扫描外,好多功能还是需要开发人员撸代码来确认的。开发人员撸代码的时候,要特别注意函数、存储过程、自增 id、触发器、长事务、事务隔离级别等。
别太相信数据库厂商鼓吹的 100% 兼容 xxx 数据库。出了事故,厂商可不背锅。工具可以解决 90% 的问题,但剩下的 10% 是最复杂,最容易出问题的地方。还是需要靠程序员人工确认的。
2. 数据分片
根据业务规则为每张表选择最合适的分片字段,比如客户身份证,客户 id,尽可能让同一个维度的数据(比如单个客户)在单个分片上。这样对同一个维度的数据的操作可以在一个分片上完成,比如 JOIN 语句,跨分片查询复杂度很高。
尤其需要注意的是不要选择离散度高的字段来分片,很容易造成数据倾斜。
将数据量小、更新频率低的表设置为全局表,比如行政区码值,同步到到各个分片,避免跨分片关联查询。
3. 性能测试
性能测试是必须要进行的事情。从传统数据库迁移到国产分布式数据库,很可能会出现性能问题,尤其原数据库是 Oracle 并且数据量在千万级别的情况。
对于复杂的业务系统,里面的 SQL 可能会达到上千条,对所有 SQL 做压测不太现实,所以一定要做全面的评估,找出可能有性能问题的 SQL 进行压测。
更难的是,因为业务场景的问题,一些 SQL 可能很难执行到,要模拟特定的场景数据才能执行到这些 SQL。很容易在压测时漏掉这些场景,这也是为什么有时候测试环境性能测试没发现问题,但上线后却出了问题。
4.切换过程
有了上面三步的评估,接下来关注的就是切换过程,直接关系到整个切换的结果。
是否允许停机。如果业务上允许短暂停机,那就太好了,先把一个时间点前的存量数据让新老库完成同步,然后短暂停服,把增量数据同步完成。一定要注意的是服务重启后,如果验证有问题,能快速回切老库,这又涉及到一个问题,重启服务后增量数据需要考虑双写,以便切回时不丢失数据。
如果业务上不允许停服,那就比较复杂了。可以考虑增加一套服务连接新库,在新服务上切换少量流量进行验证并且双写。这里会涉及新老库双向数据同步,必须解决循环同步问题。
总结
随着这些年国内新创改造的开展,数据库迁移是很多公司必须要做的一个工作,这项工作难度极大,要完全不出问题很难。做好影响分析、制定快速回切方案,最大限度降低业务损失,才能保证不出大事故。