一次mysql迁移的方案与踩坑实战记录

目录
  • 背景
  • 方案一:老数据备份
  • 方案二:分表
  • 方案三:迁移至tidb
    • 重点说下同步老数据遇到的坑
    • 最终同步脚本方案
  • 总结

背景

由于历史业务数据采用mysql来存储的,其中有一张操作记录表video_log,每当用户创建、更新或者审核人员审核的时候,对应的video_log就会加一条日志,这个log表只有insert,可想而知,1个video对应多条log,一天10w video,平均统计一个video对应5条log,那么一天50w的log, 一个月50 * 30 = 1500w条记录, 一年就是1500 * 12 = 1.8亿。目前线上已经有2亿多的数据了,由于log本身不面向C端,用于查询问题的,所以可以忍受一点的延迟。 但是随着时间的积累,必然会越来越慢,影响效率,于是提出改造。

方案一:老数据备份

由于log本身不是最关键的数据,但是也要求实时性高(用于实时查询问题),所以一开始的想法是核心的基础存储还是保持不变,较老的数据迁移出去,毕竟突然去查询一年前的操作记录的概率很小,如果突然要查,可以走离线。设计的话,我们只需要一个定时脚本,每天在凌晨4点左右(业务低峰期)抽数据。抽出的数据可以上报到一些离线存储(一般公司都有基于hive的数仓之类的),这样就可以保持线上的video_log的数据不会一直增长。

方案二:分表

分表也是一种解决方案,相对方案一的好处就是,所有的数据都支持实时查,缺点是代码要改造了。

  • 首先确认sharding key,因为video_log是和video绑定的,所以自然而然选择video_id作为我们的sharding key
  • 按什么分表确定了,接下来确认下分多少张表。先定个小目标,支撑3年。每张表最大数据量为1个亿(由于我们的查询简单),按照上面的统计,我们3年大概:3*1.8=5.4亿,那么大概需要5.4/1≈6张表。

接下来就是改造代码了,得解决新老数据读写的问题。

  • 新数据的插入直接插入新表
  • 由于log表只有insert,所以不存在update、delete这些操作,不需要考虑这些场景。
  • 分表后,一个video的log存在两张表(老表和新表),所以临时两张表都查,然后做个合并
  • 同步老数据到新表中
  • 下线读取老表的代码

方案三:迁移至tidb

方案二的缺点比较明显,3年后咋办,继续拆表?感觉始终有个历史债在那。于是我们的目光定位到了tidb,tidb是分布式的数据库,接入了tidb,我们就无需关心分表了,这些tidb都帮我们做了,它会自己做节点的扩容。由于是分布式的,所以tidb的主键是无序的,这点很重要。
整个流程大概分为以下4个步骤:

  1. 先双写(记录下刚开始双写时的mysql的id,在此id前的肯定都是老数据)
  2. 同步老数据(通过第一步记录的id来区分)
  3. 切读(老数据同步完了)
  4. 下双写

重点说下同步老数据遇到的坑

迁移至tidb,看似很简单,其实在job脚本这里隐藏着几个坑。

  • 要考虑万一job中途断了,重新启动咋办,撇开重头跑数据的时间成本,已经同步的数据重新跑会重复,还要考虑重复数据的问题。解决重复数据的问题,可以对老表新加一个字段标识是否已同步,每次同步完,更新下字段。缺点:线上数据大,加个字段不太安全,可能造成线上阻塞。
  • 既然加个字段不好,那就用现有的主键id做约束,把主键id也同步过去,这样就算脚本重启,从头开始跑的,也因为相同的主健已经插入过,那么就会报错跳过。看似很完美,然而tidb是分布式的,主键id不是连续的,那么可能出现这样一种情况。正常的业务数据插入tidb,tidb分配的主键id和mysql同步的主键id重复,那么不管是谁,最后插入的那一条肯定是失败的。

最终同步脚本方案

综合考虑数据的重复性,job重启效率性,和整个同步的效率性,我大概做出以下方案:

  1. 任务分批提升效率:首先根据处理能力和预期完成时间,先对老数据进行分批,大概分了10批,10个job去跑不同批次的数据,互不干扰,且每次批量更新100条。
  2. 记录状态,重启自动恢复到断点:每次同步数据后记录下当前同步的位置(redis记录下当前的id),就算重启也可以从redis里拿到之前的更新位置,接着更新。
  3. 避免主键冲突:同步除了主键之外的所有字段(不同步主键)

最终通过方案三的四个切换步骤+高效率的同步脚本平稳的完成了数据的迁移

总结

