Posted at

MySQLのevent_schedulerでテーブルパーティションを追加

More than 1 year has passed since last update.


CREATE TABLE

CREATE TABLE `t1` (

`id` bigint(20) NOT NULL AUTO_INCREMENT,
`created_at` datetime NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
/*!50500 PARTITION BY RANGE COLUMNS(created_at)
(PARTITION p201711 VALUES LESS THAN ('2017-12-01 00:00:00') ENGINE = InnoDB,
PARTITION p201712 VALUES LESS THAN ('2018-01-01 00:00:00') ENGINE = InnoDB,
PARTITION p201801 VALUES LESS THAN ('2018-02-01 00:00:00') ENGINE = InnoDB) */
;


CREATE PROCEDURE

プロシージャの関数として定義しておいた方が、デバッグとか楽だった。

関数の引数にテーブル名とか渡せるようにすれば、同様のパーティションロジックのテーブルについては対応できる。

DELIMITER $$

CREATE PROCEDURE add_partition()
BEGIN
-- 翌月のパーティション名
SET @pname = CONCAT('p', DATE_FORMAT(DATE_ADD(CURDATE(), INTERVAL 1 MONTH), '%Y%m'));
-- パーティション名が定義済みか取得
SELECT COUNT(*) INTO @is_parted
FROM INFORMATION_SCHEMA.PARTITIONS
WHERE TABLE_NAME = 't1' AND PARTITION_NAME = @pname;

IF @is_parted = 0 THEN
SET @lt = DATE_FORMAT(DATE_ADD(CURDATE(), INTERVAL 2 MONTH), '%Y-%m-01 00:00:00');

SET @query = CONCAT('ALTER TABLE t1 ADD PARTITION (PARTITION ', @pname);
SET @query = CONCAT(@query, ' VALUES LESS THAN (''', @lt, '''))');
PREPARE s FROM @query;
EXECUTE s;
END IF;
END $$
DELIMITER ;


CREATE EVENT

DELIMITER |

CREATE EVENT IF NOT EXISTS `e_partition`
ON SCHEDULE EVERY 1 DAY ENABLE
COMMENT 'monthly patitioning for t1'
DO BEGIN
CALL add_partition();
END|
DELIMITER ;

MySQLのイベントスケジューラを使ったことが無かったけど、こういう局所的な用途とかだと手軽で良いかもと思った、

困ったのは、プロシージャのデバッグ方法、以下のコメントでデバッグ用の関数を用意してデバッグする方法が良い感じだった

https://stackoverflow.com/a/15687954