全部产品
Search
文档中心

云原生数据库 PolarDB:TTL归档说明

更新时间:Sep 20, 2026

TTL归档在TTL自动清理过期数据的基础上,将过期数据写入独立的归档表并可迁移到OSS冷存储,实现热冷数据分层存储。

功能概述

普通TTL的行为是:后台清理线程扫描到过期行后直接删除,数据不可恢复。

TTL归档在此基础上增加一步,过期行在源表被删除的同一个事务里,先被插入到对应的归档表,随后随着时间推移,较老的整个分区会被后台自动迁移到OSS。由此得到“热数据在源表、冷数据在归档表/OSS”的分层存储结构。

需要重点理解的几个语义:

  • 源表与归档表是两张物理独立的表:

    • 不存在自动UNION或查询改写,SELECT * FROM 源表只读源表,读不到已归档数据。

    • 要查归档数据必须显式查询归档表。

  • 归档表的命名固定为<源表名>__ttl_archived__。

  • 已迁移到OSS的冷分区,默认对普通查询不可见,需要WITH ARCHIVED修饰符才会纳入扫描,详见查询归档数据。

  • 归档写入与源表删除是同一个事务,保证原子性:要么源表删除与归档写入都成功,要么一起回滚,不会出现“源表删了但归档没写”的中间状态(回填历史数据的例外情况,详见注意事项)。

适用范围

  • 集群版本:需为MySQL 8.0.2,且内核小版本需为8.0.2.2.37及以上。

  • 参数配置:启用TTL归档需要同时满足以下条件,任一不满足时,带归档属性的建表或改表会被拒绝。您可以在控制台的参数配置中开启以下参数。

    条件

    参数

    说明

    打开归档总开关

    loose_innodb_ttl_archived_enable = ON

    关闭时拒绝带归档属性的DDL,且清理线程不会归档过期行

    打开OSS能力

    loose_polar_oss_enable = ON

    归档表冷分区需迁移到OSS,建表时强制校验

    打开TTL清理

    loose_innodb_enable_ttl_purge = ON

    归档动作由TTL清理线程驱动

语法说明

创建带归档属性的TTL表

在标准TTL语法末尾追加ARCHIVED标记即可,支持两种等价写法。

语法说明

  • 写法一:紧凑串形式 TTL='列名@间隔秒数@ARCHIVED'

    CREATE TABLE `t1` (
      `a` INT PRIMARY KEY,
      `b` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
      KEY idx_b (`b`)
    ) ENGINE=InnoDB TTL='b@5@ARCHIVED';
  • 写法二:INTERVAL形式 TTL='列名' + INTERVAL n unit AND ARCHIVED

    CREATE TABLE `t1` (
      `a` INT PRIMARY KEY,
      `b` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
      KEY idx_b (`b`)
    ) ENGINE=InnoDB TTL='b' + INTERVAL 3 HOUR AND ARCHIVED;

相关说明

  • ARCHIVED标记大小写不敏感,但只接受完整单词archived;@archiv、@ARCHIV等写法会报错。

  • INTERVAL支持的时间单位与普通TTL一致:YEAR / QUARTER / MONTH / WEEK / DAY / HOUR / MINUTE / SECOND。

  • 这里的INTERVAL表示数据的过期时长,与归档表的分区粒度是两个独立概念。

为已有表增删归档属性

-- 给已有TTL表加上归档(两种写法等价)
ALTER TABLE `t2` TTL='b@5@archived';
ALTER TABLE `t2` TTL='b' + INTERVAL 5 SECOND AND ARCHIVED;

-- 去掉归档属性,保留普通TTL
ALTER TABLE `t2` TTL='b@5';

-- 完全清除TTL(含归档)
ALTER TABLE `t2` TTL='';
说明

去掉归档属性或清除TTL时,不会立即删除已有的归档表,而是由后台清理线程延迟回收。这样可避免ALTER过程中数据被提前销毁,也不会长时间持锁阻塞其他DDL。若需保留历史归档数据,请在删除前自行备份或改名。

查看表的归档属性

SHOW CREATE TABLE `t1` FULL;

FULL形式才会完整回显TTL与归档信息。

查询归档数据

归档表是普通的可见表,可直接查询。要读取已迁移到OSS的冷分区,需加WITH ARCHIVED:

-- 只读仍在本地的归档分区
SELECT a, b FROM t1__ttl_archived__ ORDER BY a;

-- 连同已迁移到OSS的冷分区一起读
SELECT a, b FROM t1__ttl_archived__ WITH ARCHIVED ORDER BY a;

语义要点:

  • WITH ARCHIVED是表引用级修饰符,仅作用于其直接标注的那张表,不能写成SELECT * FROM 源表 WITH ARCHIVED来透明读取归档数据。

  • 会话变量prune_archived_oss_partitions(默认ON)控制是否裁剪OSS冷分区。设为OFF时,普通SELECT(不带WITH ARCHIVED)也会看到冷分区。

说明

WITH ARCHIVED语法与prune_archived_oss_partitions变量并非TTL归档新增,而是底层“OSS分区归档”能力提供的通用机制。TTL归档表作为分区表复用了这套可见性控制。

归档表结构

归档表由源表结构自动派生,命名为<源表名>__ttl_archived__,与源表相比有以下差异,使用时需注意:

  1. 主键为“源表主键 + TTL列”的复合主键。若TTL列本就在源表主键中,则不重复追加。TTL列因进入主键而隐含NOT NULL。

  2. 源表上的UNIQUE索引在归档表中降级为普通(非唯一)索引。这是因为归档表允许重复主键静默跳过(详见注意事项),保留UNIQUE约束会与该行为冲突。

  3. 归档表按TTL时间列做RANGE分区,分区名形如ARCHIVED_PARTITION_<上界>。分区窗口大小由分区粒度参数决定。

