The Data Lifecycle Management (DLM) feature allows you to automatically and regularly archive cold data from PolarStore to cost-effective OSS storage, which reduces costs and improves efficiency.
Limitations
The DLM feature supports only partitioned tables that use the RANGE COLUMN partitioning method and do not contain subpartitions.
You cannot use the DLM feature on a partitioned table that has a global secondary index (GSI).
PolarDB for MySQL does not support modifying DLM policies. To make changes, delete the existing policy and create a new one.
If a table has an active DLM policy, avoid DDL operations that create inconsistencies between the source and archived tables, such as adding or dropping columns or modifying column data types. Such inconsistencies can make subsequent archived data unparsable. Before performing these DDL operations, you must delete the DLM policy. To resume automatic archiving, create a new DLM policy and specify a new name for the archived table. This name must not be the same as any previously used archived table name.
We recommend that you use INTERVAL RANGE partitioning to automatically extend partitions and use the DLM feature to archive data from infrequently used partitions to OSS.
Note INTERVAL RANGE partitioning is supported only for clusters that run PolarDB for MySQL 8.0.2 with revision version 8.0.2.2.0 or later.
You must specify a DLM policy when you run the CREATE TABLE or ALTER TABLE statement.
The SHOW CREATE TABLE statement does not display DLM policies. You can view all DLM policies in the mysql.dlm_policies table.
Precautions
After cold data is archived, the archived table in OSS is read-only, and its query performance might decrease. You must test beforehand to ensure the query performance meets your requirements.
After partitions of a partitioned table are archived to OSS, the data in the archived partitions becomes read-only. You cannot perform DDL operations on the partitioned table.
Backups do not include data archived to OSS. Data in OSS does not support point-in-time recovery.
Create DLM policy
Create a DLM policy with CREATE TABLE
CREATE TABLE [IF NOT EXISTS] tbl_name
(create_definition,...)
[table_options]
[partition_options]
[dlm_add_options]
dlm_add_options:
DLM ADD
[(dlm_policy_definition [, dlm_policy_definition] ...)]
dlm_policy_definition:
POLICY policy_name
[TIER TO TABLE/TIER TO PARTITION/TIER TO NONE]
[ENGINE [=] engine_name]
[STORAGE SCHEMA_NAME [=] storage_schema_name]
[STORAGE TABLE_NAME [=] storage_table_name]
[STORAGE [=] OSS]
[READ ONLY]
[COMMENT 'comment_string']
[EXTRA_INFO 'extra_info']
ON [(PARTITIONS OVER num)]
Create a DLM policy with ALTER TABLE
ALTER TABLE tbl_name
[alter_option [, alter_option] ...]
[partition_options]
[dlm_add_options]
dlm_add_options:
DLM ADD
[(dlm_policy_definition [, dlm_policy_definition] ...)]
dlm_policy_definition:
POLICY policy_name
[TIER TO TABLE/TIER TO PARTITION/TIER TO NONE]
[ENGINE [=] engine_name]
[STORAGE SCHEMA_NAME [=] storage_schema_name]
[STORAGE TABLE_NAME [=] storage_table_name]
[STORAGE [=] OSS]
[READ ONLY]
[COMMENT 'comment_string']
[EXTRA_INFO 'extra_info']
ON [(PARTITIONS OVER num)]
DLM policy parameters
Parameter | Required | Description |
tbl_name | Yes | The name of the table. |
policy_name | Yes | The name of the policy. |
TIER TO TABLE | Yes | Archives data to a table. |
TIER TO PARTITION | Yes | Converts partitions to be stored in OSS, creating a hybrid partitioned table.
Note This feature is in canary release. To use this feature, go to Quota Center, find the quota with the ID polardb_mysql_hybrid_partition, and click Apply in the Actions column. You can archive the partitions of a partitioned table to OSS only if your cluster runs PolarDB for MySQL 8.0.2 with revision version 8.0.2.2.17 or later. When you use this feature, make sure that the total number of partitions in the partitioned table does not exceed 8,192.
|
TIER TO NONE | Yes | Deletes cold data instead of archiving it. |
engine_name | No | The storage engine for the archived data. Currently, you can archive data only to the CSV engine. |
storage_schema_name | No | When archiving to a table, this parameter specifies the database that contains the table. Defaults to the source table's database. |
storage_table_name | No | When archiving to a table, this parameter specifies the name of the archived table. The default is <source_table_name>_<current_dlm_policy_name>. |
STORAGE [=] OSS | No | The archived data is stored in the OSS engine. This is the default setting. |
READ ONLY | No | The archived data is read-only. This is the default setting. |
comment_string | No | The comment for the DLM policy. |
extra_info | No | The OSS_FILE_FILTER information for the destination OSS table.
Note You can archive partitions of partitioned tables to OSS only if your cluster runs the Enterprise Edition of PolarDB for MySQL 8.0.2 with revision version 8.0.2.2.25 or later. This parameter applies only if the destination table does not exist. In this case, the system automatically generates a FILE_FILTER attribute based on the OSS_FILE_FILTER value in the EXTRA_INFO parameter and generates filter data during archiving. If the destination table already exists, its existing file filter is used instead.
The format of EXTRA_INFO is {"oss_file_filter":"field_filter[,field_filter]"}, where field_filter uses the following format: field_filter := field_name[:filter_type]
filter_type := bloom
|
ON (PARTITIONS OVER num) | Yes | Archives data when the number of partitions exceeds num. |
Manage DLM policy
Enable a DLM policy.
ALTER TABLE table_name DLM ENABLE POLICY [(dlm_policy_name [, dlm_policy_name] ...)]
Disable a DLM policy.
ALTER TABLE table_name DLM DISABLE POLICY [(dlm_policy_name [, dlm_policy_name] ...)]
Delete a DLM policy.
ALTER TABLE table_name DLM DROP POLICY [(dlm_policy_name [, dlm_policy_name] ...)]
In the preceding statements, table_name specifies the name of the table, and dlm_policy_name specifies the name of the policy to manage. You can specify multiple policy names.
Execute DLM policy
Execute all DLM policies on all tables in the current cluster.
CALL dbms_dlm.execute_all_dlm_policies();
Execute the DLM policies on a specific table.
CALL dbms_dlm.execute_table_dlm_policies('database_name', 'table_name');
In the preceding statement, database_name specifies the name of the database, and table_name specifies the name of the table.
You can use the mysql event feature to run DLM policies during your cluster's maintenance window. This avoids impacting database performance during peak hours and periodically moves expired data to reduce storage costs. The syntax for creating such an event is as follows:
CREATE
EVENT
[IF NOT EXISTS]
event_name
ON SCHEDULE schedule
[COMMENT 'comment']
DO event_body;
schedule: {
EVERY interval
[STARTS timestamp [+ INTERVAL interval] ...]
}
interval:
quantity {YEAR | QUARTER | MONTH | DAY | HOUR | MINUTE |
WEEK | SECOND | YEAR_MONTH | DAY_HOUR | DAY_MINUTE |
DAY_SECOND | HOUR_MINUTE | HOUR_SECOND | MINUTE_SECOND}
event_body: {
CALL dbms_dlm.execute_all_dlm_policies();
| CALL dbms_dlm.execute_table_dlm_policies('database_name', 'table_name');
}
The following table describes the parameters.
Parameter | Required | Description |
event_name | Yes | The name of the event. |
schedule | Yes | The time and frequency at which the event runs. |
comment | No | The comment for the event. |
event_body | Yes | The statement that the event executes. This must be a DLM policy execution statement.
Note If you specify CALL dbms_dlm.execute_all_dlm_policies(), the event executes all DLM policies on the cluster. Therefore, you must create one event for each cluster. If you specify CALL dbms_dlm.execute_table_dlm_policies('database_name', 'table_name');, the event executes all DLM policies only on a specific table. Therefore, you must create a corresponding event for each table that has a DLM policy to archive its data at a specified time.
|
interval | Yes | The execution interval of the event. |
timestamp | Yes | The time to start running the event. |
database_name | Yes | The database name. |
table_name | Yes | The table name. |
For more information about the MySQL EVENT feature, see the official MySQL documentation for events.
For usage examples, see Archive cold data to OSS.
Examples
Archive data to an OSS foreign table
Create a DLM policy
The following example creates a partitioned table named sales. The table uses the order_time column as the partition key and is partitioned by a time interval. The table has both an INTERVAL policy and a DLM policy:
INTERVAL policy: When inserted data falls outside the range of existing partitions, a new partition is automatically created. The time interval is one year.
DLM policy: The table retains only three partitions. When the number of partitions exceeds three, the DLM policy is triggered and performs one of the following actions:
If the OSS foreign table sales_history does not exist, create a new OSS foreign table sales_history, and dump the cold data to the sales_history foreign table.
If the sales_history foreign table exists, and the sales_history table is located on the built-in OSS space, cold data is directly dumped to the sales_history foreign table.
Note Creating an INTERVAL RANGE partitioned table has prerequisites. For more information about using INTERVAL, see INTERVAL RANGE partitioning.
Create the sales table with a DLM policy.
CREATE TABLE `sales` (
`id` int DEFAULT NULL,
`name` varchar(20) DEFAULT NULL,
`order_time` datetime NOT NULL,
PRIMARY KEY (`order_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
PARTITION BY RANGE COLUMNS(order_time) INTERVAL(YEAR, 1)
(PARTITION p20200101000000 VALUES LESS THAN ('2020-01-01 00:00:00') ENGINE = InnoDB,
PARTITION p20210101000000 VALUES LESS THAN ('2021-01-01 00:00:00') ENGINE = InnoDB,
PARTITION p20220101000000 VALUES LESS THAN ('2022-01-01 00:00:00') ENGINE = InnoDB)
DLM ADD POLICY test_policy TIER TO TABLE ENGINE=CSV STORAGE=OSS READ ONLY
STORAGE TABLE_NAME = 'sales_history' EXTRA_INFO '{"oss_file_filter":"id,name:bloom"}' ON (PARTITIONS OVER 3);
The DLM policy for this table is named test_policy. When the number of partitions exceeds three, the cold data from the source table is archived to OSS in CSV format. The archived table is named sales_history and is read-only. If the destination OSS table does not exist, the system automatically creates it and adds an OSS_FILE_FILTER on the id and name columns.
The DLM policies for the current table are stored in the mysql.dlm_policies system table. You can view the details of the DLM policies in this table. For details about the mysql.dlm_policies table, see Schema Description. View the schema of the mysql.dlm_policies table.
mysql> SELECT * FROM mysql.dlm_policies\G
The following result is returned:
*************************** 1. row ***************************
Id: 3
Table_schema: test
Table_name: sales
Policy_name: test_policy
Policy_type: TABLE
Archive_type: PARTITION COUNT
Storage_mode: READ ONLY
Storage_engine: CSV
Storage_media: OSS
Storage_schema_name: test
Storage_table_name: sales_history
Data_compressed: OFF
Compressed_algorithm: NULL
Enabled: ENABLED
Priority_number: 10300
Tier_partition_number: 3
Tier_condition: NULL
Extra_info: {"oss_file_filter": "id,name:bloom,order_time"}
Comment: NULL
1 row in set (0.03 sec)
Currently, the sales table has three partitions, so no data is archived.
Insert 3,000 rows of test data into the sales partitioned table. Inserting data outside the range of existing partitions triggers the INTERVAL policy to automatically create new partitions.
DROP PROCEDURE IF EXISTS proc_batch_insert;
delimiter $$
CREATE PROCEDURE proc_batch_insert(IN begin INT, IN end INT, IN name VARCHAR(20))
BEGIN
SET @insert_stmt = concat('INSERT INTO ', name, ' VALUES(? , ?, ?);');
PREPARE stmt from @insert_stmt;
WHILE begin <= end DO
SET @ID1 = begin;
SET @NAME = CONCAT(begin+begin*281313, '@stiven');
SET @TIME = from_days(begin + 737600);
EXECUTE stmt using @ID1, @NAME, @TIME;
SET begin = begin + 1;
END WHILE;
END;
$$
delimiter ;
CALL proc_batch_insert(1, 3000, 'sales');
The INTERVAL policy automatically creates new partitions, increasing the partition count of the sales table. The table schema is now:
mysql> SHOW CREATE TABLE sales\G
The following result is returned:
*************************** 1. row ***************************
Table: sales
Create Table: CREATE TABLE `sales` (
`id` int(11) DEFAULT NULL,
`name` varchar(20) DEFAULT NULL,
`order_time` datetime NOT NULL,
PRIMARY KEY (`order_time`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
/*!50500 PARTITION BY RANGE COLUMNS(order_time) */
/*!99990 800020200 INTERVAL(YEAR, 1) */
/*!50500 (PARTITION p20200101000000 VALUES LESS THAN ('2020-01-01 00:00:00') ENGINE = InnoDB,
PARTITION p20210101000000 VALUES LESS THAN ('2021-01-01 00:00:00') ENGINE = InnoDB,
PARTITION p20220101000000 VALUES LESS THAN ('2022-01-01 00:00:00') ENGINE = InnoDB,
PARTITION _p20230101000000 VALUES LESS THAN ('2023-01-01 00:00:00') ENGINE = InnoDB,
PARTITION _p20240101000000 VALUES LESS THAN ('2024-01-01 00:00:00') ENGINE = InnoDB,
PARTITION _p20250101000000 VALUES LESS THAN ('2025-01-01 00:00:00') ENGINE = InnoDB,
PARTITION _p20260101000000 VALUES LESS THAN ('2026-01-01 00:00:00') ENGINE = InnoDB,
PARTITION _p20270101000000 VALUES LESS THAN ('2027-01-01 00:00:00') ENGINE = InnoDB,
PARTITION _p20280101000000 VALUES LESS THAN ('2028-01-01 00:00:00') ENGINE = InnoDB) */
1 row in set (0.03 sec)
The table now has more than three partitions, which meets the DLM policy's execution condition. Data archiving can now proceed.
Execute the DLM policy
You can execute the DLM policy directly with an SQL statement or schedule periodic execution using the MySQL EVENT feature. For example, if your cluster's maintenance window starts at 01:00 every day from October 11, 2022, you can create the following event to execute the DLM policy daily at 01:00:
CREATE EVENT dlm_system_base_event
ON SCHEDULE EVERY 1 DAY
STARTS '2022-10-11 01:00:00'
do CALL
dbms_dlm.execute_all_dlm_policies();
After 01:00, this event executes all DLM policies on all tables.
Run the following command to view the schema of the sales table:
mysql> SHOW CREATE TABLE sales\G
The following result is returned:
*************************** 1. row ***************************;
Table: sales
Create Table: CREATE TABLE `sales` (
`id` int(11) DEFAULT NULL,
`name` varchar(20) DEFAULT NULL,
`order_time` datetime NOT NULL,
PRIMARY KEY (`order_time`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
/*!50500 PARTITION BY RANGE COLUMNS(order_time) */
/*!99990 800020200 INTERVAL(YEAR, 1) */
/*!50500 (PARTITION _p20260101000000 VALUES LESS THAN ('2026-01-01 00:00:00') ENGINE = InnoDB,
PARTITION _p20270101000000 VALUES LESS THAN ('2027-01-01 00:00:00') ENGINE = InnoDB,
PARTITION _p20280101000000 VALUES LESS THAN ('2028-01-01 00:00:00') ENGINE = InnoDB) */
1 row in set (0.03 sec)
The table now retains only three partitions.
You can view the execution records of DLM policies in the mysql.dlm_progress table. For information about the dlm_progress table schema, see System table schemas. Run the following command to view the information in the mysql.dlm_progress table:
mysql> SELECT * FROM mysql.dlm_progress\G
The following result is returned:
*************************** 1. row ***************************;
Id: 1
Table_schema: test
Table_name: sales
Policy_name: test_policy
Policy_type: TABLE
Archive_option: PARTITIONS OVER 3
Storage_engine: CSV
Storage_media: OSS
Data_compressed: OFF
Compressed_algorithm: NULL
Archive_partitions: p20200101000000, p20210101000000, p20220101000000, _p20230101000000, _p20240101000000, _p20250101000000
Archive_stage: ARCHIVE_COMPLETE
Archive_percentage: 0
Archived_file_info: null
Start_time: 2024-07-26 17:56:20
End_time: 2024-07-26 17:56:50
Extra_info: null
1 row in set (0.00 sec)
The partitions that store infrequently accessed cold data, including p20200101000000, p20210101000000, p20220101000000, _p20230101000000, _p20240101000000, and _p20250101000000, have been archived to the OSS foreign table.
Run the following command to view the schema of the OSS foreign table:
mysql> SHOW CREATE TABLE sales_history\G
The following result is returned:
*************************** 1. row ***************************;
Table: sales_history
Create Table: CREATE TABLE `sales_history` (
`id` int(11) DEFAULT NULL,
`name` varchar(20) DEFAULT NULL,
`order_time` datetime DEFAULT NULL,
PRIMARY KEY (`order_time`)
) /*!99990 800020213 STORAGE OSS */ ENGINE=CSV DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci /*!99990 800020204 NULL_MARKER='NULL' */ /*!99990 800020223 OSS META=1 */ /*!99990 800020224 OSS_FILE_FILTER='id,name:bloom,order_time' */
1 row in set (0.15 sec)
The table is now a CSV table with its data stored in OSS. You can query it in the same way as a local table. The system added the specified columns to the OSS_FILE_FILTER. Because order_time is a partition key, an OSS_FILE_FILTER is also created for it automatically.
Query the data in the sales and sales_history tables respectively.
SELECT COUNT(*) FROM sales;
+----------+
| count(*) |
+----------+
| 984 |
+----------+
1 row in set (0.01 sec)
SELECT COUNT(*) FROM sales_history;
+----------+
| count(*) |
+----------+
| 2016 |
+----------+
1 row in set (0.57 sec)
The total number of rows is 3,000, which matches the amount of data initially inserted into the sales table.
Query the OSS foreign table using OSS_FILE_FILTER. You must enable the OSS_FILE_FILTER switch first.
mysql> explain select * from sales_history where id = 9;
+----+-------------+---------------+------------+------+---------------+------+---------+------+------+----------+-----------------------------------------------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+---------------+------------+------+---------------+------+---------+------+------+----------+-----------------------------------------------------------------------------+
| 1 | SIMPLE | sales_history | NULL | ALL | NULL | NULL | NULL | NULL | 2016 | 10.00 | Using where; With pushed engine condition (`test`.`sales_history`.`id` = 9) |
+----+-------------+---------------+------------+------+---------------+------+---------+------+------+----------+-----------------------------------------------------------------------------+
1 row in set, 1 warning (0.59 sec)
mysql> select * from sales_history where id = 9;
+------+----------------+---------------------+
| id | name | order_time |
+------+----------------+---------------------+
| 9 | 2531826@stiven | 2019-07-04 00:00:00 |
+------+----------------+---------------------+
1 row in set (0.19 sec)
Archive partitions to OSS
Create a DLM policy
The following example creates a partitioned table named sales. The table uses the order_time column as the partition key and is partitioned by a time interval. The table has both an INTERVAL policy and a DLM policy:
INTERVAL policy: When inserted data falls outside the range of existing partitions, a new partition is automatically created. The time interval is one year.
DLM policy: The table retains only three partitions. When the number of partitions exceeds three, the DLM policy directly archives the older partitions to OSS.
Create the sales table.
CREATE TABLE `sales` (
`id` int DEFAULT NULL,
`name` varchar(20) DEFAULT NULL,
`order_time` datetime NOT NULL,
PRIMARY KEY (`order_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
PARTITION BY RANGE COLUMNS(order_time) INTERVAL(YEAR, 1)
(PARTITION p20200101000000 VALUES LESS THAN ('2020-01-01 00:00:00') ENGINE = InnoDB,
PARTITION p20210101000000 VALUES LESS THAN ('2021-01-01 00:00:00') ENGINE = InnoDB,
PARTITION p20220101000000 VALUES LESS THAN ('2022-01-01 00:00:00') ENGINE = InnoDB)
DLM ADD POLICY policy_part2part TIER TO PARTITION ENGINE=CSV STORAGE=OSS READ ONLY ON (PARTITIONS OVER 3);
The DLM policy for this table is named policy_part2part. When the number of partitions exceeds three, older partitions are archived to OSS.
View the DLM policy in the mysql.dlm_policies table.
SELECT * FROM mysql.dlm_policies\G
The following result is returned:
*************************** 1. row ***************************
Id: 2
Table_schema: test
Table_name: sales
Policy_name: policy_part2part
Policy_type: PARTITION
Archive_type: PARTITION COUNT
Storage_mode: READ ONLY
Storage_engine: CSV
Storage_media: OSS
Storage_schema_name: NULL
Storage_table_name: NULL
Data_compressed: OFF
Compressed_algorithm: NULL
Enabled: ENABLED
Priority_number: 10300
Tier_partition_number: 3
Tier_condition: NULL
Extra_info: null
Comment: NULL
1 row in set (0.03 sec)
Use the proc_batch_insert stored procedure to insert test data into the sales partitioned table to trigger the INTERVAL policy to automatically create new partitions.
CALL proc_batch_insert(1, 3000, 'sales');
The following result indicates that the data was inserted successfully:
Query OK, 1 row affected, 1 warning (0.99 sec)
Run the following command to view the schema of the sales table:
SHOW CREATE TABLE sales \G
The following result is returned:
*************************** 1. row ***************************
Table: sales
Create Table: CREATE TABLE `sales` (
`id` int(11) DEFAULT NULL,
`name` varchar(20) DEFAULT NULL,
`order_time` datetime DEFAULT NULL,
PRIMARY KEY (`order_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
/*!50500 PARTITION BY RANGE COLUMNS(order_time) */ /*!99990 800020200 INTERVAL(YEAR, 1) */
/*!50500 (PARTITION p20200101000000 VALUES LESS THAN ('2020-01-01 00:00:00') ENGINE = InnoDB,
PARTITION p20210101000000 VALUES LESS THAN ('2021-01-01 00:00:00') ENGINE = InnoDB,
PARTITION p20220101000000 VALUES LESS THAN ('2022-01-01 00:00:00') ENGINE = InnoDB,
PARTITION _p20230101000000 VALUES LESS THAN ('2023-01-01 00:00:00') ENGINE = InnoDB,
PARTITION _p20240101000000 VALUES LESS THAN ('2024-01-01 00:00:00') ENGINE = InnoDB,
PARTITION _p20250101000000 VALUES LESS THAN ('2025-01-01 00:00:00') ENGINE = InnoDB,
PARTITION _p20260101000000 VALUES LESS THAN ('2026-01-01 00:00:00') ENGINE = InnoDB,
PARTITION _p20270101000000 VALUES LESS THAN ('2027-01-01 00:00:00') ENGINE = InnoDB,
PARTITION _p20280101000000 VALUES LESS THAN ('2028-01-01 00:00:00') ENGINE = InnoDB) */
1 row in set (0.03 sec)
Execute the DLM policy
Run the following command to execute the DLM policy:
CALL dbms_dlm.execute_all_dlm_policies();
View the DLM execution records in the mysql.dlm_progress table.
SELECT * FROM mysql.dlm_progress \G
The following result is returned:
*************************** 1. row ***************************
Id: 4
Table_schema: test
Table_name: sales
Policy_name: policy_part2part
Policy_type: PARTITION
Archive_option: PARTITIONS OVER 3
Storage_engine: CSV
Storage_media: OSS
Data_compressed: OFF
Compressed_algorithm: NULL
Archive_partitions: p20200101000000, p20210101000000, p20220101000000, _p20230101000000, _p20240101000000, _p20250101000000
Archive_stage: ARCHIVE_COMPLETE
Archive_percentage: 100
Archived_file_info: null
Start_time: 2023-09-11 18:04:39
End_time: 2023-09-11 18:04:40
Extra_info: null
1 row in set (0.02 sec)
Run the following command to view the schema of the sales table:
SHOW CREATE TABLE sales \G
The following result is returned:
*************************** 1. row ***************************
Table: sales
Create Table: CREATE TABLE `sales` (
`id` int(11) DEFAULT NULL,
`name` varchar(20) DEFAULT NULL,
`order_time` datetime DEFAULT NULL,
PRIMARY KEY (`order_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci CONNECTION='default_oss_server'
/*!99990 800020205 PARTITION BY RANGE COLUMNS(order_time) */ /*!99990 800020200 INTERVAL(YEAR, 1) */
/*!99990 800020205 (PARTITION p20200101000000 VALUES LESS THAN ('2020-01-01 00:00:00') ENGINE = CSV,
PARTITION p20210101000000 VALUES LESS THAN ('2021-01-01 00:00:00') ENGINE = CSV,
PARTITION p20220101000000 VALUES LESS THAN ('2022-01-01 00:00:00') ENGINE = CSV,
PARTITION _p20230101000000 VALUES LESS THAN ('2023-01-01 00:00:00') ENGINE = CSV,
PARTITION _p20240101000000 VALUES LESS THAN ('2024-01-01 00:00:00') ENGINE = CSV,
PARTITION _p20250101000000 VALUES LESS THAN ('2025-01-01 00:00:00') ENGINE = CSV,
PARTITION _p20260101000000 VALUES LESS THAN ('2026-01-01 00:00:00') ENGINE = InnoDB,
PARTITION _p20270101000000 VALUES LESS THAN ('2027-01-01 00:00:00') ENGINE = InnoDB,
PARTITION _p20280101000000 VALUES LESS THAN ('2028-01-01 00:00:00') ENGINE = InnoDB) */
1 row in set (0.03 sec)
The schema information shows that the partitions p20200101000000, p20210101000000, p20220101000000, _p20230101000000, _p20240101000000, and _p20250101000000 of the sales partitioned table have been archived to OSS. Only the three hot data partitions _p20260101000000, _p20270101000000, and _p20280101000000 remain in the InnoDB engine. The sales table is now a hybrid partitioned table. For information on how to query data in a hybrid partitioned table, see Query a hybrid partitioned table.
Delete cold data directly
Create a DLM policy
The following example creates a partitioned table named sales. The table uses the order_time column as the partition key and is partitioned by a time interval. The table has both an INTERVAL policy and a DLM policy:
INTERVAL policy: When inserted data falls outside the range of existing partitions, a new partition is automatically created. The time interval is one year.
DLM policy: The table retains only three partitions. When the number of partitions exceeds three, the DLM policy is triggered to delete the cold data directly.
Create the sales table with a DLM policy.
CREATE TABLE `sales` (
`id` int DEFAULT NULL,
`name` varchar(20) DEFAULT NULL,
`order_time` datetime DEFAULT NULL,
PRIMARY KEY (`order_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
PARTITION BY RANGE COLUMNS(order_time) INTERVAL(YEAR, 1)
(PARTITION p20200101000000 VALUES LESS THAN ('2020-01-01 00:00:00') ENGINE = InnoDB,
PARTITION p20210101000000 VALUES LESS THAN ('2021-01-01 00:00:00') ENGINE = InnoDB,
PARTITION p20220101000000 VALUES LESS THAN ('2022-01-01 00:00:00') ENGINE = InnoDB)
DLM ADD POLICY test_policy TIER TO NONE ON (PARTITIONS OVER 3);
The DLM policy for the table is named test_policy, and it runs when the number of partitions exceeds three. When this policy runs, it directly deletes the cold data.
Run the following command to view the mysql.dlm_policies table:
SELECT * FROM mysql.dlm_policies\G
The following result is returned:
*************************** 1. row ***************************
Id: 4
Table_schema: test
Table_name: sales
Policy_name: test_policy
Policy_type: NONE
Archive_type: PARTITION COUNT
Storage_mode: NULL
Storage_engine: NULL
Storage_media: NULL
Storage_schema_name: NULL
Storage_table_name: NULL
Data_compressed: OFF
Compressed_algorithm: NULL
Enabled: ENABLED
Priority_number: 50000
Tier_partition_number: 3
Tier_condition: NULL
Extra_info: null
Comment: NULL
1 row in set (0.01 sec)
Insert test data into the sales partitioned table to trigger the INTERVAL policy to automatically create new partitions. Use the proc_batch_insert stored procedure to insert the new data.
CALL proc_batch_insert(1, 3000, 'sales');
Query OK, 1 row affected, 1 warning (0.99 sec)
Run the following command to view the schema of the sales table:
SHOW CREATE TABLE sales \G
The following result is returned:
*************************** 1. row ***************************
Table: sales
Create Table: CREATE TABLE `sales` (
`id` int(11) DEFAULT NULL,
`name` varchar(20) DEFAULT NULL,
`order_time` datetime DEFAULT NULL,
PRIMARY KEY (`order_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
/*!50500 PARTITION BY RANGE COLUMNS(order_time) */ /*!99990 800020200 INTERVAL(YEAR, 1) */
/*!50500 (PARTITION p20200101000000 VALUES LESS THAN ('2020-01-01 00:00:00') ENGINE = InnoDB,
PARTITION p20210101000000 VALUES LESS THAN ('2021-01-01 00:00:00') ENGINE = InnoDB,
PARTITION p20220101000000 VALUES LESS THAN ('2022-01-01 00:00:00') ENGINE = InnoDB,
PARTITION _p20230101000000 VALUES LESS THAN ('2023-01-01 00:00:00') ENGINE = InnoDB,
PARTITION _p20240101000000 VALUES LESS THAN ('2024-01-01 00:00:00') ENGINE = InnoDB,
PARTITION _p20250101000000 VALUES LESS THAN ('2025-01-01 00:00:00') ENGINE = InnoDB,
PARTITION _p20260101000000 VALUES LESS THAN ('2026-01-01 00:00:00') ENGINE = InnoDB,
PARTITION _p20270101000000 VALUES LESS THAN ('2027-01-01 00:00:00') ENGINE = InnoDB,
PARTITION _p20280101000000 VALUES LESS THAN ('2028-01-01 00:00:00') ENGINE = InnoDB) */
1 row in set (0.03 sec)
Execute the DLM policy
Run the following command to execute the DLM policy directly:
CALL dbms_dlm.execute_all_dlm_policies();
While the DLM policy is executing, view the data in the mysql.dlm_progress table.
SELECT * FROM mysql.dlm_progress \G
The result in the table is as follows:
*************************** 1. row ***************************
Id: 1
Table_schema: test
Table_name: sales
Policy_name: test_policy
Policy_type: NONE
Archive_option: PARTITIONS OVER 3
Storage_engine: NULL
Storage_media: NULL
Data_compressed: OFF
Compressed_algorithm: NULL
Archive_partitions: p20200101000000, p20210101000000, p20220101000000, _p20230101000000, _p20240101000000, _p20250101000000
Archive_stage: ARCHIVE_COMPLETE
Archive_percentage: 100
Archived_file_info: null
Start_time: 2023-01-09 17:31:24
End_time: 2023-01-09 17:31:24
Extra_info: null
1 row in set (0.03 sec)
The partitions that store infrequently accessed cold data, including p20200101000000, p20210101000000, p20220101000000, _p20230101000000, _p20240101000000, and _p20250101000000, have been deleted.
The schema of the sales table is now as follows:
SHOW CREATE TABLE sales \G
The following result is returned:
*************************** 1. row ***************************
Table: sales
Create Table: CREATE TABLE `sales` (
`id` int(11) DEFAULT NULL,
`name` varchar(20) DEFAULT NULL,
`order_time` datetime DEFAULT NULL,
PRIMARY KEY (`order_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
/*!50500 PARTITION BY RANGE COLUMNS(order_time) */ /*!99990 800020200 INTERVAL(YEAR, 1) */
/*!50500 (PARTITION _p20260101000000 VALUES LESS THAN ('2026-01-01 00:00:00') ENGINE = InnoDB,
PARTITION _p20270101000000 VALUES LESS THAN ('2027-01-01 00:00:00') ENGINE = InnoDB,
PARTITION _p20280101000000 VALUES LESS THAN ('2028-01-01 00:00:00') ENGINE = InnoDB) */
1 row in set (0.02 sec)
Manage policies with ALTER TABLE
Create a DLM policy using ALTER TABLE.
ALTER TABLE t DLM ADD POLICY test_policy TIER TO TABLE ENGINE=CSV STORAGE=OSS READ ONLY
STORAGE TABLE_NAME = 'sales_history' ON (PARTITIONS OVER 3);
The DLM policy for table t is named test_policy. The policy is executed when the number of partitions exceeds three. When this condition is met, data from the older partitions of table t is archived to OSS into a table named sales_history.
Enable the test_policy DLM policy on table t.
ALTER TABLE t DLM ENABLE POLICY test_policy;
Disable the test_policy DLM policy on table t.
ALTER TABLE t DLM DISABLE POLICY test_policy;
Delete the test_policy DLM policy from table t.
ALTER TABLE t DLM DROP POLICY test_policy;
Troubleshoot execution errors
Incorrect configurations can cause errors when a DLM policy runs. These error records are stored in the mysql.dlm_progress table. Run the following command to view them:
SELECT * FROM mysql.dlm_progress WHERE Archive_stage = "ARCHIVE_ERROR";
Check the Extra_info field for error details to identify the cause. Then, either delete the record or change its Archive_stage to ARCHIVE_COMPLETE. Finally, rerun the policy manually with the call dbms_dlm.execute_all_dlm_policies; command, or wait for the next scheduled execution.
Note For data security, if a policy has an execution record in the ARCHIVE_ERROR state, it will not run again automatically. You must identify the cause of the failure and modify the record before the policy can run again.