写点什么

TiDB 数据库的垃圾回收机制

  • 2024-11-15
    北京
  • 本文字数:5338 字

    阅读完需:约 18 分钟

作者: Ming 原文来源:https://tidb.net/blog/828bbbb6


TiDB 作为一个分布式数据库系统,其 GC(垃圾回收)机制对于维护数据一致性和优化存储空间至关重要。本文将深入探讨 TiDB 的 GC 机制,包括其设计参数、调整方法和监控策略,以帮助用户更好地理解和优化 GC 性能。

TiDB GC 机制概述

TiDB 采用 MVCC(多版本并发控制)机制,允许旧数据版本与新数据版本共存。GC 的任务是清理不再需要的旧数据版本,以释放存储空间并维护数据一致性。

GC 流程

1. Resolve Locks(清理锁)

作用与重要性: 在 TiDB 中,事务通过悲观锁和乐观锁机制来保证数据的一致性。Resolve Locks 步骤的主要作用是清理那些不再需要的锁,特别是那些已经提交或回滚的事务所留下的锁。这些锁如果不被及时清理,可能会阻止 GC 的进行,因为 GC 需要确保不会删除任何可能被当前活跃事务访问的数据。


执行过程:


  • 确定安全点(Safepoint): TiDB 会确定一个时间点,称为 safe point,所有在该时间点之前的事务都已经完成(提交或回滚)。这个时间点之前的锁都是可以被清理的。

  • 锁清理: 对于每个事务,TiDB 会检查其状态,如果事务已经完成,那么与之相关的锁就会被清理。


模式选择:


  • LEGACY 模式: 在 LEGACY 模式下,TiDB 会为每个需要清理的锁执行一个清理操作。这种模式简单直观,但在锁数量非常多的情况下效率较低。

  • PHYSICAL 模式(实验性): PHYSICAL 模式是一种更高效的锁清理方式,它通过批量处理来减少对存储的访问次数,提高清理效率。这种模式还在实验阶段,可能在未来的版本中成为默认设置。

2. Delete Ranges(删除区间)

作用与重要性: 当用户执行了 DROP TABLE、DROP INDEX 等操作后,会产生大量的废弃数据。这些数据不再被任何事务引用,但仍然占用存储空间。Delete Ranges 步骤的目的是快速删除这些废弃区间的数据,以释放存储空间。


执行过程:


  • 识别废弃区间: TiDB 会识别出所有因为 DDL 操作而产生的废弃数据区间。

  • 物理删除: 对这些区间进行物理删除,即直接从存储中移除这些数据,而不是标记为删除。这样可以立即释放存储空间。

3. Do GC(进行 GC 清理)

作用与重要性: Do GC 步骤是 GC 的核心,它负责删除每个 key 的过期版本。在 MVCC 机制下,TiDB 会保留数据的多个版本,以支持历史数据的查询。但是,这些过期版本最终需要被清理,以避免无限增长的数据量。


执行过程:


  • 确定过期版本: TiDB 会根据 safe point 来确定哪些版本的数据是过期的,即那些在 safe point 之前写入且没有被后续事务引用的数据版本。

  • 删除过期版本: 对这些过期版本进行删除操作,只保留 safe point 之后的最后一次写入。这样既保证了数据的一致性,又避免了数据的过度积累。

GC 配置参数

1. tidb_gc_enable

  • 作用:控制是否启用 TiKV 的垃圾回收(GC)机制。

  • 类型:布尔型

  • 默认值:ON(启用)

  • 说明:如果禁用 GC,系统将不再清理旧版本的数据,这可能会影响系统性能并占用更多存储空间。

2. tidb_gc_run_interval

  • 作用:指定垃圾回收(GC)运行的时间间隔。

  • 类型:Duration

  • 默认值:10m0s(10 分钟)

  • 范围:[10m0s, 8760h0m0s](从 10 分钟到 1 年)

  • 说明:这个参数以 Go 的 Duration 字符串格式设置,如 ”1h30m” 或 ”15m” 等,用于控制 GC 的触发频率。

