TTL archiving extends the TTL feature by writing expired data to a separate archive table and migrating it to OSS cold storage, enabling tiered storage of hot and cold data.
Overview
Standard TTL works as follows: the background purge thread scans for expired rows and deletes them directly. The deleted data cannot be recovered.
TTL archiving adds an extra step. Within the same transaction that deletes expired rows from the source table, the rows are first inserted into the corresponding archive table. Over time, older partitions are automatically migrated to OSS in the background. This creates a tiered storage structure where hot data resides in the source table and cold data resides in the archive table or OSS.
Key semantics to understand:
-
The source table and the archive table are two physically independent tables:
-
There is no automatic UNION or query rewriting.
SELECT * FROM source_tablereads only the source table and does not return archived data. -
To query archived data, you must explicitly query the archive table.
-
-
The archive table is always named
<source_table_name>__ttl_archived__. -
Cold partitions that have been migrated to OSS are invisible to regular queries by default. The
WITH ARCHIVEDmodifier is required to include them in scans. For details, see Query archived data. -
Archive writes and source table deletions occur within the same transaction, ensuring atomicity: either both the source table deletion and the archive write succeed, or both are rolled back. There is no intermediate state where "the source row was deleted but the archive write failed" (with the exception of backfilling historical data; for details, see Usage notes).
Scope of application
-
Cluster version: The cluster must run MySQL 8.0.2 with a minor engine version of 8.0.2.2.37 or later.
-
Parameter configuration: To enable TTL archiving, all of the following conditions must be met. If any condition is not met, CREATE TABLE or ALTER TABLE statements with the archiving attribute are rejected. You can enable the following parameters on the Parameters page in the console.
Condition
Parameter
Description
Enable the archiving master switch
loose_innodb_ttl_archived_enable = ONWhen OFF, DDL statements with the archiving attribute are rejected, and the purge thread does not archive expired rows
Enable OSS capability
loose_polar_oss_enable = ONCold partitions of the archive table must be migrated to OSS. This is enforced during table creation
Enable TTL purge
loose_innodb_enable_ttl_purge = ONArchiving is driven by the TTL purge thread
Syntax
Create a TTL table with the archiving attribute
Append the ARCHIVED flag to the standard TTL syntax. Two equivalent formats are supported.
Syntax
-
Format 1: Compact string
TTL='column@interval_seconds@ARCHIVED'CREATE TABLE `t1` ( `a` INT PRIMARY KEY, `b` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, KEY idx_b (`b`) ) ENGINE=InnoDB TTL='b@5@ARCHIVED'; -
Format 2: INTERVAL syntax
TTL='column' + INTERVAL n unit AND ARCHIVEDCREATE TABLE `t1` ( `a` INT PRIMARY KEY, `b` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, KEY idx_b (`b`) ) ENGINE=InnoDB TTL='b' + INTERVAL 3 HOUR AND ARCHIVED;
Notes
-
The
ARCHIVEDflag is case-insensitive, but only the complete wordarchivedis accepted. Abbreviated forms such as@archivor@ARCHIVcause an error. -
The time units supported by
INTERVALare the same as those for standard TTL:YEAR / QUARTER / MONTH / WEEK / DAY / HOUR / MINUTE / SECOND. -
The
INTERVALhere specifies the expiration duration of data, which is a separate concept from the Partition granularity of the archive table.
Add or remove the archiving attribute for an existing table
-- Add archiving to an existing TTL table (two equivalent formats)
ALTER TABLE `t2` TTL='b@5@archived';
ALTER TABLE `t2` TTL='b' + INTERVAL 5 SECOND AND ARCHIVED;
-- Remove the archiving attribute, keep standard TTL
ALTER TABLE `t2` TTL='b@5';
-- Remove TTL entirely (including archiving)
ALTER TABLE `t2` TTL='';
When you remove the archiving attribute or clear TTL, the existing archive table is not deleted immediately. Instead, it is reclaimed by the background purge thread at a later time. This prevents data from being destroyed prematurely during the ALTER operation and avoids holding locks that block other DDL statements for an extended period. To retain historical archived data, back up or rename the archive table before removing the attribute.
View the archiving attribute of a table
SHOW CREATE TABLE `t1` FULL;
The FULL option is required to display complete TTL and archiving information.
Query archived data
The archive table is a regular visible table and can be queried directly. To read cold partitions that have been migrated to OSS, add WITH ARCHIVED:
-- Read only archived partitions that are still local
SELECT a, b FROM t1__ttl_archived__ ORDER BY a;
-- Read including cold partitions that have been migrated to OSS
SELECT a, b FROM t1__ttl_archived__ WITH ARCHIVED ORDER BY a;
Key semantics:
-
WITH ARCHIVEDis a table-reference-level modifier that applies only to the table it directly annotates. You cannot writeSELECT * FROM source_table WITH ARCHIVEDto transparently read archived data. -
The session variable
prune_archived_oss_partitions(default: ON) controls whether OSS cold partitions are pruned. When set to OFF, a regularSELECT(withoutWITH ARCHIVED) also returns cold partitions.
The WITH ARCHIVED syntax and the prune_archived_oss_partitions variable are not introduced by TTL archiving. They are general mechanisms provided by the underlying OSS partition archiving capability. TTL archive tables, as partitioned tables, reuse this visibility control.
Archive table structure
The archive table is automatically derived from the source table structure and is named <source_table_name>__ttl_archived__. It differs from the source table in the following ways:
-
The primary key is a composite key of "source table primary key + TTL column". If the TTL column is already part of the source table primary key, it is not appended again. The TTL column becomes implicitly
NOT NULLbecause it is part of the primary key. -
UNIQUE indexes on the source table are downgraded to regular (non-unique) indexes in the archive table. This is because the archive table silently skips duplicate primary keys (for details, see Usage notes), and retaining the UNIQUE constraint would conflict with this behavior.
-
The archive table is RANGE-partitioned by the TTL time column. Partition names follow the format
ARCHIVED_PARTITION_<upper_bound>. The partition window size is determined by the Partition granularity parameter.
Partition granularity
loose_innodb_ttl_archived_interval_type controls the time window size for partitioning the archive table (independent of the data expiration duration):
|
Value |
Partition window |
|
|
Daily |
|
|
Weekly |
|
|
Monthly (30 days) |
|
|
Yearly (365 days) |
A larger partition window results in fewer partitions and larger batches migrated to OSS. A smaller window creates more partitions and migrates cold data more promptly. Choose based on your data volume and query patterns. In most cases, the default DAY is sufficient.
Parameters
Archiving-specific parameters
|
Parameter |
Scope |
Type |
Default |
Description |
|
|
Global |
BOOL |
OFF |
Archiving master switch. When |
|
|
Global |
ENUM |
DAY |
Archive partition granularity ( |
Cold partition visibility is controlled by the session variable prune_archived_oss_partitions (for details, see Query archived data). This variable belongs to the underlying OSS partition archiving capability and is not specific to TTL archiving, so it is not listed separately here.
General parameters required by archiving
|
Parameter |
Default |
Description |
|
|
-- |
Must be |
|
|
OFF |
TTL purge master switch. Archiving is driven by the purge thread |
|
|
4 |
Number of TTL purge threads |
|
|
100 |
Minimum allowed TTL expiration duration (seconds) |
|
|
0 / 0 |
Time window during which purge is allowed to run |
|
|
OFF |
Allow the TTL column to be of the DATETIME type |
|
|
90 |
Retention period (days) for |
Limits
When creating or altering a table with the archiving attribute, the following conditions trigger the error ER_TTL_INFO_CHECK_ERR (9913) (message template: TTL info check err:%s):
|
Scenario |
Error message |
Resolution |
|
Archiving master switch is not enabled |
|
Set |
|
OSS is not enabled |
|
Set |
|
No explicit primary key |
|
Define an explicit PRIMARY KEY for the table before enabling archiving |
|
Archive table name exceeds 64 characters |
|
Shorten the source table name so that source table name + |
|
Contains virtual column indexes or multi-valued indexes |
|
Remove virtual column indexes or multi-valued indexes |
|
Contains FULLTEXT indexes |
|
Remove FULLTEXT indexes |
|
Contains SPATIAL indexes |
|
Remove SPATIAL indexes |
|
Contains spatial columns (GEOMETRY, POINT, etc.) |
|
Remove spatial columns |
|
TTL column name contains |
|
Rename the TTL column to remove the |
|
TTL column does not exist or type mismatch |
|
Verify that the TTL column exists and is of the TIMESTAMP or DATETIME type |
|
Expiration duration is less than the minimum |
|
Increase the expiration duration. It must be greater than |
All of the above are scenarios where the kernel forcibly rejects the operation during table creation or alteration. The requirement that "the TTL column must be of the TIMESTAMP or DATETIME type" also applies to standard TTL (DATETIME requires loose_innodb_ttl_can_use_datetime=ON).
Usage notes
-
Backfilled historical data may be lost: If you backfill a batch of data with very old timestamps into a table that already has archiving enabled, the corresponding archive partitions may have already been migrated to OSS. In this case, after these rows expire and are deleted from the source table, the archive writes are silently discarded (the source table deletion still occurs as usual), resulting in data loss. Avoid backfilling data with timestamps earlier than the current OSS cold partition boundary into an archived table. If backfilling is necessary, first evaluate whether the target partition has already been migrated to OSS.
-
Duplicate primary keys are silently skipped: The archive table keeps the first written version. When a duplicate primary key (identical composite primary key) is encountered, it is silently skipped without an error.
-
Rows with NULL TTL column values never expire and therefore are never archived.
-
The archive table is writable but subject to visibility controls: Archive partitions can still be written to.
WITH ARCHIVEDonly affectsSELECTvisibility and does not affect the scope of UPDATE or DELETE operations. -
Recovery scenarios: When performing database or backup recovery, we recommend that you set
loose_innodb_enable_ttl_purgeto OFF first to prevent recovered data from being immediately purged or archived due to expiration. -
No Binlog writing: Consistent with standard TTL, archiving-related deletions or writes are not recorded in the Binlog. The primary and replica nodes each rely on their own purge threads for execution. Do not rely on Binlog replication for archiving results.
Observability
The mysql.ttl_job_history table records each TTL purge task (job_id / table_name / state / start_time / finished_time / expire_time / scan_cost / purge_cost / purge_rows, etc.). Archiving events (migration success or failure, discards, duplicate primary key skips) are written to the instance error log. Use the log to troubleshoot archiving behavior.