TTL归档在TTL自动清理过期数据的基础上,将过期数据写入独立的归档表并可迁移到OSS冷存储,实现热冷数据分层存储。
功能概述
普通TTL的行为是:后台清理线程扫描到过期行后直接删除,数据不可恢复。
TTL归档在此基础上增加一步,过期行在源表被删除的同一个事务里,先被插入到对应的归档表,随后随着时间推移,较老的整个分区会被后台自动迁移到OSS。由此得到“热数据在源表、冷数据在归档表/OSS”的分层存储结构。
需要重点理解的几个语义:
适用范围
集群版本:需为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 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;
相关说明
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__,与源表相比有以下差异,使用时需注意:
分区粒度
loose_innodb_ttl_archived_interval_type控制归档表按多大的时间窗口分区(与数据过期时长无关):
取值 | 分区窗口 |
| 按天 |
| 按周 |
| 按月(30天) |
| 按年(365天) |
分区窗口越大,分区数量越少、迁移到OSS的批次越大。越小则分区越多、冷数据下沉越及时。建议按数据量与查询模式选择,一般保持默认DAY即可。
参数说明
归档专用参数
参数 | 级别 | 类型 | 默认 | 说明 |
| 全局 | BOOL | OFF | 归档总开关。 |
| 全局 | ENUM | DAY | 归档分区粒度( |
查询冷分区可见性由会话变量prune_archived_oss_partitions控制(详见查询归档数据)。该变量属于底层“OSS分区归档”能力,非TTL归档专用,此处不再单列。
归档依赖的通用参数
参数 | 默认 | 说明 |
| — | 必须 |
| OFF | TTL清理总开关,归档由清理线程驱动 |
| 4 | TTL清理线程数 |
| 100 | TTL过期时长允许的最小值(秒) |
| 0 / 0 | 清理允许运行的时间窗 |
| OFF | 允许TTL列为DATETIME类型 |
| 90 |
|
使用限制
带归档属性的表在建表或改表校验中,遇到以下情况会报错ER_TTL_INFO_CHECK_ERR (9913)(消息模板TTL info check err:%s):
触发场景 | 报错提示 | 处理建议 |
未开启归档总开关 |
| 先设置 |
未开启OSS |
| 先设置 |
没有显式主键 |
| 为表定义显式PRIMARY KEY后再开启归档 |
归档表名超过64字符 |
| 缩短源表名,保证源表名 + |
含虚拟列索引或多值索引 |
| 去掉虚拟列索引或多值索引 |
含FULLTEXT索引 |
| 去掉FULLTEXT索引 |
含SPATIAL索引 |
| 去掉SPATIAL索引 |
含空间列(GEOMETRY/POINT等) |
| 移除空间列 |
TTL列名含 |
| 重命名TTL列,去掉 |
TTL列不存在或类型不符 |
| 确认TTL列存在且类型为TIMESTAMP或DATETIME |
过期时长小于最小值 |
| 增大过期时长,需大于 |
以上均为建表或改表时内核会强制拦截的场景。其中“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等)。归档动作(迁移成功或失败、丢弃、重复主键跳过)会输出到实例错误日志,可结合日志排查归档行为。