The Data Lifecycle Management (DLM) feature allows you to automatically and regularly archive cold data from PolarStore to cost-effective OSS storage in CSV or ORC format, 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.
-
Hybrid partitioned tables support Copy DDL and INPLACE DDL for creating or deleting secondary indexes, but do not support Instant DDL.
-
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 an OSS external table.
Note
Only CSV format is supported for archiving to OSS foreign tables.
|
|
TIER TO PARTITION
|
Yes
|
Archives partitions in CSV, ORC, or X-Engine format, that is, creates a hybrid partitioned table.
Note
-
To archive partitions of a partitioned table as a hybrid partitioned table, the following conditions must be met:
-
MySQL 8.0.2 and the minor version is 8.0.2.2.34.1 or later. You must set the loose_allow_create_hybrid_partition parameter to ON.
-
MySQL 8.0.2 and the minor version is earlier than 8.0.2.2.34.1. Upgrade to a later minor version.
-
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. Valid values: CSV, ORC, and X-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
Archive in CSV format
-
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.
Archive in ORC format
-
Create a DLM policy
The following example creates a sales_orc partitioned table that uses the order_time column as the partition key and partitions data by time interval. The table has both INTERVAL and DLM policies:
-
INTERVAL policy: When inserted data exceeds the partition range, a new partition is automatically created with a 1-year interval.
-
DLM policy: When the table has more than 3 partitions, the DLM policy archives old partitions in ORC format to OSS. The table becomes a hybrid partitioned table.
Create the sales_orc table with a DLM policy that uses TIER TO PARTITION ENGINE=ORC to archive old partitions to OSS.
CREATE TABLE `sales_orc` (
`id` int DEFAULT NULL,
`name` varchar(20) DEFAULT NULL,
`order_time` datetime NOT NULL,
PRIMARY KEY (`order_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
-- Create RANGE COLUMN partitions on order_time with a 1-year INTERVAL (automatic partition creation)
PARTITION BY RANGE COLUMNS(order_time) INTERVAL(YEAR, 1)
-- Pre-create 3 initial partitions that hold data before 2020 / 2021 / 2022
(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 policy: when the partition count exceeds 3, archive old partitions in ORC format to OSS
-- TIER TO PARTITION: partition-level archiving. The table becomes a hybrid partitioned table
-- (hot InnoDB partitions coexist with cold ORC partitions)
DLM ADD POLICY policy_orc TIER TO PARTITION ENGINE=ORC STORAGE=OSS READ ONLY
ON (PARTITIONS OVER 3);
The DLM policy is named policy_orc. When the number of partitions exceeds 3, old partitions are archived in ORC format to OSS. The table becomes a hybrid partitioned table that contains both hot InnoDB partitions and cold ORC partitions.
-
Run the DLM policy
Insert test data into the sales_orc partitioned table to trigger INTERVAL to automatically create new partitions so that the number of partitions exceeds 3 and the DLM policy condition is met.
CALL proc_batch_insert(1, 3000, 'sales_orc');
Run the DLM policy:
CALL dbms_dlm.execute_all_dlm_policies();
-
View the archiving result
Run the following command to view DLM policy execution records in the mysql.dlm_progress table:
SELECT * FROM mysql.dlm_progress\G
Partitions that store infrequently accessed cold data have been archived to OSS. Run the following command to view the schema of the sales_orc table:
SHOW CREATE TABLE sales_orc\G
The result is as follows:
*************************** 1. row ***************************
Table: sales_orc
CREATE TABLE `sales_orc` (
`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 /*!99990 800020223 OSS META=1 */ 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 = ORC,
PARTITION p20210101000000 VALUES LESS THAN ('2021-01-01 00:00:00') ENGINE = ORC,
PARTITION p20220101000000 VALUES LESS THAN ('2022-01-01 00:00:00') ENGINE = ORC,
PARTITION _p20230101000000 VALUES LESS THAN ('2023-01-01 00:00:00') ENGINE = ORC,
PARTITION _p20240101000000 VALUES LESS THAN ('2024-01-01 00:00:00') ENGINE = ORC,
PARTITION _p20250101000000 VALUES LESS THAN ('2025-01-01 00:00:00') ENGINE = ORC,
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)
As shown in the query result, the p20210101000000, p20220101000000, _p20230101000000, _p20240101000000, and _p20250101000000 partitions of the sales_orc partitioned table have been archived to OSS. Only the three hot data partitions _p20260101000000, _p20270101000000, and _p20280101000000 remain in the InnoDB engine. The sales_orc 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.