mysql交换分区_MySQL 5.6和5.7分区交换笔记

本文介绍了MySQL中的分区交换技术,特别是在5.6和5.7版本之间的差异。5.6版本中,交换分区涉及拷贝分区文件,效率不高,而在5.7版本中,分区交换变得更加直接。通过实例展示了如何在不同版本中交换分区,以及如何归档数据,以提高数据操作的效率。
摘要由CSDN通过智能技术生成

1.概述

分区表在生产环境用的太多太多,当分区增长到一定数量的时候,我们需要将数据归档,我见过有些运维在oracle环境下是这么做的,将需要归档的数据插入到其他表,于是执行这么一条语句:

insert into archive_tbl select * from live_tbl where "过滤条件"/partition 分区名;

当分区数据量有几十个GB,甚至上百GB的时候,这种操作是非常要命的,需要把交换的分区读进来,写出去,浪费非常多的IO资源,对于OLTP缓解来讲,业务高峰期,这是致命的,各种等待事件一下就上来了,搞得你目瞪口呆。

当我们使用分区交换技术的时候,将数据归档到其他表,都是妙级操作,更改的只是数据字典。在mysql中,分区交换技术主要在5.7这个版本有变化,5.7以前和5.7实现交换,略有不同。5.6的分区表交换分区比较绕,而且需要拷贝分区文件,效率不是特别高,不过话又说回来,拷贝分区文件比导入导出快多了,最后,我们也并不是特别推荐在5.6里面使用分区表,mysql内部一个分区使用一个handler,可能最后弊大于利。

本文没有深入分析分区交换的原理,也没有任何拓展。只是看到oracle环境用分区交换比较多,一时兴起记下mysql分区交换。

2.mysql5.7以前分区交换

2.1环境交代

这里我们借用percona的题材

mysql版本:5.6.34

live_tbl:生产表

archive_tbl:归档表

p201203,这个分区准备从生产表交换到归档表

dest_tbl_tmp:临时表

2.2数据准备

CREATE TABLE live_tbl (

some_id bigint(20) NOT NULL AUTO_INCREMENT,

summary_date date NOT NULL,

PRIMARY KEY (some_id,summary_date)

) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci

/*!50500 PARTITION BY RANGE COLUMNS(summary_date)

(PARTITION p201703 VALUES LESS THAN ('2017-04-01') ENGINE = InnoDB,

PARTITION p201704 VALUES LESS THAN ('2017-05-01') ENGINE = InnoDB,

PARTITION p201705 VALUES LESS THAN ('2017-06-01') ENGINE = InnoDB,

PARTITION p201706 VALUES LESS THAN ('2017-07-01') ENGINE = InnoDB,

PARTITION future VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB) */;

INSERT INTO live_tbl(summary_date) VALUES

('2017-03-15'),('2017-03-18'),

('2017-04-15'),('2017-04-18'),

('2017-05-15'),('2017-05-18'),

('2017-06-15'),('2017-06-18'),

('2017-07-15'),('2017-07-18');

root@localhost [thedb] 01:10:06>>>select * from live_tbl partition(p201703);

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

| some_id | summary_date |

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

| 1 | 2017-03-15 |

| 2 | 2017-03-18 |

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

2 rows in set (0.00 sec)

root@localhost [thedb] 01:10:26>>>select * from live_tbl partition(p201704);

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

| some_id | summary_date |

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

| 3 | 2017-04-15 |

| 4 | 2017-04-18 |

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

2 rows in set (0.00 sec)

root@localhost [thedb] 01:10:28>>>select * from live_tbl partition(p201705);

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

| some_id | summary_date |

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

| 5 | 2017-05-15 |

| 6 | 2017-05-18 |

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

2 rows in set (0.00 sec)

root@localhost [thedb] 01:10:30>>>select * from live_tbl partition(p201706);

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

| some_id | summary_date |

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

| 7 | 2017-06-15 |

| 8 | 2017-06-18 |

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

2 rows in set (0.00 sec)

root@localhost [thedb] 01:10:34>>>select * from live_tbl partition(future);

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

| some_id | summary_date |

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

| 9 | 2017-07-15 |

| 10 | 2017-07-18 |

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

2 rows in set (0.00 sec)

CREATE TABLE archive_tbl (

some_id bigint(20) NOT NULL AUTO_INCREMENT,

summary_date date NOT NULL,

PRIMARY KEY (some_id,summary_date)

) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci

/*!50500 PARTITION BY RANGE COLUMNS(summary_date)

(PARTITION p201609 VALUES LESS THAN ('2016-10-01') ENGINE = InnoDB,

PARTITION p201610 VALUES LESS THAN ('2016-11-01') ENGINE = InnoDB,

PARTITION p201611 VALUES LESS THAN ('2016-12-01') ENGINE = InnoDB,

PARTITION p201612 VALUES LESS THAN ('2017-01-01') ENGINE = InnoDB,

PARTITION p201701 VALUES LESS THAN ('2017-02-01') ENGINE = InnoDB,

PARTITION p201702 VALUES LESS THAN ('2017-03-01') ENGINE = InnoDB,

PARTITION future VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB) */;

INSERT INTO archive_tbl(summary_date) VALUES

