MySQL分区如何迁移,就是这么简单

MySQL越来越流行,而且存储在MySQL的数据量也越来越大,单表数据达亿行已经是非常常见的现象,而这些表里面保存了大量的历史记录,严重影响SQL执行的效率。本文是针对客户需求,迁移MySQL Innodb大表分区中部分历史归档分区到其他实例或者其他库表,而且迁移过程尽量减少对业务环境的影响。

环境介绍

  • MySQL 5.7.21

  • Centos 7.4

  • innodb_file_per_table=1

     

| MySQL常用的Innodb迁移方法

  • MySQL Enterprise Backup(物理备份,类似于xtrabackup)

  • Copying Data Files (冷备份)

  • 逻辑导出和导入(mysqldump,mydumper,mysqlpump)

  • 可传输的表空间

 

| 迁移方案(可传输的表空间)

准备工作

  • MySQL版本必须是5.7

  • 迁移过程中存在短暂时间内业务不可写,建议提前做好准备

操作步骤

查看需要迁移表(原表)结构

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

root@localhost : testdba 02:03:18> use test

Database changed

root@localhost : test 08:37:50> show create table sbtest2;

+---------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

Table Create Table |

+---------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

| sbtest2 | CREATE TABLE `sbtest2` (

`id` int(10) DEFAULT NULL,

`namevarchar(20) COLLATE utf8_bin DEFAULT NULL,

`dateint(20) DEFAULT NULL,

KEY `idx_fenqu` (`date`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin

/*!50100 PARTITION BY RANGE (date)

(PARTITION p0 VALUES LESS THAN (20161201) ENGINE = InnoDB,

 PARTITION p1 VALUES LESS THAN (20170101) ENGINE = InnoDB,

 PARTITION p2 VALUES LESS THAN (20170201) ENGINE = InnoDB,

 PARTITION p3 VALUES LESS THAN (20170301) ENGINE = InnoDB,

 PARTITION p4 VALUES LESS THAN (20170401) ENGINE = InnoDB,

 PARTITION p5 VALUES LESS THAN (20170501) ENGINE = InnoDB,

 PARTITION p6 VALUES LESS THAN (20170601) ENGINE = InnoDB,

 PARTITION p7 VALUES LESS THAN (20170701) ENGINE = InnoDB,

 PARTITION p8 VALUES LESS THAN (20170801) ENGINE = InnoDB,

 PARTITION p9 VALUES LESS THAN (20170901) ENGINE = InnoDB,

 PARTITION p10 VALUES LESS THAN (20171001) ENGINE = InnoDB,

 PARTITION p11 VALUES LESS THAN (20171101) ENGINE = InnoDB,

 PARTITION p12 VALUES LESS THAN (20171201) ENGINE = InnoDB,

 PARTITION p13 VALUES LESS THAN (20180101) ENGINE = InnoDB,

 PARTITION p14 VALUES LESS THAN (20180201) ENGINE = InnoDB,

 PARTITION p15 VALUES LESS THAN (20180301) ENGINE = InnoDB,

 PARTITION p16 VALUES LESS THAN (20180401) ENGINE = InnoDB,

 PARTITION p17 VALUES LESS THAN (20180501) ENGINE = InnoDB,

 PARTITION p18 VALUES LESS THAN (20180601) ENGINE = InnoDB,

 PARTITION p19 VALUES LESS THAN MAXVALUE ENGINE = InnoDB) */ |

+---------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

1 row in set (0.00 sec)

root@localhost : test 12:04:03> SELECT PARTITION_NAME, TABLE_ROWS FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_NAME = 'sbtest2';

+----------------+------------+

| PARTITION_NAME | TABLE_ROWS |

+----------------+------------+

| p0 | 22 |

| p1 | 2 |

| p2 | 2 |

| p3 | 2 |

| p4 | 2 |

| p5 | 2 |

| p6 | 2 |

| p7 | 2 |

| p8 | 2 |

| p9 | 2 |

| p10 | 2 |

| p11 | 2 |

| p12 | 2 |

| p13 | 2 |

| p14 | 2 |

| p15 | 2 |

| p16 | 2 |

| p17 | 2 |

| p18 | 2 |

| p19 | 14 |

+----------------+------------+

20 rows in set (0.00 sec)

按照个人迁移分区表需求,可以把历史分区迁移到其他MySQL实例,也可以迁移到同一MySQL实例的其他库中。首先创建与原表相同表结构的分区表,在创建分区表时,我们只需要创建我们需要迁移的表分区结构。例:下面是迁移案例,由于只迁移2017年数据,所以表结构只创建了存储2017年数据的分区(也就是分区p2-p13)。   

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

root@localhost : test 01:59:36> create database testdba;

Query OK, 1 row affected (0.12 sec)

root@localhost : test 01:59:44> use testdba;

Database changed

root@localhost : testdba 06:04:26> CREATE TABLE `sbtest2` (

-> id int(10),

-> name varchar(20),

-> date int(20),

-> key idx_fenqu(date)

-> )

-> PARTITION BY RANGE (date) (

-> PARTITION p2 VALUES LESS THAN (20170201),

-> PARTITION p3 VALUES LESS THAN (20170301),

-> PARTITION p4 VALUES LESS THAN (20170401),

-> PARTITION p5 VALUES LESS THAN (20170501),

-> PARTITION p6 VALUES LESS THAN (20170601),

-> PARTITION p7 VALUES LESS THAN (20170701),

-> PARTITION p8 VALUES LESS THAN (20170801),

-> PARTITION p9 VALUES LESS THAN (20170901),

-> PARTITION p10 VALUES LESS THAN (20171001),

-> PARTITION p11 VALUES LESS THAN (20171101),

-> PARTITION p12 VALUES LESS THAN (20171201),

-> PARTITION p13 VALUES LESS THAN (20180101)

-> );

Query OK, 0 rows affected (0.22 sec)

清除新表所有的分区独立表空间,为导入原表的分区独立表空间做准备 

1

2

3

4

root@localhost : testdba 02:00:05> use testdba;

Database changed

root@localhost : testdba 02:00:23> ALTER TABLE sbtest2 DISCARD PARTITION p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13 TABLESPACE;

Query OK, 0 rows affected (0.27 sec)

在原表中执行FLUSH TABLES ... FOR EXPORT(在分区表空间传输没有完成之前,不要退出该会话或者执行unlock tables;操作),用来获取元数据校验文件.cfg和确保该表的脏页刷到磁盘,并加共享表锁 

1

2

3

4

5

6

7

8

9

10

11

root@localhost : testdba 02:00:24> USE test;

Database changed

root@localhost : test 02:00:29> FLUSH TABLES test.sbtest2 FOR EXPORT;

Query OK, 0 rows affected (0.00 sec)

[root@slave test]# cd /var/lib/mysql/data/mydata/test

[root@slave test]# ls 

db.opt sbtest2#P#p10.cfg sbtest2#P#p12.ibd sbtest2#P#p15.cfg sbtest2#P#p17.ibd sbtest2#P#p2.cfg sbtest2#P#p4.ibd sbtest2#P#p7.cfg sbtest2#P#p9.ibd

sbtest2#P#p0.cfg sbtest2#P#p10.ibd sbtest2#P#p13.cfg sbtest2#P#p15.ibd sbtest2#P#p18.cfg sbtest2#P#p2.ibd sbtest2#P#p5.cfg sbtest2#P#p7.ibd sbtest2.frm

sbtest2#P#p0.ibd sbtest2#P#p11.cfg sbtest2#P#p13.ibd sbtest2#P#p16.cfg sbtest2#P#p18.ibd sbtest2#P#p3.cfg sbtest2#P#p5.ibd sbtest2#P#p8.cfg

sbtest2#P#p1.cfg sbtest2#P#p11.ibd sbtest2#P#p14.cfg sbtest2#P#p16.ibd sbtest2#P#p19.cfg sbtest2#P#p3.ibd sbtest2#P#p6.cfg sbtest2#P#p8.ibd

sbtest2#P#p1.ibd sbtest2#P#p12.cfg sbtest2#P#p14.ibd sbtest2#P#p17.cfg sbtest2#P#p19.ibd sbtest2#P#p4.cfg sbtest2#P#p6.ibd sbtest2#P#p9.cfg

进入到原表ibd所在的目录下,把原表需要迁移的分区表空间和元数据校验文件.cfg传输到新表所在的位置,并赋予权限 

1

2

3

4

5

6

[root@slave test]# cp sbtest2#P#p2.* sbtest2#P#p3.* sbtest2#P#p4.* sbtest2#P#p5.* sbtest2#P#p6.* sbtest2#P#p7.* sbtest2#P#p8.* sbtest2#P#p9.* sbtest2#P#p10.* sbtest2#P#p11.* sbtest2#P#p12.* sbtest2#P#p13.* /var/lib/mysql/data/mydata/testdba/

[root@slave test]# ls ../testdba/

db.opt sbtest2#P#p11.cfg sbtest2#P#p12.ibd sbtest2#P#p2.cfg sbtest2#P#p3.ibd sbtest2#P#p5.cfg sbtest2#P#p6.ibd sbtest2#P#p8.cfg sbtest2#P#p9.ibd

sbtest2#P#p10.cfg sbtest2#P#p11.ibd sbtest2#P#p13.cfg sbtest2#P#p2.ibd sbtest2#P#p4.cfg sbtest2#P#p5.ibd sbtest2#P#p7.cfg sbtest2#P#p8.ibd sbtest2.frm

sbtest2#P#p10.ibd sbtest2#P#p12.cfg sbtest2#P#p13.ibd sbtest2#P#p3.cfg sbtest2#P#p4.ibd sbtest2#P#p6.cfg sbtest2#P#p7.ibd sbtest2#P#p9.cfg

[root@slave test]# chown -R mysql:mysql /var/lib/mysql

切回到执行FLUSH TABLES ... FOR EXPORT语句窗口,释放共享表锁 

1

2

3

4

root@localhost : test 02:00:29> USE test;

Database changed

root@localhost : test 02:01:07> UNLOCK TABLES;

Query OK, 0 rows affected (0.00 sec)

进入新表所在的实例或新表所在的库,手动导入分区表空间,进行数据恢复(应用传输到新表的分区表空间) 

1

2

3

4

root@localhost : test 02:01:07> USE testdba;

Database changed

root@localhost : testdba 02:01:14> ALTER TABLE sbtest2 IMPORT PARTITION p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13 TABLESPACE;

Query OK, 0 rows affected (0.62 sec)

表空间迁移完成,数据恢复完成,最后校验数据准确性 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

root@localhost : testdba 02:03:16> SELECT PARTITION_NAME, TABLE_ROWS FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_NAME = 'sbtest2' and TABLE_SCHEMA='testdba';

+----------------+------------+

| PARTITION_NAME | TABLE_ROWS |

+----------------+------------+

| p2 | 2 |

| p3 | 2 |

| p4 | 2 |

| p5 | 2 |

| p6 | 2 |

| p7 | 2 |

| p8 | 2 |

| p9 | 2 |

| p10 | 2 |

| p11 | 2 |

| p12 | 2 |

| p13 | 2 |

+----------------+------------+

12 rows in set (0.00 sec)

| 总结

以上是我们使用MySQL的分区表空间传输方法,解决了分区表历史数据归档到其他实例或者同一实例其他库的问题。对比逻辑迁移方式mysqldump或者insert .. select ...方式速度更快,数据立即可用,而且对业务的影响更小。

 

| 作者简介

岳雷·沃趣科技数据库工程师

熟悉MySQL体系结构和innodb存储引擎工作原理;以及MySQL备份恢复、复制、数据迁移等技术;专注于MySQL、MariaDB开源数据库,喜好开源技术。

转载来源:http://blog.itpub.net/28218939/viewspace-2638041

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值