分区粒度

loose_innodb_ttl_archived_interval_type控制归档表按多大的时间窗口分区(与数据过期时长无关):

取值

分区窗口

DAY(默认)

按天

WEEK

按周

MONTH

按月(30天)

YEAR

按年(365天)

分区窗口越大,分区数量越少、迁移到OSS的批次越大。越小则分区越多、冷数据下沉越及时。建议按数据量与查询模式选择,一般保持默认DAY即可。

参数说明

归档专用参数

参数

级别

类型

默认

说明

loose_innodb_ttl_archived_enable

全局

BOOL

OFF

归档总开关。OFF时拒绝带归档属性的DDL,且不归档过期行

loose_innodb_ttl_archived_interval_type

全局

ENUM

DAY

归档分区粒度(DAY / WEEK / MONTH / YEAR)

说明

查询冷分区可见性由会话变量prune_archived_oss_partitions控制(详见查询归档数据)。该变量属于底层“OSS分区归档”能力,非TTL归档专用,此处不再单列。

归档依赖的通用参数

参数

默认

说明

loose_polar_oss_enable

—

必须ON,归档冷分区落OSS的前提

loose_innodb_enable_ttl_purge

OFF

TTL清理总开关,归档由清理线程驱动

loose_innodb_ttl_purge_thread

4

TTL清理线程数

loose_innodb_ttl_min_interval

100

TTL过期时长允许的最小值(秒)

loose_innodb_ttl_purge_start_hour / loose_innodb_ttl_purge_end_hour

0 / 0

清理允许运行的时间窗

loose_innodb_ttl_can_use_datetime

OFF

允许TTL列为DATETIME类型

loose_innodb_ttl_finished_job_expired_days

90

mysql.ttl_job_history记录保留天数

使用限制

带归档属性的表在建表或改表校验中,遇到以下情况会报错ER_TTL_INFO_CHECK_ERR (9913)(消息模板TTL info check err:%s):

触发场景

报错提示

处理建议

未开启归档总开关

TTL ARCHIVE requires innodb_ttl_archived_enable to be ON.

先设置loose_innodb_ttl_archived_enable=ON

未开启OSS

TTL ARCHIVE requires polar_oss_enable to be ON.

先设置loose_polar_oss_enable=ON

没有显式主键

TTL ARCHIVE requires an explicit PRIMARY KEY.

为表定义显式PRIMARY KEY后再开启归档

归档表名超过64字符

TTL ARCHIVE table name is too long, ...

缩短源表名,保证源表名 + __ttl_archived__ ≤ 64字符

含虚拟列索引或多值索引

TTL ARCHIVE is not supported on tables with indexes on virtual columns or multi-valued indexes.

去掉虚拟列索引或多值索引

含FULLTEXT索引

TTL is not supported on tables with FULLTEXT indexes.

去掉FULLTEXT索引

含SPATIAL索引

TTL is not supported on tables with SPATIAL indexes.

去掉SPATIAL索引

含空间列(GEOMETRY/POINT等)

TTL is not supported on tables with spatial columns.

移除空间列

TTL列名含@

TTL column name must not contain '@'.

重命名TTL列,去掉@字符

TTL列不存在或类型不符

TTL column err; column[...] must exist and it's type should be TIMESTAMP or DATETIME(...)

确认TTL列存在且类型为TIMESTAMP或DATETIME

过期时长小于最小值

'ttl_interval' should be integer and bigger than innodb_ttl_min_interval.

增大过期时长,需大于innodb_ttl_min_interval(默认100秒)

以上均为建表或改表时内核会强制拦截的场景。其中“TTL列必须为TIMESTAMP或DATETIME类型”对普通TTL同样适用(DATETIME需loose_innodb_ttl_can_use_datetime=ON)。

注意事项

  • 回填历史数据可能丢失:若向已开启归档的表回填一批很老的时间戳数据,其对应的归档分区可能早已迁移到OSS。此时这些行在源表被过期删除后,归档写入会被静默丢弃(源表删除仍照常发生),造成数据丢失。请避免向已归档表回填时间早于当前OSS冷分区边界的数据。确需回填时,先评估目标分区是否已下沉OSS。

  • 重复主键静默跳过:归档表以首个写入的版本为准,遇到重复主键(复合主键完全相同)时会静默跳过,不报错。

  • TTL列为NULL的行永不过期,因此也不会被归档。

  • 归档表可写但受可见性门控:归档分区本身仍可写入,WITH ARCHIVED只影响SELECT的可见性,不影响UPDATE/DELETE的作用范围。

  • 恢复场景:使用库表或备份恢复时,建议先将loose_innodb_enable_ttl_purge设为OFF,避免恢复出的数据因已过期被立即清理或归档。

  • 不写Binlog:与普通TTL一致,归档相关的删除或写入不记录Binlog,主备之间依赖各自的清理线程分别执行,请勿依赖Binlog复制归档结果。

观测

mysql.ttl_job_history表记录每次TTL清理任务(job_id / table_name / state / start_time / finished_time / expire_time / scan_cost / purge_cost / purge_rows等)。归档动作(迁移成功或失败、丢弃、重复主键跳过)会输出到实例错误日志,可结合日志排查归档行为。