mycat 分片数据平滑迁移实施过程

来源:互联网 发布:淘宝txt 编辑:程序博客网 时间:2024/06/10 23:08

1,实践扩容

 travelrecord表定义为10个分片,尝试将10个分片中的2个分片转移到第二台MySQL上,并完成记录

要求,最快的数据迁移做法,中断业务时间最短

 

 

2,思路说明

2.110个分片的环境准备

我的理解里面,分片就代表了集群,一个分片就是一个实例,迁移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


 

3mysql5.6.12主从搭建

Mysql5.6.12安装:http://blog.csdn.net/mchdba/article/details/35994251

主从搭建:

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

 

 

 

 

原blog地址:http://blog.csdn.net/mchdba/article/details/50991649,未经过原作者mchdba(黄杉)同意,谢绝转载。


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]#

 

之后启动mycat。

 

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实例上验证数据已经分到10个分片上了:

                                                                                                                                                                                                                                                                                                              

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>


 

7mycat分片迁移前配置文件修改

要将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>


 

修改db5、db6分片的位置:

        <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>


 

B)然后重新加载mycat,使改动的新配置的分片到新实例上生效

mysql> reload @@config;ERROR 1064 (HY000): com.alibaba.druid.sql.parser.ParserException: syntax error, error in :'reload @@config',expect IDENTIFIER, actual IDENTIFIER reloadmysql>

WHY?我的reload失败了?看来只有restart

[root@oracle_standby logs]# ../bin/mycat restartStopping Mycat-server...Stopped Mycat-server.Starting Mycat-server...[root@oracle_standby logs]#

 

C)之后去dh1上解锁表

 

mysql> unlock tables;               Query OK, 0 rows affected (0.00 sec) mysql>

 

D)然后验证mycat上刀片完整性,如下是完整的

 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>

 

E)去看mycat.log后台日志,发现db5、db6已经连接到新的实例192.168.121.12:3307上面了

 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>

去第一个旧实例上192.168.121.61,查询不到新记录:

 [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]#

 

去第二个新实例192.168.121.12上,可以查到新记录:

 [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,去原来的实例上删除分片db5db6

 [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]#                                                                                                                        

 

至此,mycat分片迁移测试完毕。

 

这种操作的缺陷是,with read lock;的时候会锁表,短暂影响业务的正常使用。

 

解决思路是:如果想不锁表不影响业务的话,就不做with read lock但是切换后手工分析旧实例中的binlog,去找出db5分片db6分片的dmlddl操作,然后重新在新的实例中去手工恢复下。

 

3 0
原创粉丝点击