3. tidb_gc_life_time

  • 作用:指定每次进行垃圾回收时保留数据的时限。

  • 类型:Duration

  • 默认值:10m0s(10 分钟)

  • 范围:[10m0s, 8760h0m0s](从 10 分钟到 1 年)

  • 说明:每次进行 GC 时,将以当前时间减去该变量的值作为 safe point,所有早于这个时间点的数据版本都可能被清理。

4. tidb_gc_concurrency

  • 作用:指定 GC 在 Resolve Locks 步骤中线程的数量。

  • 类型:整数型

  • 默认值:-1(自动决定,通常为 TiKV 节点的数量)

  • 范围:[1, 128]

  • 说明:控制 GC 操作并行执行的线程数。较高的并发可以加快 GC 速度,但可能会增加系统负载。

5. tidb_gc_scan_lock_mode

  • 作用:指定垃圾回收(GC)的 Resolve Locks 步骤中扫描锁的方式。

  • 类型:字符串

  • 默认值:根据 TiDB 版本和配置可能有所不同

  • 说明:这个参数影响 GC 在处理锁时的策略,不同的模式可能影响 GC 的效率和资源消耗。

6. tidb_gc_max_wait_time

  • 作用:指定活跃事务阻碍 GC safe point 推进的最大时间。

  • 类型:整数型

  • 默认值:86400(24 小时)

  • 范围:[600, 31536000](10 分钟到 1 年)

  • 单位:秒

  • 说明:如果活跃事务运行时间未超过该值,GC safe point 会一直被阻塞不更新,直到活跃事务运行时间超过该值后 safe point 才会正常推进。

配置修改方法

TiDB 的 GC 配置可以通过系统变量直接设置,也可以通过 mysql.tidb 系统表进行配置。例如,要修改 tidb_gc_life_time 为保留最近一天以内的数据,可以使用以下 SQL 语句:


UPDATE mysql.tidb SET VARIABLE_VALUE="24h" WHERE VARIABLE_NAME="tidb_gc_life_time";
复制代码

监控 GC

TiDB 监控面板在 Grafana 中提供了多个与 GC 相关的监控指标,这些指标可以帮助用户分析 GC 的执行阶段和速度。

TiDB 监控面板

1. GC –> Worker Action OPM

这个监控项展示了 TiDB 的 GC Worker 进行的各种操作的统计,主要包括前两个阶段的操作次数统计。这些操作包括:


  • delete_range:表示在 Delete Ranges 阶段活动的次数,调用了 UnsafeDestroyRange 接口。

  • redo_delete_range:表示已经删除过的区间在 24 小时后再次删除的操作,这个指标通常不需要太关注。

  • resolve_locks:表示清锁阶段的活动次数,无论是否产生真实的清锁操作,都会有这个指标(scan_lock 是该阶段内部调用的 TiKV 接口,所以不会在这里展示)。

  • run_job:在 GC 第一阶段最开始时会产生一个尖峰,可以用这个指标确认是否完成了整轮 GC。

2. GC –> Duration

这个监控项展示了 TiDB 整轮 GC 的耗时情况。从 3.0 版本开始,只包括前两个阶段的耗时,第三阶段的耗时需要查看 TiKV-Details 面板的 TiKV Auto GC Progress。

TiKV-Details 监控面板

TiKV-Details 监控面板提供了 TiKV Auto GC Progress 的详细信息,帮助用户了解 GC 的执行进度。

1. TiKV Auto GC Progress

这个监控项显示了 TiKV 自行进行分布式 GC 的阶段的粗略进度。它通过将已扫描的 Region 数量与该 TiKV 节点上 Region 总数相除的方式计算粗略的百分比。如果 GC 运行过快(例如在一个新建的几乎为空的集群上),该指标可能显示不出来。

2. TiKV Auto GC SafePoint

这个监控项显示了每台 TiKV 当前自行 GC 时所使用的 Safepoint。该 Safepoint 由每台 TiKV 定期从 PD 获取。

监控指标的重要性

监控 GC 的性能和问题对于维护 TiDB 集群的健康至关重要。通过监控 GC 的各个阶段,管理员可以及时发现并解决 GC 延迟、性能瓶颈等问题,确保数据的及时清理和存储空间的有效利用。例如,如果发现 GC 耗时过长或者 Resolve Locks 进度停滞,可能需要检查集群中的长事务或者配置问题。

