在OceanBase数据库的运维过程中,snapshot_gc_ts 是一个关键但又不直接暴露给用户的核心参数。它控制着快照垃圾回收(Snapshot Garbage Collection)的边界,直接影响到存储空间利用率和查询性能。理解它是什么、如何监控其状态,对于保障数据库稳定运行至关重要。
一、snapshot_gc_ts 的核心作用
snapshot_gc_ts 是一个时间戳,其核心作用是界定存储层可以安全清理的历史多版本数据的边界。
简单来说,它告诉OceanBase存储层(OBS):所有早于此时间戳的数据历史版本,如果没有被其他活跃事务引用,都可以被清理掉。
定义与核心用途
这个参数主要用于通知存储层在进行数据合并(compaction)时,判断哪些历史版本的数据可以被回收。这是 多版本并发控制(MVCC) 机制中垃圾回收的关键一环。如果 snapshot_gc_ts 长时间停滞不向前推进,会导致大量过期数据版本堆积在磁盘上,进而引发一系列问题:
- 磁盘空间压力增大:历史数据无法及时清理。
- 查询性能下降:读取数据时需要扫描更多的历史版本。
- 频繁的转储(minor freeze):因为MemTable中积累了过多版本。
存储位置与正常行为
snapshot_gc_ts 的值存储在OceanBase的内部系统表 __all_core_table 中,具体是 table_name = '__all_global_stat' 这条记录里的一个字段。
在健康运行的集群(cluster_type = PRIMARY)中,这个时间戳应该随着系统的运行而持续向前推进。通常,它与当前时间的差值不会太大(例如,小于1小时)。系统自身有监控机制:
- 若超过半小时未推进,会打印WARN日志。
- 若超过1小时未推进,则会打印ERROR日志,此时需要DBA重点关注。
需要注意的特殊场景
在备库(Standby)环境中,如果副本尚未完成数据同步,snapshot_gc_ts 暂停推进是正常现象,不需要视为故障报警。我们主要需要关注主集群中的状态。
二、如何查询与监控 snapshot_gc_ts
目前OceanBase没有像 GV$OB_PARAMETERS 这样的标准视图直接暴露 snapshot_gc_ts 的值。我们可以通过以下两种间接方式来探查它的状态。
方法一:通过分析日志获取(推荐)
最安全、最常用的方法是通过查询 observer.log 日志文件。日志中会记录该时间戳的更新信息。
你可以在服务器上使用 grep 命令搜索相关关键字:
cat observer.log|grep snapshot_gc
执行后,你会看到类似下面的日志输出,其中就包含了 snapshot_gc_ts_ 的具体数值:
[2025-12-23 11:04:02.827740] INFO [STORAGE] try_update_reserved_snapshot (ob_tenant_freeze_info_mgr.cpp:1048) [2946][T1034_FreInfoRe][T1034][Y0-0000000000000000-0-0] [lt=102] success to update min reserved snapshot(reserved_snapshot=1766457232094536000, duration=1800, snapshot_gc_ts_=1766459032094536000)
从日志中提取出时间戳数值(例如 1766459032094536000)后,可以使用OceanBase内置函数 scn_to_timestamp 将其转换为人类可读的时间:
obclient(root@sys)[oceanbase]> select scn_to_timestamp(1766459032094536000);
+---------------------------------------+
| scn_to_timestamp(1766459032094536000) |
+---------------------------------------+
| 2025-12-23 11:03:57.310202 |
+---------------------------------------+
1 row in set (0.002 sec)
通过对比这个时间与当前时间,就可以判断 snapshot_gc_ts 的推进是否延迟。
方法二:直接查询系统表(需谨慎)
snapshot_gc_ts 最终存储在内部表 __all_core_table 中。请注意:直接查询内部系统表存在风险,仅建议在OceanBase技术支持人员的指导下进行,严禁在生产环境随意操作。
如果确实需要查询,可以按照以下步骤:
- 首先查看表结构。
- 查询存储全局统计信息的记录。
obclient(root@sys)[oceanbase]> desc __all_core_table;
+--------------+----------------+------+------+----------------------+--------------------------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+----------------+------+------+----------------------+--------------------------------+
| gmt_create | timestamp(6) | YES | | CURRENT_TIMESTAMP(6) | |
| gmt_modified | timestamp(6) | YES | | CURRENT_TIMESTAMP(6) | ON UPDATE CURRENT_TIMESTAMP(6) |
| table_name | varchar(128) | NO | PRI | NULL | |
| row_id | bigint(20) | NO | PRI | NULL | |
| column_name | varchar(128) | NO | PRI | NULL | |
| column_value | varchar(65536) | YES | | NULL | |
+--------------+----------------+------+------+----------------------+--------------------------------+
6 rows in set (0.023 sec)
obclient(root@sys)[oceanbase]> SELECT * FROM __all_core_table WHERE table_name = '__all_global_stat';
+----------------------------+----------------------------+-------------------+--------+-------------------------+---------------------+
| gmt_create | gmt_modified | table_name | row_id | column_name | column_value |
+----------------------------+----------------------------+-------------------+--------+-------------------------+---------------------+
| 2025-07-01 20:37:25.396818 | 2025-07-01 20:38:34.302356 | __all_global_stat | 1 | baseline_schema_version | 1751373514259360 |
| 2025-07-01 20:37:25.396818 | 2025-07-01 20:37:27.871192 | __all_global_stat | 1 | core_schema_version | 1751373447795256 |
| 2025-07-01 20:37:25.396818 | 2025-07-01 20:37:25.396818 | __all_global_stat | 1 | current_data_version | 17180001539 |
| 2025-07-01 20:37:25.396818 | 2025-12-19 14:55:19.565381 | __all_global_stat | 1 | ddl_epoch | 16 |
| 2025-07-01 20:37:25.396818 | 2025-07-01 20:37:25.396818 | __all_global_stat | 1 | gc_schema_version | 0 |
| 2025-07-01 20:37:25.396818 | 2025-12-22 22:55:25.475389 | __all_global_stat | 1 | rootservice_epoch | 81 |
| 2025-07-01 20:37:25.396818 | 2025-12-23 11:01:52.046140 | __all_global_stat | 1 | snapshot_gc_scn | 1766458912046140000 |
| 2025-07-01 20:37:25.396818 | 2025-07-01 20:37:25.396818 | __all_global_stat | 1 | target_data_version | 17180001539 |
+----------------------------+----------------------------+-------------------+--------+-------------------------+---------------------+
8 rows in set (0.006 sec)
查询结果中 snapshot_gc_scn 对应的值(此处为 1766458912046140000)就是 snapshot_gc_ts。同样可以用 scn_to_timestamp 函数转换查看。
obclient(root@sys)[oceanbase]> select scn_to_timestamp(1766458912046140000);
+---------------------------------------+
| scn_to_timestamp(1766458912046140000) |
+---------------------------------------+
| 2025-12-23 11:01:52.046140 |
+---------------------------------------+
1 row in set (0.002 sec)
⚠️ 再次强调:直接访问内部系统表可能影响数据库稳定性,非必要不操作。
三、常见问题与处理思路
当监控发现 snapshot_gc_ts 异常时,可以参考以下思路进行初步排查。
| 问题 |
描述 |
处理建议 |
| snapshot_gc_ts 长时间不推进 |
主集群中该时间戳停滞超过1小时,可能由日志归档异常、日志流(LS)垃圾回收卡住等原因导致。 |
检查 observer.log 中 ob_garbage_collector.cpp 相关的日志,重点排查归档位点、checkpoint 推进是否被阻塞。 |
| 备库 snapshot_gc_ts 不动 |
在备库环境,副本数据未完全同步前,这是正常现象。 |
不需要干预,等待主备同步完成即可。 |
| 尝试手动恢复 |
在某些情况下,尝试切主可能恢复卡住的状态。 |
在技术支持指导下,使用命令:ALTER TENANT sys SET primary_zone = ‘xxx’; 此操作有风险,需谨慎。 |
例如,如果怀疑是垃圾回收器(Garbage Collector)卡住,可以查看相关日志:
[root@observer1 log]# cat observer.log|grep ob_garbage_collector|tail -20
[2025-12-23 13:42:04.183275] INFO [CLOG] gc_check_ls_status_ (ob_garbage_collector.cpp:1646) [8360][T1005_GCCollect][T1005][Y0-0000000000000000-0-0] [lt=13] gc_candidates push_back success(ret=0, candidate={ls_id_:{id:1}, ls_status_:1, gc_reason_:0})
... (更多日志输出)
四、辅助诊断视图
虽然不能直接查询 snapshot_gc_ts,但 OceanBase 提供了一些辅助视图来帮助分析整体的快照状态。
GV$OB_LS_SNAPSHOTS:这个视图从 V4.3.0 版本开始引入,用于展示日志流(LS)级别的快照信息。包含 TENANT_ID、LS_ID、SNAPSHOT_ID、SVR_IP 等字段,可以帮助你了解各个日志流上快照的分布和保留情况,是综合诊断存储层多版本问题的重要工具。
总结
snapshot_gc_ts 是OceanBase数据库中管理多版本数据生命周期的核心守门员。它的正常推进是保证存储空间效率和查询性能的基础。由于其存储在内部表中,日常监控应以日志分析为主,结合 GV$OB_LS_SNAPSHOTS 等视图进行综合判断。
运维人员应当建立对 snapshot_gc_ts 延迟的监控告警。一旦发现其长时间停滞,通常意味着底层有异常(如归档、GC等问题),应及时根据日志深入分析或联系OceanBase技术支持。希望这篇技术文档能帮助你更好地理解和处理与快照垃圾回收相关的问题。