您可以通過建立定時任務的方式來建立、刪除或交換分區,以實現分區自動化管理。
背景資訊
在某些行業中,固定周期內可能會產生大量的資料,同時也會通過刪除大量資料的方式來節省儲存空間。如果新產生的資料和需要刪除的資料儲存在同一張表中,周期性的大批量資料更新,極有可能影響業務的連續性。且在分區表使用不夠普遍的情況下,通常的做法是,由DBA在營運時間內定期手動建立新表來承載新的資料,並且需要刪除無用資料所在的表。
這種情境存在一系列痛點:
周期性的大批次更新表,可能會對業務的連續性有影響。
DBA在營運時間內手動更新表資料,會增加營運成本。
通過建立定時任務的方式來實現自動化管理分區,既可以避免影響商務持續性,也可以減少不必要的人工操作。
前提條件
叢集版本需為PolarDB MySQL版8.0.2版本且Revision version為8.0.2.2.0及以上。您可以通過查詢版本號碼確認叢集版本。
定時任務文法
文法
CREATE
[DEFINER = user]
EVENT
[IF NOT EXISTS]
event_name
ON SCHEDULE schedule
[ON COMPLETION [NOT] PRESERVE]
[ENABLE | DISABLE | DISABLE ON SLAVE]
[COMMENT 'string']
DO event_body;
參數說明
參數 | 是否必選 | 說明 |
DEFINER | 否 | 給指定使用者添加該定時任務的使用許可權。 |
IF NOT EXISTS | 否 | 判斷需要建立的事件是否已存在。 |
event_name | 是 | 指定事件名稱。 |
schedule | 是 | 指定該事件的調度時間。調度時間文法支援以下兩種:
其中,
|
ON COMPLETION [NOT] PRESERVE | 否 | 指定事件執行完一次後的處理方式。
|
ENABLE、DISABLE、DISABLE ON SLAVE | 否 | 指定事件的一種屬性。取值如下:
|
COMMENT ‘comment’ | 否 | 指定事件的注釋。 |
DO event_body | 是 | 指定事件啟動時需要執行的代碼。 說明
|
樣本
假設資料庫中存在一張INTERVAL RANGE分區表orders
,該表以時間列作為分區鍵,可以將不同時間範圍內的資料劃分到不同的分區中。建表語句如下所示:
CREATE TABLE orders(
id int,
ordertime datetime
)
PARTITION BY RANGE COLUMNS(ordertime) INTERVAL(DAY, 1)
(
PARTITION p20220520 VALUES LESS THAN('2022-05-20'),
PARTITION p20220521 VALUES LESS THAN('2022-05-21')
);
基於orders
表來介紹定時新增分區、定時刪除分區和定時轉換分區的使用方法。
定時新增分區
如果您需要為orders
分區表定時新增分區,可以通過建立定時任務的方式定時觸發新增分區,樣本如下:
DELIMITER ||
CREATE EVENT IF NOT EXISTS add_partition ON SCHEDULE
EVERY 1 DAY STARTS '2022-05-20 22:00:00'
ON COMPLETION PRESERVE
DO
BEGIN
set @pname = concat("alter table orders add partition (partition p",date_format(date_add(curdate(), interval 2 day), '%Y%m%d'), " values less than('", date_add(curdate(), interval 2 day), "'))");
prepare stmt_add_partition from @pname;
execute stmt_add_partition;
deallocate prepare stmt_add_partition;
END ||
DELIMITER ;
假設當前已經存在的最大的分區範圍為:2022-05-20 00:00:00
~2022-05-20 23:59:59
,該定時任務可以從2022-05-20 22:00:00
開始,每天建立一個新的分區,來儲存第二天的資料。
如果分區表orders
為INTERVAL RANGE分區,也可以通過INSERT方式定時觸發新增分區,樣本如下:
CREATE EVENT IF NOT EXISTS add_partition ON SCHEDULE
EVERY 1 DAY STARTS '2022-05-20 00:00:00'
ON COMPLETION PRESERVE
DO INSERT INTO orders VALUES(id, DATE_ADD(NOW(), INTERVAL 1 DAY));
假設當前最大的分區範圍是2022-05-20 00:00:00
~2022-05-20 23:59:59
,定時任務會從2022-05-20 00:00:00
開始執行,每天新增一個新分區,而且是提前一天新增下一天的分區。
定時刪除分區
如果業務上需要定期清理orders
表中無用的資料,可以建立一個定時任務刪除對應的分區。樣本如下:
DELIMITER ||
CREATE EVENT IF NOT EXISTS drop_partition ON SCHEDULE
EVERY 1 DAY STARTS '2022-05-21 02:00:00'
ON COMPLETION PRESERVE
DO
BEGIN
set @pname = concat('alter table orders drop partition p', date_format(curdate(), '%Y%m%d'));
prepare stmt_drop_partition from @pname;
execute stmt_drop_partition;
deallocate prepare stmt_drop_partition;
END ||
DELIMITER ;
假設營運時間從02:00
開始,該定時任務會從2022-05-21 02:00:00
開始,在每天的02:00
刪除前一天建立的分區。
定時轉換分區
如果您不想直接刪除orders
表中的分區,也可以通過exchange_partition將不再需要的分區轉成一張表,這張表與orders
分區表完全獨立,您可以自行決定如何處理這張表中的資料。樣本如下:
-- 建立一個與分區表相同表結構的非分區表來做exchange, DDL結束後分區資料會被交換出去,原來的分區會變為空白分區。
DELIMITER ||
CREATE EVENT IF NOT EXISTS exchange_partition ON SCHEDULE
EVERY 1 DAY STARTS '2022-05-21 02:00:00'
ON COMPLETION PRESERVE
DO
BEGIN
set @pname = concat('create table orders_', date_format(curdate(), '%Y%m%d'), '(id int, ordertime datetime)');
prepare stmt_create_table from @pname;
execute stmt_create_table;
deallocate prepare stmt_create_table;
set @pname = concat('alter table orders exchange partition p', date_format(curdate(), '%Y%m%d'), ' with table orders_', date_format(curdate(), '%Y%m%d'));
prepare stmt_exchange_partition from @pname;
execute stmt_exchange_partition;
deallocate prepare stmt_exchange_partition;
END ||
DELIMITER ;
該任務會從2022-05-21 02:00:00
開始,在每天的02:00
,將前一天建立的分區與一個空表進行交換,分區中原有的資料都會儲存在被交換的表中。