日志解读

1. 查找 GC Leader

在分析 GC 日志之前,首先需要确定当前的 GC Leader 所在的 TiDB 实例。可以通过以下 SQL 查询来查找 GC Leader 的信息:


SELECT VARIABLE_NAME, VARIABLE_VALUE FROM mysql.tidb WHERE VARIABLE_NAME IN ('tikv_gc_leader_uuid', 'tikv_gc_leader_desc');
复制代码


这条查询会返回 GC Leader 的 UUID 和描述信息,包括主机名、进程 ID 和启动时间。

2. 分析 GC 日志

一旦确定了 GC Leader 所在的 TiDB 实例,就可以登录到该实例并查看 tidb.log 文件中的 GC 相关日志信息。以下是一些关键的日志条目及其含义:

a. 整轮 GC 开始
2024-11-12 14:23:41 (UTC+08:00)TiDB 192.168.80.128:4000[gc_worker.go:328] ["[gc worker] starts the whole job"] [uuid=64befb776340009] [safePoint=453874030003355648] [concurrency=1]
复制代码


这条日志表示新一轮 GC 开始,safePoint 是此次 GC 的安全点时间戳,concurrency 是并行执行的线程数。

b. 解锁阶段开始和结束
2024-11-12 14:23:41 (UTC+08:00)TiDB 192.168.80.128:4000[gc_worker.go:1039] ["[gc worker] start resolve locks"] [uuid=64befb776340009] [safePoint=453874030003355648] [concurrency=1]2024-11-12 14:23:41 (UTC+08:00)TiDB 192.168.80.128:4000[gc_worker.go:1064] ["[gc worker] finish resolve locks"] [uuid=64befb776340009] [safePoint=453874030003355648] [regions=61]
复制代码


这两条日志分别表示解锁阶段的开始和结束,regions 字段表示处理的 Region 数量。

c. 删除区间阶段
[2020/09/28 11:09:18.187 +08:00] [INFO] [gc_worker.go:622] ["[gc worker] start delete ranges"] [uuid=5d335b8561c000c] [ranges=0][2020/09/28 11:09:18.187 +08:00] [INFO] [gc_worker.go:651] ["[gc worker] finish delete ranges"] [uuid=5d335b8561c000c] ["num of ranges"=0] ["cost time"=6.505µs]
复制代码


这两条日志表示删除区间阶段的开始和结束,ranges 字段表示处理的区间数量。

d. 重做删除区间阶段
2024-11-12 14:25:21 (UTC+08:00)TiDB 192.168.80.128:4000[gc_worker.go:702] ["[gc worker] start delete ranges"] [uuid=64befb776340009] [ranges=0]2024-11-12 14:25:21 (UTC+08:00)TiDB 192.168.80.128:4000[gc_worker.go:749] ["[gc worker] finish delete ranges"] [uuid=64befb776340009] ["num of ranges"=0] ["cost time"=251ns]
复制代码


这两条日志表示重做删除区间阶段的开始和结束。

e. 发送安全点到 PD
2024-11-12 14:25:21 (UTC+08:00)TiDB 192.168.80.128:4000[gc_worker.go:1436] ["[gc worker] sent safe point to PD"] [uuid=64befb776340009] ["safe point"=453874030003355648]
复制代码


这条日志表示 GC Worker 将安全点发送给 PD(Placement Driver)。

3. 日志监控指标

通过分析 GC 日志,可以获得以下监控指标:


  • GC 执行频率:通过日志可以监控 GC 的执行频率,判断是否按照预期的时间间隔执行。

  • GC 耗时:通过比较 GC 开始和结束的时间戳,可以计算出每次 GC 的耗时。

  • GC 阶段耗时:可以监控每个 GC 阶段(如解锁、删除区间)的耗时,以识别性能瓶颈。

  • 处理的数据量:通过 regions 和 ranges 字段,可以监控 GC 处理的数据量。

4. 常见问题排查

  • GC 卡住:如果 GC 长时间没有进展,可以检查日志中是否有错误信息或者长时间没有更新的日志条目。

  • GC 执行过快或过慢:如果 GC 执行速度异常,可以检查 GC 配置参数是否合理,如 tidb_gc_run_interval 和 tidb_gc_life_time。

  • 安全点更新问题:如果安全点长时间没有更新,可能需要检查集群中的长事务或者配置问题。