('2016-09-15'),('2016-09-18'),

('2016-10-15'),('2016-10-18'),

('2016-11-15'),('2016-11-18'),

('2016-12-15'),('2016-12-18'),

('2017-01-15'),('2017-01-18'),

('2017-02-15'),('2017-02-18');

root@localhost [thedb] 01:47:42>>>select * from archive_tbl partition(p201609);

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

| some_id | summary_date |

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

| 1 | 2016-09-15 |

| 2 | 2016-09-18 |

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

2 rows in set (0.00 sec)

root@localhost [thedb] 01:47:42>>>select * from archive_tbl partition(p201610);

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

| some_id | summary_date |

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

| 3 | 2016-10-15 |

| 4 | 2016-10-18 |

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

2 rows in set (0.00 sec)

root@localhost [thedb] 01:47:42>>>select * from archive_tbl partition(p201611);

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

| some_id | summary_date |

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

| 5 | 2016-11-15 |

| 6 | 2016-11-18 |

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

2 rows in set (0.00 sec)

root@localhost [thedb] 01:47:42>>>select * from archive_tbl partition(p201612);

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

| some_id | summary_date |

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

| 7 | 2016-12-15 |

| 8 | 2016-12-18 |

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

2 rows in set (0.00 sec)

root@localhost [thedb] 01:47:42>>>select * from archive_tbl partition(p201701);

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

| some_id | summary_date |

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

| 9 | 2017-01-15 |

| 10 | 2017-01-18 |

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

2 rows in set (0.00 sec)

root@localhost [thedb] 01:47:42>>>select * from archive_tbl partition(p201702);

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

| some_id | summary_date |

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

| 11 | 2017-02-15 |

| 12 | 2017-02-18 |

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

2 rows in set (0.00 sec)

2.2 创建临时表

mysql> CREATE TABLE dest_tbl_tmp LIKE archive_tbl;

mysql> ALTER TABLE dest_tbl_tmp REMOVE PARTITIONING;

mysql> ALTER TABLE dest_tbl_tmp DISCARD TABLESPACE;

2.3 拷贝交换分区

为了保证数据一致性,我们flush一下。

mysql> USE thedb

mysql> FLUSH TABLE live_tbl FOR EXPORT;

然后在操作系统层面讲分区拷贝到临时表:

shell> cp live_tbl#P#p201703.ibd dest_tbl_tmp.ibd

然后import分区到临时表

mysql> unlock tables;

mysql> ALTER TABLE dest_tbl_tmp IMPORT TABLESPACE;

2.4 归档表添加分区

mysql> ALTER TABLE archive_tbl REORGANIZE PARTITION future INTO (

PARTITION p201703 VALUES LESS THAN ('2017-04-01'),

PARTITION future VALUES LESS THAN (MAXVALUE)

);

2.5 进行分区交换

mysql> ALTER TABLE archive_tbl EXCHANGE PARTITION p201703 WITH TABLE dest_tbl_tmp;

2.6 删除久分区,并验证

root@localhost [thedb] 02:17:06>>>select * from archive_tbl partition(p201703);

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

| some_id | summary_date |

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

| 1 | 2017-03-15 |

| 2 | 2017-03-18 |

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

2 rows in set (0.01 sec)

mysql>ALTER TABLE live_tbl DROP PARTITION p201703;

3. mysql5.7的分区交换

5.7的分区交换相对容易,不需要那么绕。

表和数据准备:

CREATE TABLE e (

id INT NOT NULL,

fname VARCHAR(30),

lname VARCHAR(30)

)

PARTITION BY RANGE (id) (

PARTITION p0 VALUES LESS THAN (50),

PARTITION p1 VALUES LESS THAN (100),

PARTITION p2 VALUES LESS THAN (150),

PARTITION p3 VALUES LESS THAN (MAXVALUE)

);

INSERT INTO e VALUES

(1669, "Jim", "Smith"),

(337, "Mary", "Jones"),

(16, "Frank", "White"),

(2005, "Linda", "Black");

准备一张结构相似的非分区表:

CREATE TABLE e2 LIKE e;

ALTER TABLE e2 REMOVE PARTITIONING;

各个分区数据的分布:

root@localhost [db01] 03:47:50>>>SELECT PARTITION_NAME, TABLE_ROWS FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_NAME = 'e';

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

| PARTITION_NAME | TABLE_ROWS |

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

| p0 | 1 |

| p1 | 0 |

| p2 | 0 |

| p3 | 3 |

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

4 rows in set (0.00 sec)

将P0分区交换出去

ALTER TABLE e EXCHANGE PARTITION p0 WITH TABLE e2;

验证现有数据:

root@localhost [db01] 03:48:56>>>SELECT PARTITION_NAME, TABLE_ROWS FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_NAME = 'e';

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

| PARTITION_NAME | TABLE_ROWS |

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

| p0 | 0 |

| p1 | 0 |

| p2 | 0 |

| p3 | 2 |

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

4 rows in set (0.00 sec)

查看交换出来的数据:

root@localhost [db01] 03:48:57>>>SELECT * FROM e2;

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

| id | fname | lname |

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

| 16 | Frank | White |

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

1 row in set (0.00 sec)

Posted in MySQL

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值