环境
- 数据库:Mysql8
- 操作系统:Windows10、CentOS7
- 中间件:Mycat1.6.7
场景
数据库使用的mysql,起初是单库单表,时间久了单表的数据量越来越大,一个表中的数据量达到3个多亿,mysql单表数据量达到800万左右就达到瓶颈了,不得不分表了,使用mycat中间件
迁移前准备
- 部署好新的数据库节点,服务器磁盘容量保证要从充足
- 分析需要迁移的单表数据量,计算现有数据量及估算每日新增大概数据量,按照单表800万左右存储,计算单表需要拆分成多少个分片
- 在新的数据库节点创建好相应的分片表及mycat配置,建议涉及到的索引这个时候也创建好
导出原始数据
导出数据的方式有很多种,也可以参考这篇文章:Mysql千万级数据量批量快速迁移
– mysqldump 方式
– load data 方式
– 利用Navicat For Mysql可视化工具方式
– 第三方开源工具yugong
– …
注:以上几种最快的方式是第二种load data
– 实际测试如果将导出的数据通mycat1.6.7版本导入到新的数据节点,load data方式不支持,根据mycat1.x官方文档的描述,使用load data方式迁移数据分配路由,schema.xml配置文件中dbDriver方式必须为native,实际测试并没有用,mycat社区委员会俊文也表示不建议通过mycat1.x使用load data方式
– 由于作者使用的是mycat1.6.7版本所以,没能使用load data迁移,最后选择使用mysqldump方式,有一张单表数据量达到了将近4亿,在处理这张表的时候,考虑到数据量比较大,以及有其他程序也在源源不断的写入新的数据,所以采用按条件分割处理,分析表结构,如果有ID自增主键这种,可以按照ID来分割,或者按照其他旧数据不会再新增的条件,这里根据自己实际业务需求
导出语句示例
代码语言:javascript复制mysqldump -uroot -p123456 -h127.0.1 -P3306 --default-character-set=utf8 -c -t --skip-add-locks --databases testDB --tables user --where="user_id BETWEEN 0 AND 10000"> D:user_id_0_10000.sql
mysqldump -uroot -p123456 -h127.0.1 -P3306 –default-character-set=utf8 -c -t –skip-add-locks –databases testDB –tables user –where=”user_id BETWEEN 0 AND 10000″> D:user_id_0_10000.sql
参数解释
– -u(小写):mysql用户名
– -p(小写):mysql密码
– -h(小写):mysql所在主机地址,可以是远程可以是本机,本机可以省略
– -P(大写):mysql端口号
– -c(小写):使用完整的insert语句(包含列名称)。这么做能提高插入效率,但是可能会受到max_allowed_packet参数的影响而导致插入失败。
– -t(小写):只导出数据,而不添加CREATE TABLE 语句。
– –default-character-set=utf8:设置默认字符集,默认值为utf8
– –skip-add-locks:取消在每个表导出之前增加LOCK TABLES(默认存在锁)
– –databases:导出的数据名,这里只需要导出的表所在的数据名字
– –tables:需要导出的表名
– –where:添加条件,示例:user_id BETWEEN 0 AND 10000,这里只会导出user_id大于等于0小于10000的数据,可以理解为执行导出了以下sql结果:SELECT * FROM user WHERE user_id BETWEEN 0 AND 10000;
– D:user_id_0_10000.sql:导出位置,如果使用的windows本机机器导出远程服务器上的数据,这里就是本地的路径,如果在linux上执行,路径就换成linux上的即可比如:/root/user_id_0_10000.sql
导入
如果要对原表进行分片,然后通过mycat导入
如果原表单表导入到新节点之后做了分片,这里举例,假如原来一张单表通过mycat分片导入之后分成了3个分片表,也就是原来的一张表数据分散导入到三张表中
以下配置前提已经创建好了分片表,假如分片表名为user1、user2、user3
mycat配置文件schemal.xml
代码语言:javascript复制<table name="user" primaryKey="user_id" autoIncrement="true" dataNode="dn1" subTables="user$1-3" rule="mod_Name"></table>
这里全局序列号采用:自增长主键方式,具体参考文章:Mycat1.6.7.6全局序列号的使用
分片算法采用:取模
配置完成之后重启mycat开始执行导入即可,mycat会自动路由将原来的数据较均匀分配到各个分片中
本地导入
如果本地能链接mycat服务,或者mycat做了高可用个,可以通过haproxy链接,重点是本地如果能够连接成功mycat,那么前面导出的user_id_0_10000.sql文件就不需要上传到服务器了,作者实际测试本地windows上的mysql服务并不能够成功连接到Linux上的mycat服务,如果本地你能够连接成功,那么执行以下命令导入数据到新的数据节点即可,注意路径切换到你自己的
代码语言:javascript复制source D:user_id_0_10000.sql
服务器导入
如果本地不能连接到mycat服务,不能通过本地实现,就需要多一步,将导出的sql文件上传至装有mysql服务的服务器,任意一台即可,前提安装有mysql服务,上传完成之后就和本地类似了,通过mysql服务连接到mycat,然后执行以下命令即可,注意路径切换到你自己的
代码语言:javascript复制source /root/user_id_0_10000.sql
接下来就是慢慢的等待执行完成~
实际测试平均执行效率大概每秒插入1000条左右
检查
导入完成之后需要检查数据的一致性,这里就很简答了,比如导出之前在原始数据库上查一下导出的数据数量,按照本文示例统计查询
代码语言:javascript复制SELECT count(1) FROM user WHERE user_id BETWEEN 0 AND 10000;
然后在新的数据节点执行同样的命令,对比两次查询结果即可