GC in Compaction Filter 机制

机制概述: TiDB 引入了 GC in Compaction Filter 机制,这是一种在 RocksDB 的 Compaction 过程中进行 GC 的新技术。这种机制避免了传统的 GC 过程中额外的磁盘读取和删除标记对顺序扫描性能的影响,从而提高了 GC 效率和系统性能。


工作原理: 在传统的 GC 过程中,TiDB 会有一个单独的 GC worker 线程来处理过期数据的清理。而 GC in Compaction Filter 机制则是在 RocksDB 的 Compaction 过程中,通过 CompactionFilter 接口来识别和删除过期的数据版本。这样,GC 的工作就被集成到了 RocksDB 的 Compaction 过程中,减少了 GC 对系统资源的额外需求。

优势

  1. 减少磁盘读取: 传统的 GC 需要额外的磁盘读取来识别过期数据,而 GC in Compaction Filter 机制避免了这一步骤,因为它是在 Compaction 过程中直接进行 GC。

  2. 提高顺序扫描性能: 减少了大量的删除标记,从而避免了这些标记对顺序扫描性能的影响。

  3. 降低 CPU 和 IO 消耗: GC 属于资源密集型操作,通过在 Compaction 过程中进行 GC,可以减少定期 GC 时处理的数据量,加快 GC 处理速度,降低 CPU 和 IO 的消耗。

配置和监控

配置: TiKV 配置文件中的[gc]部分可以设置 enable-compaction-filter 参数来控制是否启用 GC in Compaction Filter 机制:


[gc]enable-compaction-filter = true
复制代码


该参数也可以通过在线配置变更来开启。



监控:


  • GC in Compaction-filter 监控: 在 TiKV 的监控面板中,可以查看 write CF 的 Compaction filter 中已过滤版本的数量,包括 filtered(过滤掉的所有 keys 数量)和 rollback/lock(过滤的 keys 中包含的 rollback 和 lock keys 数量)。

结论

本文探讨了 TiDB 的 GC 机制,包括其工作原理、配置参数以及监控方法。GC 机制在 TiDB 中扮演着至关重要的角色,它不仅负责维护数据的一致性,还直接影响到数据库的性能和存储效率。以下是本文的核心结论:


  1. GC 机制的重要性:TiDB 的 GC 机制通过 MVCC 技术管理数据版本,确保数据的一致性和隔离性,同时清理过期数据以释放存储空间。

  2. 参数配置:合理配置 GC 参数,如 tidb_gc_enable、tidb_gc_run_interval、tidb_gc_life_time 等,对于平衡 GC 的执行频率和系统资源消耗至关重要。

  3. 监控与分析:通过 TiDB 和 TiKV 的监控面板,可以实时监控 GC 的运行状态,及时发现并解决性能瓶颈和潜在问题。

  4. 实践指导:本文提供的 GC 配置、监控,有助于构建高效、稳定的 TiDB 集群。

  5. 持续改进:随着 TiDB 的不断发展,GC 机制也在不断优化。用户应持续关注 TiDB 的新版本和最佳实践,以充分利用最新的性能优化特性。


通过本文的分析和讨论,我们希望用户能够对 TiDB 的 GC 机制有一个全面的理解,并能够应用这些知识来优化自己的 TiDB 集群。GC 是数据库性能调优的重要组成部分,正确的配置和监控可以显著提升数据库的性能和稳定性。希望本文能作为用户在 TiDB GC 领域探索和实践的起点。


发布于: 刚刚阅读数: 4
用户头像

TiDB 社区官网:https://tidb.net/ 2021-12-15 加入

TiDB 社区干货传送门是由 TiDB 社区中布道师组委会自发组织的 TiDB 社区优质内容对外宣布的栏目,旨在加深 TiDBer 之间的交流和学习。一起构建有爱、互助、共创共建的 TiDB 社区 https://tidb.net/

评论

发布
暂无评论
TiDB数据库的垃圾回收机制_监控_TiDB 社区干货传送门_InfoQ写作社区