mycat 分片数据平滑迁移实施过程
2016-03-27 14:30
453 查看
1,实践扩容
travelrecord表定义为10个分片,尝试将10个分片中的2个分片转移到第二台MySQL上,并完成记录要求,最快的数据迁移做法,中断业务时间最短
2,思路说明
2.1,10个分片的环境准备
我的理解里面,分片就代表了集群,一个分片就是一个实例,迁移2个分片,就是迁移2个实例到新的环境上面,但是由于测试没法准备那么多10个实例,所以用一个database来代表一个实例一个分片,这样测试起来方便简单快捷得多;2.2,数据迁移最快、时间最短
要中断业务时间最短,那么只有第二个实例上也有在实际生产环境中,也就是说,基本在数据迁移这中间时间最短,这种目前可以用mysql主从的机制来实现,因为主从同步延迟基本上是1秒以下,基本能满足需求。1). 在迁移前,修改mycat配置。
2). 将第二台MySQL实例作为第一个Master的slave,注意,只同步db5、db6这两个分片。
3). 等同步完成后在业务量较小的时候,重新加载mycat
4). 登录第一个Master节点,手动删除两个分片的数据。
2.3,服务器准备:
名称 | Ip地址 | 端口 |
Mycat | 192.168.121.52 | 8066 |
Mysql 主 | 192.168.121.61 | 3306 |
Mysql从 | 192.168.121.12 | 3307 |
3,mysql5.6.12主从搭建
Mysql5.6.12安装:/article/1563981.html主从搭建:
A)在主库(121.61)上创建复制用户:GRANT REPLICATION SLAVE ON *.* TO 'repl_mycat'@'192.168.%' IDENTIFIED BY 'replmycattest'; grant all on *.* to root@'192.168.%' identified by ''; B)在主库上(121.61)获取复制position:show master status; C)在从上,修改my.cnf配置文件,只同步2个分片的数据, replicate-do-db=db5 replicate-do-db=db6 D)在从库上(121.12)开始搭建复制: stop slave; reset slave; change master to master_user='repl_mycat', master_password='replmycattest', master_host='192.168.121.61',master_port=3306, master_log_file='mysql-bin.025055',master_log_pos=120; start slave; show slave status\G |
4,准备在主库上建好10个分片
这里如果按照实际是需要10个mysql实例的,因为一个实例一个分片,我这里仅仅是功能测试,所以一时没有那么多实例,就用了实例上的多个db库来代替,达到类似多个分片的效果,可以理解一个库一个分片,db1就是第一个分片,db2就是第二个分片,db3就是第三个分片……db10就是第10个分片,在主库上192.168.121.61执行,会自动同步到从库192.168.121.12上面去。mysql> create database db1; Query OK, 1 row affected (0.00 sec) mysql> mysql> create database db2; Query OK, 1 row affected (0.00 sec) mysql> create database db3; Query OK, 1 row affected (0.00 sec) mysql> create database db4; Query OK, 1 row affected (0.00 sec) mysql> create database db5; Query OK, 1 row affected (0.01 sec) mysql> create database db6; Query OK, 1 row affected (0.00 sec) mysql> create database db7; Query OK, 1 row affected (0.00 sec) mysql> create database db8; Query OK, 1 row affected (0.00 sec) mysql> create database db9; Query OK, 1 row affected (0.00 sec) mysql> create database db10; Query OK, 1 row affected (0.00 sec) mysql> |
5,准备mycat配置文件
Schema.xml迁移前的配置(迁移前是如下配置,迁移后会有变化) :<!— 配置表 --> <table name="travelrecord" dataNode="dn$1-10" rule="auto-sharding-long" /> <!— 配置分片 --> <dataNode name="dn1" dataHost="dh1" database="db1" /> <dataNode name="dn2" dataHost="dh1" database="db2" /> <dataNode name="dn3" dataHost="dh1" database="db3" /> <dataNode name="dn4" dataHost="dh1" database="db4" /> <dataNode name="dn5" dataHost="dh1" database="db5" /> <dataNode name="dn6" dataHost="dh1" database="db6" /> <dataNode name="dn7" dataHost="dh1" database="db7" /> <dataNode name="dn8" dataHost="dh1" database="db8" /> <dataNode name="dn9" dataHost="dh1" database="db9" /> <dataNode name="dn10" dataHost="dh1" database="db10" /> <dataHost name="dh1" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100"> <heartbeat>select user()</heartbeat> <writeHost host="hostM1" url="192.168.121.61:3306" user="root" password=""/> </dataHost> |
[root@oracle_standby conf]# more autopartition-long.txt 0-10=0 10-20=1 20-30=2 30-40=3 40-50=4 50-60=5 60-70=6 70-80=7 80-90=8 90-100=9 [root@oracle_standby conf]# |
6,往10个分片里面录入测试数据
准备工作:建表sql: CREATE TABLE `travelrecord` ( `id` bigint(20) NOT NULL, `user_id` varchar(100) DEFAULT NULL, `traveldate` date DEFAULT NULL, `fee` decimal(10,0) DEFAULT NULL, `days` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; 录入测试数据: insert into travelrecord(id,user_id,traveldate,fee,days) values(1,'000001',now(),1235,6); insert into travelrecord(id,user_id,traveldate,fee,days) values(3,'000001',now(),1235,6); insert into travelrecord(id,user_id,traveldate,fee,days) values(11,'110002',now(),1235,6); insert into travelrecord(id,user_id,traveldate,fee,days) values(13,'130002',now(),1235,6); insert into travelrecord(id,user_id,traveldate,fee,days) values(21,'210003',now(),1235,6); insert into travelrecord(id,user_id,traveldate,fee,days) values(23,'230003',now(),1235,6); insert into travelrecord(id,user_id,traveldate,fee,days) values(31,'310002',now(),1235,6); insert into travelrecord(id,user_id,traveldate,fee,days) values(33,'330002',now(),1235,6); insert into travelrecord(id,user_id,traveldate,fee,days) values(41,'410002',now(),1235,6); insert into travelrecord(id,user_id,traveldate,fee,days) values(43,'430002',now(),1235,6); insert into travelrecord(id,user_id,traveldate,fee,days) values(51,'510002',now(),1235,6); insert into travelrecord(id,user_id,traveldate,fee,days) values(53,'530002',now(),1235,6); insert into travelrecord(id,user_id,traveldate,fee,days) values(61,'610002',now(),1235,6); insert into travelrecord(id,user_id,traveldate,fee,days) values(63,'630002',now(),1235,6); insert into travelrecord(id,user_id,traveldate,fee,days) values(71,'710002',now(),1235,6); insert into travelrecord(id,user_id,traveldate,fee,days) values(73,'730002',now(),1235,6); insert into travelrecord(id,user_id,traveldate,fee,days) values(81,'810002',now(),1235,6); insert into travelrecord(id,user_id,traveldate,fee,days) values(83,'830002',now(),1235,6); insert into travelrecord(id,user_id,traveldate,fee,days) values(91,'910002',now(),1235,6); insert into travelrecord(id,user_id,traveldate,fee,days) values(93,'930002',now(),1235,6); |
执行过程如下: mysql> CREATE TABLE `travelrecord` ( -> `id` bigint(20) NOT NULL, -> `user_id` varchar(100) DEFAULT NULL, -> `traveldate` date DEFAULT NULL, -> `fee` decimal(10,0) DEFAULT NULL, -> `days` int(11) DEFAULT NULL, -> PRIMARY KEY (`id`) -> ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; Query OK, 0 rows affected (0.05 sec) mysql> insert into travelrecord(id,user_id,traveldate,fee,days) values(1,'000001',now(),1235,6); now(),1235,6); insert into travelrecord(id,user_id,traveldate,fee,days) values(13,'130002',now(),1235,6); insert into travelrecord(id,user_id,traveldate,fee,days) values(21,'210003',now(),1235,6); insert into travelrecord(id,user_id,traveldate,fee,days) values(23,'230003',now(),1235,6); insert into travelrecord(id,user_id,traveldate,fee,days) values(31,'310002',now(),1235,6); insert into travelrecord(id,user_id,traveldate,fee,days) values(33,'330002',now(),1235,6); insert into travelrecord(id,user_id,traveldate,fee,days) values(41,'410002',now(),1235,6); insert into travelrecord(id,user_id,traveldate,fee,days) values(43,'430002',now(),1235,6); insert into travelrecord(id,user_id,traveldate,fee,days) values(51,'510002',now(),1235,6); insert into travelrecord(id,user_id,traveldate,fee,days) values(53,'530002',now(),1235,6); insert into travelrecord(id,user_id,traveldate,fee,days) values(61,'610002',now(),1235,6); insert into travelrecord(id,user_id,traveldate,fee,days) values(63,'630002',now(),1235,6); insert iQuery OK, 1 row affected, 1 warning (0.02 sec) mysql> insert into travelrecord(id,user_id,traveldate,fee,days) values(3,'000001',now(),1235,6); nto travelrecord(id,user_id,traveldate,fee,days) values(71,'710002',now(),1235,6); insert into travelrecord(id,user_id,traveldate,fee,days) values(73,'730002',now(),1235,6); insert into travelrecord(id,user_id,traveldate,fee,days) values(81,'810002',now(),Query OK, 1 row affected, 1 warning (0.01 sec) mysql> insert into travelrecord(id,user_id,traveldate,fee,days) values(11,'110002',now(),1235,6); Query OK, 1 row affected, 1 warning (0.00 sec) mysql> insert into travelrecord(id,user_id,traveldate,fee,days) values(13,'130002',now(),1235,6); 1235,6); insert into travelrecord(id,user_id,traveldate,fee,days) values(83,'830002',now(),1235,6); insert into travelrecord(id,user_id,traveldate,fee,days) values(91,'910002',now(),1235,6); insert into travelrecord(id,user_id,traveldate,fee,days) values(9Query OK, 1 row affected, 1 warning (0.01 sec) mysql> insert into travelrecord(id,user_id,traveldate,fee,days) values(21,'210003',now(),1235,6); 3,'930002',now(),1235,6); insert into travelrecord(id,user_id,traveldate,fee,days) values(101,'1010002',now(),1235,6); insert into travelrecord(id,user_id,traveldate,fee,days) values(103,'1030002',now(),1235,6); Query OK, 1 row affected, 1 warning (0.00 sec) mysql> insert into travelrecord(id,user_id,traveldate,fee,days) values(23,'230003',now(),1235,6); Query OK, 1 row affected, 1 warning (0.00 sec) mysql> insert into travelrecord(id,user_id,traveldate,fee,days) values(31,'310002',now(),1235,6); Query OK, 1 row affected, 1 warning (0.01 sec) mysql> insert into travelrecord(id,user_id,traveldate,fee,days) values(33,'330002',now(),1235,6); Query OK, 1 row affected, 1 warning (0.00 sec) mysql> insert into travelrecord(id,user_id,traveldate,fee,days) values(41,'410002',now(),1235,6); Query OK, 1 row affected, 1 warning (0.01 sec) mysql> insert into travelrecord(id,user_id,traveldate,fee,days) values(43,'430002',now(),1235,6); Query OK, 1 row affected, 1 warning (0.00 sec) mysql> insert into travelrecord(id,user_id,traveldate,fee,days) values(51,'510002',now(),1235,6); Query OK, 1 row affected, 1 warning (0.00 sec) mysql> insert into travelrecord(id,user_id,traveldate,fee,days) values(53,'530002',now(),1235,6); Query OK, 1 row affected, 1 warning (0.00 sec) mysql> insert into travelrecord(id,user_id,traveldate,fee,days) values(61,'610002',now(),1235,6); Query OK, 1 row affected, 1 warning (0.00 sec) mysql> insert into travelrecord(id,user_id,traveldate,fee,days) values(63,'630002',now(),1235,6); Query OK, 1 row affected, 1 warning (0.01 sec) mysql> insert into travelrecord(id,user_id,traveldate,fee,days) values(71,'710002',now(),1235,6); Query OK, 1 row affected, 1 warning (0.00 sec) mysql> insert into travelrecord(id,user_id,traveldate,fee,days) values(73,'730002',now(),1235,6); Query OK, 1 row affected, 1 warning (0.00 sec) mysql> insert into travelrecord(id,user_id,traveldate,fee,days) values(81,'810002',now(),1235,6); Query OK, 1 row affected, 1 warning (0.01 sec) mysql> insert into travelrecord(id,user_id,traveldate,fee,days) values(83,'830002',now(),1235,6); Query OK, 1 row affected, 1 warning (0.00 sec) mysql> insert into travelrecord(id,user_id,traveldate,fee,days) values(91,'910002',now(),1235,6); Query OK, 1 row affected, 1 warning (0.00 sec) mysql> insert into travelrecord(id,user_id,traveldate,fee,days) values(93,'930002',now(),1235,6); Query OK, 1 row affected, 1 warning (0.01 sec) mysql> |
mysql> explain select * from travelrecord; +-----------+--------------------------------------+ | DATA_NODE | SQL | +-----------+--------------------------------------+ | dn1 | SELECT * FROM travelrecord LIMIT 100 | | dn10 | SELECT * FROM travelrecord LIMIT 100 | | dn2 | SELECT * FROM travelrecord LIMIT 100 | | dn3 | SELECT * FROM travelrecord LIMIT 100 | | dn4 | SELECT * FROM travelrecord LIMIT 100 | | dn5 | SELECT * FROM travelrecord LIMIT 100 | | dn6 | SELECT * FROM travelrecord LIMIT 100 | | dn7 | SELECT * FROM travelrecord LIMIT 100 | | dn8 | SELECT * FROM travelrecord LIMIT 100 | | dn9 | SELECT * FROM travelrecord LIMIT 100 | +-----------+--------------------------------------+ 10 rows in set (0.00 sec) mysql> |
mysql> select * from db1.travelrecord; +----+---------+------------+------+------+ | id | user_id | traveldate | fee | days | +----+---------+------------+------+------+ | 1 | 000001 | 2016-03-27 | 1235 | 6 | | 3 | 000001 | 2016-03-27 | 1235 | 6 | +----+---------+------------+------+------+ 2 rows in set (0.00 sec) mysql> select * from db2.travelrecord; +----+---------+------------+------+------+ | id | user_id | traveldate | fee | days | +----+---------+------------+------+------+ | 11 | 110002 | 2016-03-27 | 1235 | 6 | | 13 | 130002 | 2016-03-27 | 1235 | 6 | +----+---------+------------+------+------+ 2 rows in set (0.00 sec) mysql> select * from db5.travelrecord; +----+---------+------------+------+------+ | id | user_id | traveldate | fee | days | +----+---------+------------+------+------+ | 41 | 410002 | 2016-03-27 | 1235 | 6 | | 43 | 430002 | 2016-03-27 | 1235 | 6 | +----+---------+------------+------+------+ 2 rows in set (0.00 sec) mysql> mysql> select * from db9.travelrecord; +----+---------+------------+------+------+ | id | user_id | traveldate | fee | days | +----+---------+------------+------+------+ | 81 | 810002 | 2016-03-27 | 1235 | 6 | | 83 | 830002 | 2016-03-27 | 1235 | 6 | +----+---------+------------+------+------+ 2 rows in set (0.00 sec) mysql> select * from db10.travelrecord; +----+---------+------------+------+------+ | id | user_id | traveldate | fee | days | +----+---------+------------+------+------+ | 91 | 910002 | 2016-03-27 | 1235 | 6 | | 93 | 930002 | 2016-03-27 | 1235 | 6 | +----+---------+------------+------+------+ 2 rows in set (0.00 sec) mysql> |
7,mycat分片迁移前配置文件修改
要将db5、db6这2个分片切到第二个实例,也就是从库192.168.121.12上面去,都在schema.xml里面修改:新添加从库的dataHost配置:
<dataHost name="dh2" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100"> <heartbeat>select user()</heartbeat> <writeHost host="hostM1" url="192.168.121.12:3307" user="root" password=""/> </dataHost> |
<dataNode name="dn5" dataHost="dh2" database="db5" /> <dataNode name="dn6" dataHost="dh2" database="db6" /> |
8,在业务量小的时候,比如凌晨,进行切换
先在db5、db6之上做flush table命令将db5.travelrecord、db6.travelrecord内存中数据刷到磁盘中,并重新加载mycat:A)先在dh1上192.168.121.61刷磁盘
mysql> flush table db2.travelrecord,db3.travelrecord with read lock; Query OK, 0 rows affected (0.00 sec) mysql> |
mysql> reload @@config; ERROR 1064 (HY000): com.alibaba.druid.sql.parser.ParserException: syntax error, error in :'reload @@config',expect IDENTIFIER, actual IDENTIFIER reload mysql> WHY?我的reload失败了?,看来只有restart了 [root@oracle_standby logs]# ../bin/mycat restart Stopping Mycat-server... Stopped Mycat-server. Starting Mycat-server... [root@oracle_standby logs]# |
mysql> unlock tables;
Query OK, 0 rows affected (0.00 sec)
mysql> |
mysql> explain select * from travelrecord; +-----------+--------------------------------------+ | DATA_NODE | SQL | +-----------+--------------------------------------+ | dn1 | SELECT * FROM travelrecord LIMIT 100 | | dn10 | SELECT * FROM travelrecord LIMIT 100 | | dn2 | SELECT * FROM travelrecord LIMIT 100 | | dn3 | SELECT * FROM travelrecord LIMIT 100 | | dn4 | SELECT * FROM travelrecord LIMIT 100 | | dn5 | SELECT * FROM travelrecord LIMIT 100 | | dn6 | SELECT * FROM travelrecord LIMIT 100 | | dn7 | SELECT * FROM travelrecord LIMIT 100 | | dn8 | SELECT * FROM travelrecord LIMIT 100 | | dn9 | SELECT * FROM travelrecord LIMIT 100 | +-----------+--------------------------------------+ 10 rows in set (0.20 sec) mysql> |
03/27 14:10:58.433 INFO [$_NIOREACTOR-1-RW] (GetConnectionHandler.java:66) -connected successfuly MySQLConnection [id=11, lastTime=1459059058433, user=root, schema=db6, old shema=db6, borrowed=true, fromSlaveDB=false, threadId=216, charset=utf8, txIsolation=0, autocommit=true, attachment=null, respHandler=null, host=192.168.121.12, port=3307, statusSync=null, writeQueue=0, modifiedSQLExecuted=false] 03/27 14:10:58.434 INFO [$_NIOREACTOR-1-RW] (GetConnectionHandler.java:66) -connected successfuly MySQLConnection [id=13, lastTime=1459059058433, user=root, schema=db5, old shema=db5, borrowed=true, fromSlaveDB=false, threadId=218, charset=utf8, txIsolation=0, autocommit=true, attachment=null, respHandler=null, host=192.168.121.12, port=3307, statusSync=null, writeQueue=0, modifiedSQLExecuted=false] |
9,录入新的数据,验证下
在mycat窗口执行录入:mysql> insert into travelrecord(id,user_id,traveldate,fee,days) values(45,'450002',now(),1235,6); Query OK, 1 row affected, 1 warning (0.03 sec) mysql> insert into travelrecord(id,user_id,traveldate,fee,days) values(55,'550002',now(),1235,6); Query OK, 1 row affected, 1 warning (0.01 sec) mysql> |
[root@oracle_standby logs]# mysql -uroot -p -h192.168.121.61 -P3306 -e "select * from db5.travelrecord where id=45; select * from db6.travelrecord where id=55; "Enter password: [root@oracle_standby logs]# |
[root@oracle_standby logs]# mysql -uroot -p -h192.168.121.12 -P3307 -e "select * from db5.travelrecord where id=45; select * from db6.travelrecord where id=55; "Enter password: +----+---------+------------+------+------+ | id | user_id | traveldate | fee | days | +----+---------+------------+------+------+ | 45 | 450002 | 2016-03-27 | 1235 | 6 | +----+---------+------------+------+------+ +----+---------+------------+------+------+ | id | user_id | traveldate | fee | days | +----+---------+------------+------+------+ | 55 | 550002 | 2016-03-27 | 1235 | 6 | +----+---------+------------+------+------+ [root@oracle_standby logs]# |
10,去原来的实例上删除分片db5、db6
[root@oracle_standby logs]# mysql -uroot -p -h192.168.121.61 -P3306 -e "drop database db5; drop database db6;" Enter password: [root@oracle_standby logs]# |
这种操作的缺陷是,with read lock;的时候会锁表,短暂影响业务的正常使用。
解决思路是:如果想不锁表不影响业务的话,就不做with read lock但是切换后手工分析旧实例中的binlog,去找出db5分片db6分片的dml、ddl操作,然后重新在新的实例中去手工恢复下。
相关文章推荐
- ASP.NET-页面缓存
- Struts2<s:select></s:select>
- SVN Access to ‘/xxx/’ forbidden,不能更新提交的解决办法
- 腾讯前端面试
- socket编程入门
- 获得Java类的方法签名
- JAVA学习初步 级数求和
- ASP.NET-webconfig中注意事项
- HTTP协议
- HDU 4323 Magic Number 编辑距离
- Thinking in Java读书笔记
- 金融行业密钥详解
- 学习进度条 第四周
- HDU 5650 异或
- 网络属性
- 对于一个给定的 source 字符串和一个 target 字符串,你应该在 source 字符串中找出 target 字符串出现的第一个位置(从0开始)。如果不存在,则返回 -1。
- 第5周-项目1-三角形类锥形(2)
- Scala-IDE构建Maven项目
- 水平居中
- KEIL Target 详细注解