文章目录

  • 停机迁移方案
  • 双写迁移方案
  • 其他
  • 一、现状
  • 二、目标
  • 三、解决方案
  • 四、采坑
  • 五、结果


停机迁移方案

我先给你说一个最 low 的方案,就是很简单,大家伙儿凌晨 12 点开始运维,网站或者 app 挂个公告,说 0 点到早上 6 点进行运维,无法访问。

接着到 0 点停机,系统停掉,没有流量写入了,此时老的单库单表数据库静止了。然后你之前得写好一个导数的一次性工具,此时直接跑起来,然后将单库单表的数据哗哗哗读出来,写到分库分表里面去。

导数完了之后,就 ok 了,修改系统的数据库连接配置啥的,包括可能代码和 SQL 也许有修改,那你就用最新的代码,然后直接启动连到新的分库分表上去。

验证一下,ok了,完美,大家伸个懒腰,看看看凌晨 4 点钟的夜景,打个滴滴回家吧。

但是这个方案比较 low,谁都能干,我们来看看高大上一点的方案。

DM8数据库迁移到mysql数据库 mysql数据库迁移方案_增删改

双写迁移方案

这个是我们常用的一种迁移方案,比较靠谱一些,不用停机,不用看凌晨 4 点的风景。

简单来说,就是在线上系统里面,之前所有写库的地方,增删改操作,除了对老库增删改,都加上对新库的增删改,这就是所谓的双写,同时写俩库,老库和新库。

然后系统部署之后,新库数据差太远,用之前说的导数工具,跑起来读老库数据写新库,写的时候要根据 gmt_modified 这类字段判断这条数据最后修改的时间,除非是读出来的数据在新库里没有,或者是比新库的数据新才会写。简单来说,就是不允许用老数据覆盖新数据。

导完一轮之后,有可能数据还是存在不一致,那么就程序自动做一轮校验,比对新老库每个表的每条数据,接着如果有不一样的,就针对那些不一样的,从老库读数据再次写。反复循环,直到两个库每个表的数据都完全一致为止。

接着当数据完全一致了,就 ok 了,基于仅仅使用分库分表的最新代码,重新部署一次,不就仅仅基于分库分表在操作了么,还没有几个小时的停机时间,很稳。所以现在基本玩儿数据迁移之类的,都是这么干的。

其他

一、现状

mysql下,某business单表已近2000万且还在持续增加中,存在多个索引,有较高的查询压力。现业务端使用guava cache拦了一道,还能顶得住,但是后台管理系统的全量数据的分页排序查询比较慢,且将来会越来越慢。

二、目标

业务端+admin查询都快。

三、解决方案

1.基于实际情况(大家一定要根据实际情况来),把数据库拆为三个,如下:

  1. 热数据(老表):提供CURD操作,事务加锁等等,最大限度的不用更改原代码。
  2. 半年内数据(history):只提供查询业务。
  3. 半年之前数据(backup):归档,不提供业务查询,只支持手动查库(已跟产品沟通好)。

2.数据迁移,采用公司统一任务调度平台,注册任务后调度执行,自带WEB管理页面。支持暂停、恢复、执行计划、日志查询。

3.由于历史数据过千万,需要上线前进行一次手动迁移,初始化数据

1)history表保存:7天~半年,非进行状态的数据。

2)backup表保存:半年前的,非进行状态的数据。

3)删除business表中,7天前的,非进行状态的数据。

4 . 后续每天凌晨定时任务迁移数据(迁移时注意:保证ID一致 )

business–>history >7天,非进行状态的数据。

history–>backup >半年,非进行状态的数据。

5.admin切到从库读。主从分离,避免从库读全量数据,导致业务端查询缓慢。

四、采坑

1.千万级带索引删除记录,记得不能一次性直接delete, 可以根据创建时间来,一次删除百万级数据,多分几次删除。否则容易出现假死,慢查询,kill不掉执行sql.

2.注意初始化数据时候,可能当天多次执行,所以加上修改时间在当天前的,这样多次执行,不会出现数据重复

3.写批量插入sql时,

1)不要用函数:sql中使用函数极端消耗时间。

2)不要用#,要用$:避免再次编译消耗时间,这里不用怕什么sql注入,内部接口。

1 <insert id="transferTradingOrderByIds">
 2     insert into ${toTableName} (<include refid="Base_Column_List"/>)
 3     select <include refid="Base_Column_List"/>
 4     from ${fromTableName}
 5     <where>
 6         id in
 7         <foreach collection="transferTradingOrderIds" item="id" separator="," open="(" close=")">
 8             ${id}
 9         </foreach>
10     </where>
11 </insert>

五、结果

热表数据:一百万内,增删改查极快。

历史数据:一千万内,查询快。

归档数据:千万级以上,慢,但是业务不调用。