TiDB 实时计算大表 DDL 实战指南:在线变更不锁表

TiDB 实时计算大表 DDL 实战指南:在线变更不锁表

在实时计算场景中,数据表持续承接高吞吐的写入与查询,表结构变更(DDL)往往成为运维的痛点。传统单机数据库执行大表 DDL 时通常需要长时间锁表或拷贝数据,严重阻塞业务。TiDB 作为分布式 NewSQL 数据库,其在线 DDL 机制允许在大量读写并发下完成表结构变更,为实时计算大表提供了可靠的变更方案。本文将系统介绍 TiDB 在大表 DDL 中的核心原理、实操指南与性能优化方法。

TiDB 在线 DDL 架构与原理

TiDB 的 DDL 操作由集群中的 DDL Owner 节点统一协调执行,其他 TiDB 节点作为 DDL Worker 参与数据重组。DDL 语句首先被提交到 TiKV 的 Schema 版本中,通过递增的 schema version 通知各节点同步最新的表结构。普通 DDL(如增加列、修改列默认值)通常只需更新元数据,毫秒级完成;而需要重组数据的 DDL(如添加索引、修改列类型)则由 DDL Owner 分批次处理数据,整个过程不阻塞读写,称为 Online Schema Change

TiDB 的在线变更借鉴了 Google F1 的算法思想,将 DDL 划分为多个阶段:先创建临时索引或临时列,再回填历史数据,最后原子切换新旧结构并清理旧数据。关键在于每个阶段都维护新旧 schema 的兼容性,保证任意时刻的读写请求都能使用至少一个有效的表结构版本。

实时计算场景下大表 DDL 的挑战

实时计算业务通常要求数据延迟在秒级甚至毫秒级,表结构变更可能带来以下问题:

  • 资源竞争:大表 DDL 的数据回填会消耗大量 CPU、IO 和网络资源,挤占实时计算任务的资源配额。
  • 写入延迟抖动:DDL 产生的额外写放大可能导致 TiKV 写入延迟升高,影响实时数据链路。
  • 长事务冲突:在线 DDL 的回填操作若与实时写入产生锁冲突,可能引发事务重试或失败。
  • 元数据同步开销:频繁的 schema version 变更会导致所有 TiDB 节点同步元数据,增加集群内通信负担。

因此,在实时计算环境执行大表 DDL 必须谨慎规划,充分利用 TiDB 的在线变更能力,同时通过参数调优和控制变更时机来降低对业务的影响。

TiDB 大表 DDL 操作实践

1. 使用在线 DDL 语句

TiDB 支持绝大多数 ALTER TABLE 操作在线执行,例如:

  • 增加列:ALTER TABLE t ADD COLUMN new_col INT
  • 添加索引:ALTER TABLE t ADD INDEX idx_name (col)
  • 修改列类型(部分支持在线):ALTER TABLE t MODIFY COLUMN col BIGINT
  • 删除列或索引(元数据变更,立即完成)

执行大表 DDL 前,建议先通过 SHOW TABLE REGIONS 确认表的 Region 数量和大小,评估数据回填规模。对于超过亿行的大表,添加索引可能需要数小时,应提前规划维护窗口。

2. 监控 DDL 进度

可通过 ADMIN SHOW DDL JOBS 查看当前 DDL 任务进度:

  • ADMIN SHOW DDL JOBS:列出最近执行的 DDL 任务,包含状态、进度百分比、耗时等信息。
  • ADMIN SHOW DDL JOB QUERIES job_id:查看具体 DDL 语句。

进度百分比表示数据回填的完成度,对于大表添加索引,进度会缓慢增长。若 DDL 任务长时间停在某一进度,需检查集群是否有 Region 热点或资源瓶颈。

3. 大表 DDL 的注意事项

  • 避免在业务高峰期执行:虽然在线 DDL 不锁表,但数据回填会消耗大量资源,建议在低峰期或专门维护窗口执行。
  • 控制并发 DDL 数量:同时执行多个大表 DDL 会加剧资源争抢,应串行执行。
  • 注意列类型变更的限制:部分类型转换(如 INT 到 VARCHAR)需要全表数据重写,耗时与表大小成正比;而增加列仅需元数据变更,秒级完成。
  • 谨慎使用 ALTER TABLE ... ADD INDEX 的并行参数:默认参数已适合多数场景,盲目增大并行度可能导致 TiKV 过载。

性能优化与参数调优

TiDB 针对 DDL 数据回填提供了几个关键参数,可在会话或全局级别调整:

  • tidb_ddl_reorg_worker_cnt:控制每个 DDL 任务用于数据回填的 worker 数量,默认 4,可适当调大以加速回填,但会占用更多 TiDB 节点资源。
  • tidb_ddl_reorg_batch_size:控制每批回填的行数,默认 256,调大可以减少提交频率但增加单事务大小,需根据 TiKV 写入能力权衡。
  • tidb_ddl_reorg_priority:设置回填操作的优先级,可设为 LOW 以降低对实时读写的影响,但会延长 DDL 耗时。

在实时计算场景中,建议将 tidb_ddl_reorg_priority 设置为 LOWPRIORITY_LOW,确保 DDL 回填不会抢占实时任务的关键资源。同时可通过 TiDB Dashboard 的 Key Visualizer 观察回填期间的热点分布,如发现某 Region 写入过热,可手动分裂 Region 分散压力。

实时计算大表 DDL 最佳实践

结合实时计算业务特点,以下实践可帮助提升大表 DDL 的安全性与效率:

  • 先加列后加索引:若业务需要同时新增列和索引,建议分两步执行,先加列(秒级完成),再在低峰期添加索引,避免单次 DDL 耗时过长。
  • 使用 pt-oscgh-ost 的思想验证:虽然 TiDB 原生支持在线 DDL,但在极端情况下(如回填期间发生网络分区)仍需做好回滚预案。建议在测试环境用相同数据量模拟变更,预估耗时与资源消耗。
  • 结合数据生命周期管理:对于按时间分区的实时数据表,可先对历史分区执行 DDL,再对新分区变更,降低一次性大表回填的风险。
  • 利用 TiDB 的 INSTANT 特性:TiDB 6.5 及以上版本对添加列、修改列默认值等操作支持 INSTANT 算法,仅修改元数据而不回填任何数据,真正实现毫秒级 DDL。

下面是一个典型的实时计算大表添加索引的操作示例:

  • 1. 评估表大小:SELECT COUNT(*) FROM realtime_table; 或使用 SHOW TABLE REGIONS 查看 Region 数量。
  • 2. 选择低峰期窗口,设置会话参数:SET tidb_ddl_reorg_priority = 'LOW';
  • 3. 执行 DDL:ALTER TABLE realtime_table ADD INDEX idx_event_time (event_time);
  • 4. 监控进度:ADMIN SHOW DDL JOBS; 观察进度百分比,若长时间停滞则排查资源。
  • 5. DDL 完成后验证索引是否生效:EXPLAIN SELECT * FROM realtime_table WHERE event_time > '2025-01-01';

通过以上步骤,即使表数据量达数十亿行,TiDB 也能在不中断实时读写的情况下完成索引添加,虽然回填可能耗时数小时,但业务始终在线。

总结

TiDB 的在线 DDL 能力为实时计算大表的结构变更提供了可靠保障。理解其架构原理、合理设置回填参数、并选择合适的变更时机,可以最大限度降低 DDL 对实时业务的影响。在实际运维中,运维人员应结合监控与测试,针对不同表规模和业务负载制定个性化的大表 DDL 操作规范,确保数据库变更既高效又安全。