基于湖库一体架构,统一管理结构化、半结构化与非结构化等多模态数据,一个系统承载事务处理、实时分析与 AI 工作负载。
合并问题排查
更新时间:2026-06-30 12:18:33
本文主要介绍合并慢、超时问题的排查方法。
适用版本
OceanBase 数据库所有版本
问题排查思路
在进行合并问题排查时,首先要确定当前集群中的合并配置项,确定当前的合并状态,然后根据查询得到的情况,对不同的合并问题类型进行分析后再寻找根因。
确认合并配置项
OceanBase 数据库中包含以下合并相关的配置项:
enable_manual_merge:是否开启手动合并,取值为TRUE表示需要手动合并,默认为FALSE。zone_merge_concurrency:用于设置在合并时,支持多少个 Zone 并发。当值为0时,由系统根据部署情况自动选择最佳并发度,一般不需要设置。默认为1,表示单次只有一个 Zone 进行合并。zone_merge_order:用于设置 Zone 的轮转合并顺序。不指定时,由系统自动决定,一般不需要设置。enable_merge_by_turn:用于设置是否开启轮转合并策略,设置为TRUE时表示开启轮转合并,默认为FALSE。major_freeze_duty_time:每日合并发起时间。enable_auto_leader_switch:用于设置是否开启自动切主,默认为TRUE。
有关以上系统配置项的详细信息,请参见《OceanBase 数据库 参考指南》中的 配置项参考 章节。
确认合并状态
本例中,当前的 frozen_version 为 25,表示集群需要合并到 25 版本,但 cn-shanghai-e 这个 Zone 副本只合并到了 24 版本。
obclient> SELECT * FROM __all_zone WHERE name = "frozen_version" or name = "last_merged_version";
+----------------------------+----------------------------+---------------+---------------------+-------+------+
| gmt_create | gmt_modified | zone | name | value | info |
+----------------------------+----------------------------+---------------+---------------------+-------+------+
| 2020-12-07 16:01:30.793286 | 2020-12-30 02:00:00.445594 | | frozen_version | 25 | |
| 2020-12-07 16:01:30.793490 | 2020-12-29 02:01:12.449651 | | last_merged_version | 24 | |
| 2020-12-07 16:01:30.794375 | 2020-12-29 02:01:11.880114 | cn-shanghai-e | last_merged_version | 24 | |
| 2020-12-07 16:01:30.795109 | 2020-12-30 02:01:15.563291 | cn-shanghai-f | last_merged_version | 25 | |
| 2020-12-07 16:01:30.795842 | 2020-12-30 02:01:22.694016 | cn-shanghai-g | last_merged_version | 25 | |
+----------------------------+----------------------------+---------------+---------------------+-------+------+
5 rows in set (0.00 sec)
继续查询 __all_zone 表,查看 cn-shanghai-e 的合并状态,发现状态为 MERGING,表示正在合并。
obclient> SELECT * FROM __all_zone WHERE name = "merge_status";
+----------------------------+----------------------------+---------------+---------------------+---------+------+
| gmt_create | gmt_modified | zone | name | value | info |
+----------------------------+----------------------------+---------------+---------------------+---------+------+
| 2020-12-07 16:01:30.793286 | 2020-12-30 02:00:00.445594 | | merge_status | MERGING | |
| 2020-12-07 16:01:30.794375 | 2020-12-29 02:01:11.880114 | cn-shanghai-e | merge_status | MERGING | |
| 2020-12-07 16:01:30.795109 | 2020-12-30 02:01:15.563291 | cn-shanghai-f | merge_status | IDLE | |
| 2020-12-07 16:01:30.795842 | 2020-12-30 02:01:22.694016 | cn-shanghai-g | merge_status | IDLE | |
+----------------------------+----------------------------+---------------+---------------------+---------+------+
5 rows in set (0.00 sec)
合并问题类型
根据上面查询到的信息,一般情况下可以分为以下几类:未合并问题、合并超时问题、合并慢问题。下面针对每一类问题进行详细的分析。
未合并问题
未合并问题分为两类:RootService 没有发起相关 Zone 的合并和副本未合并。
Zone 未合并
根据上面的信息,发现正在合并,此时查询该 Zone 的 global_broadcast_version 与 broadcast_version。 如果 broadcast_version 等于 last_merged_version,且 last_merged_version 落后于 global_broadcast_version,说明 RootService 没有发起相关 Zone 的合并 。
obclient> SELECT * FROM __all_zone WHERE name = "global_broadcast_version" or name = "broadcast_version";
+----------------------------+----------------------------+---------------+--------------------------+---------+------+
| gmt_create | gmt_modified | zone | name | value | info |
+----------------------------+----------------------------+---------------+--------------------------+---------+------+
| 2020-12-07 16:01:30.793286 | 2020-12-30 02:00:00.445594 | | global_broadcast_version | 25 | |
| 2020-12-07 16:01:30.794375 | 2020-12-29 02:01:11.880114 | cn-shanghai-e | broadcast_version | 24 | |
| 2020-12-07 16:01:30.795109 | 2020-12-30 02:01:15.563291 | cn-shanghai-f | broadcast_version | 25 | |
| 2020-12-07 16:01:30.795842 | 2020-12-30 02:01:22.694016 | cn-shanghai-g | broadcast_version | 25 | |
+----------------------------+----------------------------+---------------+--------------------------+---------+------+
5 rows in set (0.00 sec)
对于 RootService 未发起相关 Zone 合并的情况,按以下方法排查:
排查 RootService 合并调度线程是否有报错。
如果有返回值,则说明合并调度线程存在错误。
grep "daily.*merge.*ret=-" rootservice.log检查集群是否正在补副本。 如果以下查询有返回值,则说明正在进行副本的负载均衡。
obclient> SELECT count(*) FROM __all_virtual_replica_task;
副本未合并
本例继续假设当前要合并的目标版本是 25,查询 meta 表查看 data_version != 25 的副本以缩小排查范围。
- 对于社区版 OceanBase 数据库 V3.1.X 及后续版本,查询
__all_virtual_core_meta_table、__all_virtual_core_root_table、__all_root_table与__all_virtual_meta_table表。
obclient> SELECT * FROM __all_virtual_meta_table WHERE data_version != 25 LIMIT 10;
+-----------+------------------+--------------+---------------+----------+----------------------------+----------------------------+----------+---------+---------------+---------------+------+-----------------------------------------------------------------------------------------------------------+-----------+-----------+--------------+---------------+--------------+-----------------+--------------------+--------------------+-------------+---------+--------------+---------------+-----------------------+------------+--------------------+--------+-----------+--------------------+------------------+
| tenant_id | table_id | partition_id | svr_ip | svr_port | gmt_create | gmt_modified | sql_port | unit_id | partition_cnt | zone | role | member_list | row_count | data_size | data_version | data_checksum | row_checksum | column_checksum | is_original_leader | is_previous_leader | create_time | rebuild | replica_type | required_size | status | is_restore | partition_checksum | quorum | fail_list | recovery_timestamp | memstore_percent |
+-----------+------------------+--------------+---------------+----------+----------------------------+----------------------------+----------+---------+---------------+---------------+------+-----------------------------------------------------------------------------------------------------------+-----------+-----------+--------------+---------------+--------------+-----------------+--------------------+--------------------+-------------+---------+--------------+---------------+-----------------------+------------+--------------------+--------+-----------+--------------------+------------------+
| 1001 | 1100611139463766 | 0 | xxx.xxx.x.xa | xxxx | 2020-12-29 10:34:15.176561 | 2020-12-29 10:34:15.205753 | 2881 | 1001 | 0 | cn-shanghai-e | 1 | xxx.xxx.x.xx:2882:1609209255175464,xxx.xxx.x.xx:2882:1609209255175464,xxx.xxx.x.xx:2882:1609209255175464 | 0 | 0 | 24 | 0 | 0 | | 0 | 1609209255204831 | 0 | 0 | 0 | 0 | REPLICA_STATUS_NORMAL | 0 | 0 | 3 | | 0 | 100 |
+-----------+------------------+--------------+---------------+----------+----------------------------+----------------------------+----------+---------+---------------+---------------+------+-----------------------------------------------------------------------------------------------------------+-----------+-----------+--------------+---------------+--------------+-----------------+--------------------+--------------------+-------------+---------+--------------+---------------+-----------------------+------------+--------------------+--------+-----------+--------------------+------------------+
1 row in set (0.07 sec)
根据上面的信息,发现是 pkey 为{tid:1100611139463766, partition_id:0} 的表在 xxx.xxx.x.xa:xxxx 机器上未合并。
也可以通过搜索 rootservice.log 定位是哪个表阻塞了合并。
合并超时问题
定位未合并到指定版本的 partition。
进数据库查询 例如当前要合并的目标版本是 25,可以去 meta 表看
data_version != 25的副本,从而缩小排查范围。 说明这里 meta 表指一组表,一般先看最后一级 meta 表
__all_meta_table/__all_virtual_meta_table)有没有 data_version 没推上去的副本,没有的话,查看更上一级的 meta 表。对于 V3.1.x 版本,meta 表指
__all_virtual_core_meta_table、__all_virtual_core_root_table、__all_root_table、__all_virtual_meta_table。在数据库后台查询 以
not merged为关键词搜索 RS 所在机器上的最新的rootservice.log。
判断该 partition 的合并任务是否在执行中。
SELECT * FROM __all_virtual_sys_task_status;可以通过该虚拟表拿到执行的 trace,然后去对应机器上查询,判断合并任务是否卡住。
如果该 partition 没有调度合并任务,判断该 partition 的最新的转储 sstable 的 snapshot_version 有没有推过
freeze_info点,如果没有推过freeze_info点,说明转储有问题。SELECT * FROM __all_virtual_table_mgr WHERE table_id = xxx and partition_id = xxx; SELECT * FROM __all_virtual_freeze_info WHERE data_version = xxx;如果没有获取任何有用信息,可以搜索最近一段时间的
observer.log的 ERROR 日志来获取线索。
合并慢问题
如果合并还未结束,可以按照合并超时的排查路径进行排查。如果合并已经完成,可以按照以下步骤进行排查。
通过 SQL 查询指定 Major 版本的合并信息统计,找到合并耗时最多的几个 partition 来具体分析。
SELECT /*+ query_timeout(10000000)*/* FROM __all_virtual_partition_sstable_merge_info WHERE merge_type = "major merge" and version = "<merge_version>" ORDER BY merge_cost_time desc limit 5;说明
version有三个字段,第一个非 0 字段是merge_version,查询时需要替换成本次合并的merge_version,后两个字段保持为0即可。 您可通过__all_zone表可以查到本次合并的merge_version。通过表
__all_virtual_partition_sstable_merge_info查看宏块重用情况。步骤 1 中的
occupy_size、macro_block_count、use_old_macro_block_count、rewrite_macro_old_micro_block_count、rewrite_macro_total_micro_block_count等字段,分别表示该 partition 的数据量、宏块数、重用宏块数、重用宏块中重写的微块数。如果重用宏块数量 、总宏块数的比率非常低有可能会产生合并变慢的情况,这种情况有可能发生在新导入表的第一次合并或随机写严重,导致发生了全量合并。查看合并开始时间是否合理。
SELECT * FROM __all_virtual_partition_sstable_merge_info WHERE table_id = xxx and partition_id = xxx and svr_ip = "xxx" ORDER BY merge_finish_time desc LIMIT 10;找到合并开始最晚的几个 partition,在该时间段的
observer.log中搜索其 compaction 记录。grep "sstable merge finish.* table_id.* partition_id" observer.log.20211117* | vi -如果有报错信息需要在合并模块进行排查。