到此这篇关于mysql迁移的方案与踩坑的文章就介绍到这了,更多相关mysql迁移方案与踩坑内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • mysql Innodb表空间卸载、迁移、装载的使用方法

    条件:2台服务器:A和B,需要A服务器上的表迁移到B服务器.Innodb表:sysUser,记录数:351781.以下测试在MySQL 5.5.34中进行.开始处理:1:在B服务器上建立sysUser表,并且执行: 复制代码 代码如下: zjy@B : db_test 09:50:30>alter table sysUser discard tablespace; 2:把A服务器表的表空间(ibd)复制到B服务器的相应数据目录.3:修改复制过来的ibd文件权限: 复制代码 代码如下: chown

  • 浅析mysql迁移到clickhouse的5种方法

    数据迁移需要从mysql导入clickhouse, 总结方案如下,包括clickhouse自身支持的三种方式,第三方工具两种. create table engin mysql CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster] ( name1 [type1] [DEFAULT|MATERIALIZED|ALIAS expr1] [TTL expr1], name2 [type2] [DEFAULT|MATERIAL

  • oracle数据库迁移到MySQL的方法总结

    前言 之前搭建了一个ExtJS + spring + Oracle 的这样一个报表系统的框架. 因为其他部门的要求, 也需要这个Framework 进行一些特殊的定制. 但是有一个问题是 Oracle 的数据库是需要收费的, 个人使用倒没什么问题, 公司使用的话就会有侵权的问题了. 而MySQL 则是完全免费的. 所以使用 ExtJS + Spring + MySQL  这样的组合应该就没什么问题了. 理论上来说, MySQL 已经被Oracle 收购, 这两者之间的Migrate 应该比较容易

  • mysql 备份与迁移 数据同步方法

    不过最近发现这个可视化操作有点点问题,就是当数据条数超过一定数目EMS SQL Manager就挂了,也不知道是否是软件问题--当然该开始我是将大的数据库文件分拆成小份小份的,多次导入. 刚才发现同事用了mysql 自带的mysqldump 工具就不存在这个问题. (羞愧,不过我平时极少接触数据库) 这里记录下操作方式: 1. 进入bin目录,执行命令: mysqldump -hlocalhost -uroot -padmin local_db > a.sql 2. 这时发现在bin目录生成了

  • Mysql的数据库迁移到另一个机器上的方法详解

    1.先找到迁移服务器上的Data文件,我安装的是mysql5.7,默认安装的路径.那么就是在C:\ProgramData\MySQL文件里面,先把隐藏文件打开. 这个Data文件就是你的数据文件:将你要迁移的数据库文件放到这里如下: 然后打开my.ini:找到datadir,然后将你的Data文件路径复制到下面,你要启动哪一个Data文件就用那个文件的地址,只能存在一个.如下: 然后在重启MySQL服务如下: 然后打开数据库连接工具,我这边用的Navicat,你连接迁移数据库,是你迁移之前的密码

  • mysql数据库迁移至Oracle数据库

    本文实例为大家分享了java获取不同路径的方法,供大家参考,具体内容如下 1.使用工具: (1) Navicat Premium (2) PL/SQL Developer 11.0 (3) Oracle SQL Developer 4.0.0.12.84(点击可进入下载页面) 特别说明:最初我用的一直是高版本的SQL Developer,但在数据库移植到大概两分钟的时候,总是报错,而错误信息又不明确.最后换成 Oracle SQL Developer 4.0.0.12.84,才把问题解决掉!如果

  • 关于MySQL数据迁移--data目录直接替换注意事项的详解

    近日更换服务器,要做数据库迁移,将数据库内的数据从服务器A迁移到服务器B.由于数据量较大,直接做dump耗时太长,故而采用如下方式处理:首先,在服务器B上安装了与服务器A同版本的MySQL,停止MySQL服务,将安装后的data目录删除:然后,服务器A锁住全部表,从服务器A将整个data目录和数据文件直到拷贝到服务器B上,修改服务器B上MySQL的my.cnf文件中的datadir指向新的data目录.最后,启动服务器B上的MySQL服务.结果启动失败,报出 "无法启动MySQL服务"

  • mysql5.5数据库data目录迁移方法详解

    //前一阵子以为学习需要就在自己的本本上装了个mysql数据库.今天想把结合jsp做的项目拿到学校机器上用用,但发现数据库数据怎么迁移,首先找不到数据库的数据目录在什么地方,就上网搜了搜也没找到合适的答案,但无意中发现原来5.5已经很人性化了.现在废话不多. 先说一下,其实数据库的目录就在你安装目录的data里面,我的实在D盘.可能大家默认安装都在C吧.这样就要迁移了.这个大家都懂.(D:\Program Files\MySQL\MySQL Server 5.5\data)要是我要迁移到学校机器

  • MySQL数据库迁移data文件夹位置详细步骤

    由于yum安装mysql的时候,数据库的data目录默认是在/var/lib下,出于数据安全性的考虑需要把它挪到/data分区.步骤如下:一.关闭apache和mysql. 复制代码 代码如下: service httpd stopservice mysqld stop 二.将/var/lib下的mysql目录mv(移动)到data目录.为什么要用mv命令,而不用cp命令呢?应为linux文件系统特殊性,mv命令能保留文件的所有属性和权限,尤其是selinux属性.如果用cp命令,就需要回头再去

  • MySQL数据库迁移快速导出导入大量数据

    数据库迁移是我们经常可遇到的问题,对于少量的数据,迁移基本上不会有什么问题.生产环境中,有以下情况需要做迁移工作: 磁盘空间不够.比如一些老项目,选用的机型并不一定适用于数据库.随着时间的推移,硬盘很有可能出现短缺: 业务出现瓶颈.比如项目中采用单机承担所有的读写业务,业务压力增大,不堪重负.如果 IO 压力在可接受的范围,会采用读写分离方案: 机器出现瓶颈.机器出现瓶颈主要在磁盘 IO 能力.内存.CPU,此时除了针对瓶颈做一些优化以外,选择迁移是不错的方案: 项目改造.某些项目的数据库存在跨

随机推荐