
TiDB TTL 表设计与实现全解行级到期数据自动清理的语法、调度架构与源码剖析【免费下载链接】tidbTiDB is built for agentic workloads that grow unpredictably, with ACID guarantees and native support for transactions, analytics, and vector search. No data silos. No noisy neighbors. No infrastructure ceiling.项目地址: https://gitcode.com/GitHub_Trending/ti/tidbTTLTime To Live表是 TiDB 提供的一种数据自动过期清理能力为表指定一个时间列与保留时长后后台任务会周期性扫描并删除已过期的行广泛适用于验证码、会话、日志、事件流水等只需短期保留数据的场景。本文以 TTL 表设计提案 为骨架结合当前仓库中pkg/ttl的实现源码完整讲解 TTL 表的 DDL 语法、表级配置、后台作业调度Job/Task架构、扫描与删除执行细节、系统变量与监控指标并给出可复现的 SQL 示例与源码级证据帮助读者既能会用也能理解如何实现。一、TTL 表要解决什么问题在传统数据库中清理过期数据通常依赖业务方定期执行DELETE或由 DBA 编写定时脚本按时间字段分批删除。这类做法有两个痛点删除语句容易与在线业务互相影响且多久删一次、删哪些行完全游离于表结构之外无法被数据库统一管理与运维。TTL 表把过期清理变成一种表级声明式属性。一个 TTL 表包含一个类型为DATE/DATETIME/TIMESTAMP的时间列该列与当前时间比较当二者间隔超过设定的阈值如 3 个月时对应行会被自动删除。如设计文档引言所述其典型场景就是清理过期的验证码这类数据——写入后只需要存活有限时间之后由数据库自动回收业务代码无需再关心删除逻辑。二、总体设计选型为什么采用 SQL 层方案设计文档明确了 TiDB TTL 的核心理念是SQL-layer approach后台任务通过 SQL 协议扫描并删除过期行。相比把 TTL 下沉到存储层这一方案的优势被明确列出实现简单天然感知表结构与 SQL 语义与 TiCDC、BR备份恢复、二级索引等生态工具兼容良好删除行为本身就是普通的 SQL DML可被这些组件识别与同步。设计文档同时分析了其他备选方案的短板候选方案主要问题复用 TiKV RawKV 上的 TTL不具备 SQL 感知无法用任意列含生成列做 TTL 列无法支撑未来外键TTL 是 KV 级别的不能按表开关与 CDC、备份、二级索引不兼容将 TTL 配置下推给 TiKV 执行存在未解决的隔离性问题如可能破坏快照隔离约束CockroachDB 行级 TTL理念相似但 CockroachDB 用隐藏列存储到期时间戳而非直接比较创建时间列因此ALTERTTL 选项时会引发存量数据改写性能受表大小影响TiDB 选择直接用创建时间列 INTERVAL 表达式的方式ALTER表级 TTL 配置只改元数据、不触碰数据行这是它在实现层面的一个优势。三、TTL 表 DDL 语法完整指南设计文档给出的语法分为建表、改表、移除三类下面结合仓库实现逐一说明。3.1 创建 TTL 表最基本的 TTL 表把created_at声明为 TTL 时间列数据在写入 3 个月后过期CREATE TABLE t1 ( id int PRIMARY KEY, created_at TIMESTAMP ) TTL created_at INTERVAL 3 MONTH;其中TTL time_column INTERVAL n unit即到期时间 时间列值 保留时长。保留时长由数值与时间单位组成时间单位在语法层面支持到ast.TimeUnitType如MONTH、DAY、HOUR等可参考源码中对IntervalTimeUnit的建模pkg/meta/model/table.go 中的TTLInfo结构体将IntervalExprStr与IntervalTimeUnit分开存储。3.2 用 TTL_ENABLE 开关后台任务默认建表后 TTL 作业即为开启状态若只想声明 TTL 语义而暂不执行删除可显式关闭CREATE TABLE t1 ( id int PRIMARY KEY, created_at TIMESTAMP ) TTL created_at INTERVAL 3 MONTH TTL_ENABLE OFF;TTL_ENABLE缺省时为ON。在 DDL 解析与落库阶段getTTLInfoInOptions见 pkg/ddl/ttl.go会把TableOptionTTL、TableOptionTTLEnable、TableOptionTTLJobInterval三类选项聚合成model.TTLInfoEnable默认置true若同时出现TTL_ENABLE则以显式值为准pkg/ddl/create_table.go、pkg/ddl/executor.go 中对ast.TableOptionTTL等选项的分支处理可印证。3.3 兼容 MySQL 的注释式语法为使语法形态与 MySQL 生态兼容TTL 选项同样支持放在特殊注释块中CREATE TABLE t1 ( id int PRIMARY KEY, created_at TIMESTAMP ) /*T![ttl] TTL created_at INTERVAL 3 MONTH TTL_ENABLE OFF*/;MySQL 及不支持 TTL 的下游工具会将其整体视为普通注释而忽略TiDB 则解析其中的 TTL 配置。3.4 ALTER 为已有表添加或更新 TTL对一张已存在非 TTL表可直接通过ALTER TABLE追加 TTL 属性ALTER TABLE t1 TTL created_at INTERVAL 3 MONTH;更新已有 TTL 配置时ALTER会以最小覆盖原则合并只修改本次给出的选项其余选项沿用旧值。这一行为在 DDL 执行逻辑onTTLInfoChange中有明确实现——当只改TTL_ENABLE或只改TTL_JOB_INTERVAL而对应表尚未有 TTL 配置时会报ErrSetTTLOptionForNonTTLTable参见 pkg/ddl/ttl.go更新完成后该表正在运行的后台作业会按最新配置停止或重启。文档示例中TTL_JOB_INTERVAL用于自定义作业调度周期例如把表t1的清理作业周期调整为 1 天ALTER TABLE t1 TTL_JOB_INTERVAL1d;调度周期既支持设计文档里的ALTER表级设置也支持在CREATE TABLE时一并声明。注意默认值的版本演进设计文档写作时默认周期为 1 小时而当前仓库中表级默认值已演进为24h见 pkg/meta/model/table.go 中DefaultTTLJobInterval 24h同时保留了OldDefaultTTLJobInterval 1h作为 8.5 及之前版本的兼容值——当老版本建的表JobInterval字段为空时GetJobInterval()会回退返回1h保证从 v6.5 一路升级过来的集群行为一致。3.5 移除 TTLREMOVE TTL与 MySQL 的ALTER TABLE ... REMOVE PARTITIONING思路类似去掉表的 TTL 属性只需ALTER TABLE t1 REMOVE TTL;对应 DDL 内部流程为onTTLInfoRemovepkg/ddl/ttl.go置空tblInfo.TTLInfo并落库作业随后被终止。3.6 生成列作为 TTL 时间列设计文档指出TTL 表支持把生成列Generated Column作为时间列例如把 JSON/VARCHAR 中的时间字段转换为DATETIME后再作为 TTL 列。但文档明确提示当前存在性能退化生成列的表达式条件无法下推到 TiKV过滤工作只能在 TiDB 侧完成扫描阶段网络与 CPU 开销更高多数日期函数同样不支持下推。要从根本上解决需要生成列表达式支持下推 TiKV与常用日期函数支持下推 TiKV两项能力详见本文已知问题一节。3.7 使用约束与合法性校验TTL 表并非可以随意声明仓库 pkg/ddl/ttl.go 的checkTTLInfoValid汇总了全部校验规则可归纳为外键约束被其他表通过外键引用的表不能加 TTL父表被引用时删除父表行可能违反子表外键约束对应报错ErrUnsupportedTTLReferencedByFK。设计文档给出的描述与该实现一致。时间列类型TTL 时间列必须是时间类型DATE/DATETIME/TIMESTAMP否则报ErrUnsupportedColumnInTTLConfig。列存在性TTL 配置指向的列必须真实存在否则报ErrBadField。临时表临时表不允许设置 TTLErrTempTableNotAllowedWithTTL。聚簇主键类型若表使用聚簇主键且主键含FLOAT/DOUBLE列不允许创建 TTLErrUnsupportedPrimaryKeyTypeWithTTL。原因是删除过期行走的是 SQLDELETE ... WHERE PK IN (...)浮点主键在比较时存在精度损失风险。间隔表达式合法性创建/修改时会用cache.EvalExpireTime预计算校验INTERVAL表达式可被正确求值。列保护TTL 时间列不能被DROP COLUMN删除ErrTTLColumnCannotDrop。四、表级 TTL 配置在元数据中的存储形态TTL 属性最终落在每张表的元数据TableInfo.TTLInfo上其结构定义在 pkg/meta/model/table.go字段含义ColumnNameTTL 时间列名IntervalExprStr间隔表达式的文本如INTERVAL 3 MONTH中3 MONTH部分经过 RESTORE 后的字符串IntervalTimeUnit间隔时间单位内部为ast.TimeUnitType以int存储避免循环依赖Enable该表 TTL 作业是否启用对应TTL_ENABLEJobInterval两次 TTL 作业之间的间隔字符串形式如24hJobInterval的解析统一走(*TTLInfo).GetJobInterval()其中注入了 failpointoverwrite-ttl-job-interval以便测试覆盖。这也说明多久跑一次作业在最终实现中是每表各自可配置的设计文档中提及的全局tidb_ttl_job_run_interval变量在落地演进中被表级TTL_JOB_INTERVAL 全局作业开关等变量取代使用时请以当前版本的 系统变量清单 为准。五、后台作业调度与任务管理架构5.1 作业模型概述设计文档给出的作业模型是为每个 TTL 表在需要时调度一个作业Job作业与物理表一一对应尽量把不同表的作业分散到不同 TiDB 节点执行降低对单个节点的影响一个分区表会被视为多个物理表每个分区对应一条状态记录因而同一时刻可能有多个作业在不同 TiDB 节点上并行运行。在 pkg/ttl/ttlworker/config.go 中可以看到调度器的若干关键周期常量例如作业管理器主循环 10s、任务管理器循环 1 分钟、任务心跳 1 分钟、任务领取轮询 5 秒、作业超时上限 6 小时等这些常量均可通过 failpoint 注入改写以便集成测试从侧面印证调度循环的周期性特征。5.2 状态记录表 mysql.tidb_ttl_table_status每个 TTL 物理表的状态记录在系统表mysql.tidb_ttl_table_status中。设计文档给出的建表结构完整继承了表中全部字段CREATE TABLE tidb_ttl_table_status ( table_id bigint(64) PRIMARY KEY, parent_table_id bigint(64), table_statistics TEXT DEFAULT NULL, last_job_id varchar(64) DEFAULT NULL, last_job_start_time timestamp NULL DEFAULT NULL, last_job_finish_time timestamp NULL DEFAULT NULL, last_job_ttl_expire timestamp NULL DEFAULT NULL, last_job_summary text DEFAULT NULL, current_job_id varchar(64) DEFAULT NULL, current_job_owner_id varchar(64) DEFAULT NULL, current_job_owner_addr varchar(256) DEFAULT NULL, current_job_owner_hb_time timestamp, current_job_start_time timestamp NULL DEFAULT NULL, current_job_ttl_expire timestamp NULL DEFAULT NULL, current_job_state text DEFAULT NULL, current_job_status varchar(64) DEFAULT NULL, current_job_status_update_time timestamp NULL DEFAULT NULL );该表在集群 bootstrap 阶段随其他系统表一同创建见 pkg/session/bootstrap.gotidb_ttl_table_status与后文tidb_ttl_task均在其中注册。字段语义按设计文档可归纳为table_idTTL 表物理表ID分区表场景下是每个分区的物理 ID。parent_table_id若当前行为某个分区则为其父表 ID否则等于table_id。table_statistics表的统计信息。last_job_*前缀最近一次成功执行作业的信息包括作业 ID、开始/完成时间、本次作业使用的过期时间last_job_ttl_expire以及作业摘要last_job_summary。current_job_*前缀当前尚未结束作业的信息除 ID、开始时间、过期时间外还包括current_job_owner_id/current_job_owner_addr/current_job_owner_hb_time作业宿主某个 TiDB 节点的 ID、地址与心跳时间。宿主周期性刷新心跳若心跳长期不更新说明原宿主已下线作业会被其他节点接管fail over。current_job_state作业内部状态用于失败后的状态恢复。current_job_status作业生命周期状态。current_job_status_update_time状态最近更新时间。设计文档给出的current_job_status枚举为waiting / running / cancelling / cancelled / error在 pkg/ttl/cache/ttlstatus.go 的实现中该枚举进一步演进为waiting / running / cancelling / cancelled / timeout / finished六态实际使用时以上述源码定义为准。current_job_id不只代表正在运行的作业失败或用户取消但尚未清理的作业同样保留其中方便排查。5.3 取消运行中的作业需要终止某个作业时执行管理命令ADMIN CANCEL TTL JOB 123456789作业状态会先变为cancelling随后最终更新为cancelled。5.4 分布式任务表 mysql.tidb_ttl_task为了让集群资源得到最大化利用设计文档提出把单个作业拆成多个扫描任务并分发到所有 TiDB 节点执行每个新作业创建时向系统表mysql.tidb_ttl_task写入若干行每行代表一个扫描任务每个 TiDB 节点周期性扫描该表发现新任务后把任务 owner 置为自己并执行。在 pkg/ttl/ttlworker/task_manager.go 中可以看到对应的 SQL 模板族UPDATE mysql.tidb_ttl_task设置任务 owner、标记任务完成、刷新心跳、放弃 ownerresign以及SELECT count(1) ... WHERE status running统计运行中任务数完整佐证了认领—执行—心跳—收尾的分布式任务生命周期。任务行还记录了扫描范围scan_range_start/scan_range_end、过期时间与创建时间见 pkg/ttl/cache/task.go。集成测试 pkg/ttl/ttlworker/task_manager_integration_test.go 中模拟多 TiDB 节点task-manager-1/task-manager-2竞争领取任务并验证running → finished状态迁移是理解该机制最直接的样例。六、作业执行细节扫描与删除一个运行中的 TTL 作业包含两类任务扫描任务Scan Tasks负责从表中过滤出过期行删除任务Delete Tasks负责批量删除。全部过期行删完后作业结束。单个 TiDB 节点上运行多个 worker 并发消费这些任务。6.1 扫描任务按主键范围分批翻页作业开始时先把表按主键切分成 NN ≥ 1个范围每个范围交给一个扫描任务执行范围扫描。设计文档给出的伪代码如下func doScanTask(tbl, range, expire, ch) { var lastRow for { selectSQL : buildSelect(tbl, range lastRow, expire, LIMIT) rows : execute(selectSQL) ch - deleteTask{tbl, expire, rows} if len(rows) LIMIT { break } lastRow : rows[len(rows)-1] } }首次查询形如SELECT LOW_PRIORITY id FROM t1 WHERE create_time 2022-01-01 00:00:00 AND id 12345 AND id 45678 ORDER BY id ASC LIMIT 500;其中2022-01-01 00:00:00是作业启动时刻计算出的过期时间[12345, 45678)是当前扫描任务负责的键范围LIMIT 500为单次最多返回行数可用系统变量tidb_ttl_scan_batch_size调整。由于一次查询通常取不完所有过期行当返回行数达到上限时就把上次读到的最后一行主键如23456作为下一次查询的起点继续翻页SELECT LOW_PRIORITY id FROM t1 WHERE create_time 2022-01-01 00:00:00 AND id 23456 AND id 45678 ORDER BY id ASC LIMIT 500;直到某次返回行数不足LIMIT即代表该范围读尽。需要注意的关键点扫描很重它本质上是全表范围扫描因此对大表而言建议把作业周期如TTL_JOB_INTERVAL/ 作业调度窗口调大摊薄单日资源开销。无主键/非聚簇主键表使用隐藏列_tidb_rowid作为行号参与范围切分与翻页。生成列时间列条件无法下推时过滤在 TiDB 侧完成需要更多网络流量与 CPU。在实现层面pkg/ttl/ttlworker/scan.go 的doScanWithSession除了逐页翻页读取当前vardef.TTLScanBatchSize作为limit还做了两类加固比设计文档更进一步安全过期时间校验任务执行前会把作业计算出的过期时间与按当前最新配置重新计算的安全过期时间对比。因为作业提交后、任务真正执行前用户可能已把保留时长从 2 天改成 1 天若仍按旧的过期时间删除就可能误删本不该删的行因此校验不通过时任务会直接报错中止对应代码注释中的完整时序说明。失败重试单条扫描 SQL 执行失败时按scanTaskExecuteSQLMaxRetry 5次、间隔 2 秒的重试策略处理pkg/ttl/ttlworker/config.go 与 pkg/ttl/ttlworker/scan.go。6.2 删除任务分批多行 DELETE删除 worker 从 channel 中消费扫描阶段投递的任务再把行拆成若干批次。设计文档伪代码如下func doDelTask(ch) { for _, task : range ch { batches : splitRowsToDeleteBatches(task.rows) for _, batch : range batches { deleteBatch(task.tbl, task.batch, task.expire) } } }批次大小由系统变量tidb_ttl_delete_batch_size控制每个批次用一条多行DELETE完成DELETE LOW_PRIORITY FROM t WHERE id in (1, 2, 3, ...) AND create_time 2022-01-01 00:00:00;这里刻意保留create_time ...条件是为了避免误删某行在扫描时已过期但在真正执行删除前可能被业务更新为未过期值此时id IN (...)即使命中也会因时间条件不满足而被跳过。关于性能设计文档指出若 TTL 表没有二级索引传入删除的行大多落在同一 Region删除操作多数情况下可以用1PC一阶段提交提交事务开销显著降低。因此对大表而言不建二级索引往往反而能获得更好的 TTL 清理性能。6.3 SQL 构造器的实现佐证扫描与删除 SQL 并非手工字符串拼接而是由 pkg/ttl/sqlbuilder/sql.go 的SQLBuilder状态机式生成。可以看到查询以SELECT LOW_PRIORITY SQL_NO_CACHE开头删除以DELETE LOW_PRIORITY FROM开头——LOW_PRIORITY用于降低 TTL 后台任务对在线查询的影响与设计文档示例一致建表 SQL 支持分区表构造时会追加PARTITION(name)限定到具体分区构造器内部强制要求写入time_col expire的过期条件WriteCommonCondition否则在生成最终 SQL 时报expire condition not write错误——从代码层面保证任何删除都携带过期条件杜绝无差别删除。七、时区考量TTL 时间列支持三种字段类型Date、DateTime与TimeStamp。其中Date/DateTime不是绝对时间点必须结合时区才能确定精确的到期时刻设计文档列出了两种时区选择方案及其隐患使用系统时区全局变量system_time_zone集群 bootstrap 时确定且之后不变行会在固定的绝对时刻被删除不会因用户改时区而漂移但如果集群把会话/全局time_zone设置为与SYSTEM不同例如system_time_zone为08:00而time_zone为UTC在作业周期小于 8 小时时记录会被立即视为过期而误删。使用集群时区变量time_zone在time_zone不变化时表现良好但一旦用户修改time_zoneTTL 作业必须及时感知新时区否则某行是否过期在不知道历史时区的情况下无法判定可能删除非预期行。这一节说明TTL 表在使用DATE/DATETIME作为时间列时部署时应保证集群时区设置长期稳定并清楚其相对时间的语义TIMESTAMP存储的是绝对时间点不存在此类歧义。八、系统变量全览设计文档规划了 8 个全局系统变量。对照仓库中的变量注册表 pkg/sessionctx/vardef/tidb_vars.go 与 pkg/sessionctx/variable/sysvar.go实际落地的变量清单与参数如下个别默认值在实现中已与设计稿不同已按仓库当前定义修正系统变量作用作用域取值范围默认值tidb_ttl_job_enable全局总开关OFF时停止调度新作业并取消正在运行的作业GlobalON/OFFONtidb_ttl_job_schedule_window_start_timeTTL 作业调度时间窗口的开始时刻Global时间值00:00 0000tidb_ttl_job_schedule_window_end_timeTTL 作业调度时间窗口的结束时刻Global时间值23:59 0000tidb_ttl_scan_worker_count每个 TiDB 节点的扫描 worker 数Global[1, 256]4tidb_ttl_scan_batch_size扫描任务中每条 SELECT 的 LIMIT 值Global[1, 10240]500tidb_ttl_delete_worker_count每个 TiDB 节点的删除 worker 数Global[1, 256]4tidb_ttl_delete_batch_size每条 DELETE 的批次大小Global[1, 10240]100tidb_ttl_delete_rate_limit每个 TiDB 节点的删除速率上限0 表示不限速Global[0, MaxInt64]0tidb_ttl_running_tasks集群中允许同时运行的任务数上限支持自动值Global自动值或 [1, 最大并发]-1由 TiDB 自动决定早期设计稿为 0以上变量的当前默认值可以从vardef包中的DefTiDBTTL*常量直接核对如DefTiDBTTLScanBatchSize 500、DefTiDBTTLDeleteBatchSize 100、DefTiDBTTLScanWorkerCount 4等。其中tidb_ttl_running_tasks在设计稿中的含义是最大并行任务数-1表示由 TiDB 自动决定变量类型注册为TypeInt、AllowAutoValue: true说明允许赋自动值以让系统按集群规模动态确定。使用方式示例SET global.tidb_ttl_job_enable ON; SET global.tidb_ttl_scan_worker_count 8; SET global.tidb_ttl_delete_batch_size 200; SET global.tidb_ttl_job_schedule_window_start_time 01:00 0000; SET global.tidb_ttl_job_schedule_window_end_time 05:00 0000;九、可观测性TTL 监控指标设计文档规划了 6 组 Prometheus 指标用于观察 TTL 作业健康度与开销相关定义可在 pkg/ttl/metrics/metrics.go 及全局 metrics 定义中找到对应实现指标类型Labels含义ttl_queriesCountersql_type,resultTTL 作业执行的查询总数ttl_processed_expired_rowsCountersql_typeTTL 作业处理的过期行总数ttl_query_durationHistogramsql_type,resultTTL 查询耗时分布ttl_job_statusGauge实现中按作业状态打标当前 TTL 作业所处状态处于该状态时为 1否则为 0ttl_phase_timeCountertype,phase各 worker 在不同执行阶段如 idle、begin/commit txn、query、wait retry、dispatch、check TTL、wait token 等见 pkg/ttl/metrics/metrics.go 中的 Phase 常量的耗时ttl_insert_rowsCounter—写入 TTL 表的总行数设计文档对ttl_queries等指标的sql_type取值为select/deleteresult取值为ok/error。在实现中扫描、删除成功与失败的行数分别通过不同 Counter 记录如ScannedExpiredRows、DeleteSuccessExpiredRows、DeleteErrorExpiredRows运行中/取消中的作业数量由RunningJobsCnt、CancellingJobsCnt等 Gauge 体现。这些指标配合 Grafana 即可监控TTL 是否在按窗口执行、单位时间清理了多少行、后台任务对集群压力有多大。十、已知问题与性能影响设计文档明确列出的已知问题是生成列条件无法下推到 TiKV。若表使用生成列作为 TTL 时间列过滤会在 TiDB 侧完成带来额外网络流量并使查询变慢。该限制在文档写作时存在也属于未来工作中性能优化部分的头号议题下推生成列表达式、或直接用生成列定义构造过滤条件。因此当前使用 TTL 时若对清理性能敏感应优先选择真实时间列而非生成列。另外如前文所述无二级索引的表由于删除通常可走 1PC、且无索引写入热点往往表现更好。十一、未来演进方向11.1 性能优化设计文档规划的优化方向包括若 TTL 表存在 TiFlash 副本扫描改走 TiFlash 以卸载 TiKV 压力若存在以 TTL 时间列为前缀的索引用索引定点查询过期行替代全表范围扫描缩短扫描耗时对无二级索引的表利用统计信息缓存例如作业结束后缓存每个 Region 最旧行的创建时间下次作业开始时跳过无更新且未过期的 Region对无二级索引的表把扫描与删除下推到 TiKV 侧执行避免 TiDB 与 TiKV 之间的数据搬运——类似 GCWorker引入新的 Coprocessor 命令TTLGC由 TiKV 以非事务方式直接清理过期行结合全局资源控制框架设计时仍在进行中最大化集群资源利用率。11.2 更多功能支持支持 TTL 表作为被ON DELETE CASCADE子表引用的父表实现级联清理支持将生成列条件下推 TiKV或用生成列定义直接构造过滤条件根据集群当前负载动态调整运行期参数为云环境增加内置 ALTER 支持。十二、测试方案与仓库验证设计文档给出了功能与性能两方面的测试计划功能测试Functional TestDDL 操作创建带 TTL 的表、对非 TTL 表执行 ALTER 增加 TTL、对 TTL 表 ALTER 更新 TTL 选项、移除表的 TTL 选项TTL 表能调度后台作业并删除过期行TTL_ENABLE或全局global.tidb_ttl_job_enable为OFF时表不调度作业作业只在配置的时间窗口内被调度。性能测试Performance Test构造 1000 万行表、其中 10% 为过期行测试清空过期数据所需时间同时运行基准测试与 TTL 作业采集基准的 QPS/延迟并与未运行 TTL 时对比评估对在线负载的影响。这些计划在当前仓库中均有对应的工程化验证DDL 侧有 pkg/ddl/ttl_test.go校验默认间隔、TTL_ENABLE选项的解析与持久化、pkg/ddl/db_table_test.go作业与任务侧有 pkg/ttl/ttlworker/job_manager_test.go、pkg/ttl/ttlworker/scan_test.go、pkg/ttl/ttlworker/del_test.go以及多节点场景的 pkg/ttl/ttlworker/integrationtest 集成测试目录TTL 表状态读写与字段抽取逻辑见 pkg/ttl/cache/ttlstatus_test.go。读者若想深入理解某个机制直接阅读对应测试是最高效的入口。结语TiDB TTL 表把过期数据自动清理做成了表级声明式能力通过TTL 时间列 INTERVAL语法定义保留策略由 TiDB 后台以 SQL 层作业Job 拆分为 Scan/Delete 任务在集群内分布执行。相比手工脚本它具备统一元数据管理、天然兼容 TiCDC/BR/二级索引、作业状态可观测、可全局开关与限速等工程化优势相比存储层 TTL 方案则避免了 KV 级语义带来的隔离性、表感知与外键兼容问题。理解其语法、调度状态机、任务分发与各项系统变量是在生产环境中正确、高效使用 TTL 的关键前提。【免费下载链接】tidbTiDB is built for agentic workloads that grow unpredictably, with ACID guarantees and native support for transactions, analytics, and vector search. No data silos. No noisy neighbors. No infrastructure ceiling.项目地址: https://gitcode.com/GitHub_Trending/ti/tidb创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考