The data lifecycle management (DLM) feature helps you reduce storage costs and improve efficiency. It automatically and periodically archives infrequently accessed cold data from PolarStore to a low-cost storage medium, such as Object Storage Service (OSS).
Prerequisites
Your cluster must run PolarDB for MySQL 8.0.2, revision 8.0.2.2.34.1 or later.
Note To check your cluster version, see Query the engine version.
If your cluster runs PolarDB for MySQL 8.0.2, revision 8.0.2.2.11.1 or later, the DLM feature does not record operations in the binary log.
You must enable cold data archiving before you can use DLM policies. For more information, see Enable cold data archiving.
Note If you do not enable the cold data archiving feature, the following error is returned:
ERROR 8158 (HY000): [Data Lifecycle Management] DLM storage engine is not support. The value of polar_dlm_storage_mode is OFF.
Limitations
The DLM feature supports only partitioned tables that do not contain subpartitions. The partitioning method must be RANGE COLUMN.
You cannot use the DLM feature on a partitioned table that has a global secondary index (GSI).
PolarDB for MySQL does not support modifying a DLM policy. To modify a policy, you must first delete the existing policy and then create a new one.
If a DLM policy exists on a table, do not perform DDL operations that cause schema inconsistencies between the source table and the archive table, such as adding or deleting columns or modifying column data types. Such inconsistencies can prevent subsequently archived data from being parsed. Before you perform these DDL operations, you must delete the DLM policy from the table. To resume automatic data archiving, create a new DLM policy and specify a new name for the archive table. The new name cannot be the same as any previously used archive table name.
Use INTERVAL RANGE partitioning to automatically extend partitions and 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, revision 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 archive table in OSS is read-only, and query performance may be slow. You must test in advance to ensure that the query performance meets your requirements.
After a partition from a partitioned table is archived to OSS, the data in that partition becomes read-only. You cannot perform DDL operations on the partitioned table.
Backup operations do not include data that has been archived to OSS. Data in OSS does not support point-in-time recovery.
Create a 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 table name. |
policy_name | Yes | The policy name. |
TIER TO TABLE | Yes | Archives data to a new OSS foreign table. |
TIER TO PARTITION | Yes | Converts hot data partitions into cold data partitions stored in OSS within the same table, creating a hybrid partitioned table.
Note This feature is in canary release. To use this feature, go to Quota Center, find the quota name that corresponds to the polardb_mysql_hybrid_partition quota ID, 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, revision 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 the data from the oldest partitions instead of archiving it. |
engine_name | No | The storage engine for the archived data. Currently, data can be archived only to the CSV engine. |
storage_schema_name | No | The database for the archive table. This defaults to the source table's database. |
storage_table_name | No | The name of the archive table. If unspecified, it defaults to <source_table_name>_<dlm_policy_name>. |
STORAGE [=] OSS | No | Stores the archived data in OSS. This is the default. |
READ ONLY | No | Makes the archived data read-only. This is the default. |
comment_string | No | The comment for the DLM policy. |
extra_info | No | Specifies the OSS_FILE_FILTER information for the destination OSS table.
Note Archiving partitions to OSS requires your cluster to run the Enterprise Edition of PolarDB for MySQL 8.0.2, revision 8.0.2.2.25 or later. This feature takes effect only if the destination table does not exist. In this case, the system automatically generates the FILE_FILTER attribute based on the OSS_FILE_FILTER parameter in EXTRA_INFO when the destination OSS table is created. If the destination table already exists, the existing file filter is used.
The format of EXTRA_INFO is {"oss_file_filter":"field_filter[,field_filter]"}, where field_filter is defined as follows: field_filter := field_name[:filter_type]
filter_type := bloom
|
ON (PARTITIONS OVER num) | Yes | Archives data when the number of partitions is greater than num. |
Manage a 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 these statements, table_name is the name of the table, and dlm_policy_name is the name of the policy to manage. You can specify multiple policy names.
Execute a 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 single table.
CALL dbms_dlm.execute_table_dlm_policies('database_name', 'table_name');
In this statement, database_name is the name of the database that contains the table, and table_name is the name of the table.
You can use the MySQL event feature to execute DLM policies during your cluster's maintenance window. This method prevents database performance from being affected during peak business hours and allows you to periodically move expired data to reduce storage costs. Use the following syntax to execute a DLM policy with an event:
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 to run the event. |
comment | No | The comment for the event. |
event_body | Yes | The content that the event executes. This must be a statement that executes a DLM policy.
Note If you use CALL dbms_dlm.execute_all_dlm_policies(), the event executes all DLM policies on the cluster. Therefore, you must create only one such event per cluster. If you use CALL dbms_dlm.execute_table_dlm_policies('database_name', 'table_name');, the event executes all DLM policies only on a specific table. Therefore, create an event for each table that requires scheduled archiving.
|
interval | Yes | The execution frequency 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 CREATE EVENT.
For usage examples, see Examples of archiving cold data to OSS.
Examples
Archive data to a foreign table
Create a DLM policy
The following example creates a partitioned table named sales that uses the order_time column as the partition key. The table has an INTERVAL policy and a DLM policy:
INTERVAL policy: When inserted data falls outside the existing partition range, a new partition is automatically created with a time interval of one year.
DLM policy: The table is defined to retain 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, a new OSS foreign table named sales_history is created, and the cold data is archived to the sales_history table.
If the sales_history external table exists, and the sales_history table is on the built-in OSS, the cold data is directly archived to the sales_history external table.
Note To create a table with INTERVAL RANGE partitioning, make sure that all prerequisites are met. For more information about 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 the table is named test_policy. When the number of partitions exceeds three, the policy archives the cold data from the source table in CSV format to OSS. The resulting archive table is named sales_history and is read-only. If the OSS archive table does not exist, the system automatically creates it and adds an OSS_FILE_FILTER to the id and name columns.
The DLM policies for the current table are stored in the system table mysql.dlm_policies. You can query this table to view the details of the DLM policies. For more information about the mysql.dlm_policies table, see Table structure description. View the structure of the mysql.dlm_policies table.
mysql> SELECT * FROM mysql.dlm_policies\G
Sample output:
*************************** 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. This ensures that the data exceeds the defined partition range and 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 is triggered, which adds new partitions to the sales table. The table structure is now as follows:
mysql> SHOW CREATE TABLE sales\G
Sample output:
*************************** 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 new partitions increase the total partition count to more than three. This meets the condition for the DLM policy, and the data is now ready for archiving.
Execute the DLM policy
You can execute the DLM policy directly by using an SQL statement, or you can run it periodically by using the MySQL EVENT feature. For example, assume your maintenance window starts at 01:00 every day, beginning on October 11, 2022. You can create the following event to run 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 sales table structure:
mysql> SHOW CREATE TABLE sales\G
Sample output:
*************************** 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 has only three partitions.
You can query the mysql.dlm_progress table to view the execution history of the DLM policy. For more information about the dlm_progress table, see Table structures. Run the following command to query the mysql.dlm_progress table:
mysql> SELECT * FROM mysql.dlm_progress\G
Sample output:
*************************** 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 structure of the OSS foreign table:
mysql> SHOW CREATE TABLE sales_history\G
Sample output:
*************************** 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 that uses the OSS engine for storage. You can query it in the same way as a local table. The specified columns have been added 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 on the sales and sales_history tables separately.
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 number of rows that were initially inserted into the sales table.
Query the OSS foreign table by using the OSS_FILE_FILTER. The OSS_FILE_FILTER switch must be enabled.
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 that uses the order_time column as the partition key. The table has an INTERVAL policy and a DLM policy:
INTERVAL policy: When inserted data falls outside the existing partition range, a new partition is automatically created with a time interval of one year.
DLM policy: The table is defined to retain only three partitions. When the number of partitions exceeds three, the DLM policy is triggered and archives the older partitions directly 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 the table is named policy_part2part. When the number of partitions exceeds three, the older partitions are archived to OSS.
View the DLM policy in the mysql.dlm_policies table.
SELECT * FROM mysql.dlm_policies\G
Sample output:
*************************** 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. This action triggers the INTERVAL policy, which automatically creates new partitions.
CALL proc_batch_insert(1, 3000, 'sales');
The following result indicates that the data is inserted successfully:
Query OK, 1 row affected, 1 warning (0.99 sec)
Run the following command to view the sales table structure:
SHOW CREATE TABLE sales \G
Sample output:
*************************** 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();
Query the mysql.dlm_progress table to view the DLM execution history.
SELECT * FROM mysql.dlm_progress \G
Sample output:
*************************** 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 sales table structure:
SHOW CREATE TABLE sales \G
Sample output:
*************************** 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 output shows that the partitions p20200101000000, p20210101000000, p20220101000000, _p20230101000000, _p20240101000000, and _p20250101000000 of the sales partitioned table are archived to OSS. Only the three hot data partitions, _p20260101000000, _p20270101000000, and _p20280101000000, are retained in the InnoDB engine. The sales table is now a hybrid partitioned table. For information about how to query data in a hybrid partitioned table, see Query a hybrid partitioned table.
Delete cold data
Create a DLM policy
The following example creates a partitioned table named sales that uses the order_time column as the partition key. The table has an INTERVAL policy and a DLM policy:
INTERVAL policy: When inserted data falls outside the existing partition range, a new partition is automatically created with a time interval of one year.
DLM policy: The table is defined to retain only three partitions. When the number of partitions exceeds three, the DLM policy is triggered to delete the cold data.
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. It is triggered when the number of partitions exceeds three. When executed, the policy deletes the cold data.
Run the following command to query the mysql.dlm_policies table:
SELECT * FROM mysql.dlm_policies\G
Sample output:
*************************** 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)
Use the proc_batch_insert stored procedure to insert test data into the sales partitioned table. This action triggers the INTERVAL policy, which automatically creates new partitions.
CALL proc_batch_insert(1, 3000, 'sales');
Query OK, 1 row affected, 1 warning (0.99 sec)
Run the following command to view the sales table structure:
SHOW CREATE TABLE sales \G
Sample output:
*************************** 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 running, query the data in the mysql.dlm_progress table.
SELECT * FROM mysql.dlm_progress \G
The results in the table are 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 sales table structure is now as follows:
SHOW CREATE TABLE sales \G
Sample output:
*************************** 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 by using the ALTER TABLE statement.
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. It is triggered when the number of partitions exceeds three. When executed, this policy archives data from the oldest partitions of table t to an OSS 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
DLM policies may fail to execute due to configuration issues. Error records are stored in the mysql.dlm_progress table. Run the following command to view error records:
SELECT * FROM mysql.dlm_progress WHERE Archive_stage = "ARCHIVE_ERROR";
Find the error details in the Extra_info field. After you identify and resolve the cause of the error, either delete the record or update its Archive_stage to ARCHIVE_COMPLETE. You can then run the call dbms_dlm.execute_all_dlm_policies; command to manually execute the policy, or wait for the next scheduled execution.
Note For data security, if a policy execution record has the ARCHIVE_ERROR state, the scheduler will not run the policy again automatically. After you confirm the cause of the failure and update the record, the policy resumes its scheduled execution.