作者:郑增权,爱可生 DBA 团队成员,OceanBase 和 MySQL 数据库技术爱好者。
爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。
本文约 1300 字,预计阅读需要 5 分钟。
1背景
某客户由于 OBServer 机器(租户 Follower 节点)发生过重启,且时钟同步服务未自动启动,导致此机器时间比时钟源落后 60s+!
集群合并时,发现时间落后的 OBServer 所在的 zone3 一直处于 COMPACTING 状态,合并无法完成。本文复现问题(步骤略)并记录排查过程。
环境说明:客户发生故障的环境为 OB 社区版,本文基于 OB 企业版复现,两版本均可复现。
2环境信息
OceanBase: 4.2.1.4 架构:1-1-1 zone1: 10.186.64.161 (RS Leader) zone2: 10.186.64.162 zone3: 10.186.64.163 时钟源: 10.186.64.160
3视图排查
查看集群租户信息
集群存在 5 个租户,其中 1001 和 1003 是 META 租户。
select * from __all_tenant;
查看租户级合并信息
LAST_SCN 表示上一轮已完成合并的版本号,GLOBAL_BROADCAST_SCN 表示当前这一轮全局广播的合并版本号。
LAST_SCN == GLOBAL_BROADCAST_SCN:当前轮次的合并已经结束
LAST_SCN != GLOBAL_BROADCAST_SCN:当前轮次的合并尚未结束。若长时间合并未结束,则可能是合并卡住了。
当前所有租户均处于合并卡住的状态。
select * from cdb_ob_major_compaction;
查看租户角色信息
若当前合并处于卡住状态(本文状态),直接查看卡住的租户 1 号日志流的 Leader 在哪个机器上。
若当前不处于合并卡住状态,则需找到合并卡住的租户的 1 号日志流切主历史。从切主历史中,找到需要排查的时间段内,租户的 1 号日志流的 Leader 在哪台机器上再进行排查。
可以看到租户 1 号日志流的 Leader 节点都在 10.186.64.161。
查看各租户 compaction_scn 小于 GLOBAL_BROADCAST_SCN 的信息
RS 端判定合并结束的主要流程:检查每个 zone 中的 tablet 版本号是否皆已推高至当前合并版本号,如果是,则更新 __all_zone_merge_info
内部表中对应 zone 的 last_merged_scn 并将 is_merging 置为 false。
__all_tablet_meta_table
存在于 SYS/META 租户下:比如要查 1004 租户下的某个 tablet,需要先切至其 META 租户才能查到 1004 的 tablet meta 信息( SYS 租户 2881 直连登陆后:alter system change tenant META$1004;
)。
meta
表目前实现了对应的虚拟表 __all_virtual_tablet_meta_table
,通过虚拟表查询则不需要切换租户。
下图可以看到有大量的 tablet 版本号未推高至当前合并版本号,导致合并卡住,需要进一步排查存储层为何尚未将这些 tablets 的版本推高至当前合并版本号(GLOBAL_BROADCAST_SCN)。
select count(*) from __all_virtual_tablet_meta_table where tenant_id = 1 and compaction_scn < 1718165680404973713;
select count(*) from __all_virtual_tablet_meta_table where tenant_id = 1001 and compaction_scn < 1718165680509150848;
select count(*) from __all_virtual_tablet_meta_table where tenant_id = 1002 and compaction_scn < 1718165680443836989;
select count(*) from __all_virtual_tablet_meta_table where tenant_id = 1003 and compaction_scn < 1718165680590612402;
select count(*) from __all_virtual_tablet_meta_table where tenant_id = 1004 and compaction_scn < 1718165680471683591;
查看 ZONE 级合并信息
可以看到是 zone3 卡住了合并。
select * from cdb_ob_zone_major_compaction;
查看合并诊断信息
RS_UNCOMPACTED:不一定存在异常。说明还存在 tablet 版本尚未推高至当前合并版本号,可以先通过 GV$OB_COMPACTION_PROGRESS
判断是否处于正常合并进行的状态。
如果还有 RUNNING 的合并,则大概率是合并任务的问题。
这里可以看到存在 tablet 数据快照版本号未更新的情况(compaction_scn_not_update)。
select * from __all_virtual_compaction_diagnose_info where create_time >= '2024-06-12%';
确认存储层合并是否完成
TABLET_COMPACTION_FINISHED:代表存储层合并已完成。
可以看到每个租户所有 zone 存储层均已完成合并,但 RS 未完成后续操作导致合并卡住。
结合前方排查信息,RS 未进行后续操作的原因是存在 tablet 数据快照版本号未更新,需要进一步排查为何数据快照版本号(compaction_scn)未更新的原因。
select * from __all_virtual_server_compaction_event_history where tenant_id = 1 and compaction_scn = 1718165680404973713 and event like '%FINISHED%' order by zone;
select * from __all_virtual_server_compaction_event_history where tenant_id = 1001 and compaction_scn = 1718165680509150848 and event like '%FINISHED%' order by zone;
select * from __all_virtual_server_compaction_event_history where tenant_id = 1002 and compaction_scn = 1718165680443836989 and event like '%FINISHED%' order by zone;
select * from __all_virtual_server_compaction_event_history where tenant_id = 1003 and compaction_scn = 1718165680590612402 and event like '%FINISHED%' order by zone;
select * from __all_virtual_server_compaction_event_history where tenant_id = 1004 and compaction_scn = 1718165680471683591 and event like '%FINISHED%' order by zone;
查看 GV$OB_COMPACTION_PROGRESS,可以看到不存在仍在运行的合并任务。
select * from GV$OB_COMPACTION_PROGRESS where status != 'FINISH';
排查至此我们发现从相关视图中可以找到的信息比较有限,转入日志排查,尝试寻找合并卡住的具体原因。
4日志排查
1. 查看是否存在 tablet 版本尚未推高至当前合并版本号
由于合并服务注册在每个租户 1 号日志流的 Leader上,前方已查出在 10.186.64.161 ,查看此机器的日志。
在 10.186.64.161 执行如下语句,定位未成功合并的分区。
tail -10
为可选项,避免打印信息过多我们复制一个 trace_id 用于后续排查,此处我们选择 sys 租户的 trace_id
grep --color=always "replica not merged" rootservice.log | tail -10
2. grep 前方复制的 tarce_id : 查看详细信息
zone1 和 zone2 的 unmerged_cnt=0,说明所有 tablet 副本版本都已推高至当前合并版本号。
zone3 的 unmerged_cnt=891,说明 zone3 中还有 891 个 tablet 副本版本尚未推高至当前合并版本号。
grep "YB420ABA40A1-00061A34C8AC5770-0-0" rootservice.log* | grep --color=always "unmerged_cnt" | grep --color=always -E "zone1|zone2|zone3"
3. 确认 Tablet 对应租户是否发起了版本号为 broadcast_scn 的合并。
可以看到卡住的租户都发起了版本号等于 broadcast_scn 的合并。
grep "try to schedule merge" observer.log.202406121* | grep --color=always "tenant_id" | grep --color=always "scn:{val:"
4. 确认 zone3 合并前的转储 memtable 是否冻结
需要确认 memtable 的 snapshot version 是否大于本次合并的版本号,如果小于,则说明备机读时间戳没有推过冻结点。
若没有日志,说明 memtable 没有冻结。 tail -1
为可选项,避免打印信息过多,实际排查请去掉
可以看到 memtable 的 snapshot version 大于对应租户本次合并的版本号 ,即 zone3 合并前的转储 memtable已经冻结。
grep --color=always "ready for flush" observer.log* | grep -w T1 | grep --color=always -w "snapshot_version:{val" | tail -1
grep --color=always "ready for flush" observer.log* | grep -w T1001 | grep --color=always -w "snapshot_version:{val" | tail -1
grep --color=always "ready for flush" observer.log* | grep -w T1002 | grep --color=always -w "snapshot_version:{val" | tail -1
grep --color=always "ready for flush" observer.log* | grep -w T1003 | grep --color=always -w "snapshot_version:{val" | tail -1
grep --color=always "ready for flush" observer.log* | grep -w T1004 | grep --color=always -w "snapshot_version:{val" | tail -1
5. 确认 zone3 转储是否成功生成了对应的转储/合并 sstable
可以看到存在 4012 报错的 MINI_MERGE
MINI_MERGE:表示转储,冻结 MemTable 通过转储变成 Mini SSTable
grep "sstable merge finish" observer.log* | grep -v "ret=0" | grep --color=always "ret="
复制 trace_id
检索,确认此处转储最终状态是否为成功。
此处结果显示报错的转储最终是成功的,即转储全部成功生成了对应的转储/合并 sstable
6. 租户合并信息汇报确认
__all_tablet_meta_table
表存在于 SYS/META 租户下,即 SYS 租户或 META 租户会向 __all_tablet_meta_table
表汇报合并信息(普通租户需切至对应的 META 租户进行汇报),我们主要基于 tenant_id 为 1、1001、1003 这三个租户来看下是否汇报成功。
取一条租户汇报失败的语句,复制其 trace_id
。
grep "REPORT: batch update tablets" observer.log | grep "ret=-"
7. grep 复制的 trace_id,可以看到存在向 __all_tablet_meta_table 汇报失败的行为
grep "YB420ABA40A3-00061A354A6E3DD4-0-0" observer.log* | grep "__all_tablet_meta_table" | grep errcode | grep compaction_scn | head -1
可以看到 1001 租户 在发起对应的 GLOBAL_BROADCAST_SCN
(1718165680509150848 )汇报时遭遇 6210 超时报错。
汇报超时:OB_TRANS_TIMEOUT。
8. 在 trace_id 中检索关键字 "original error message",看它对应的远端地址(remote_addr) 是哪个OBServer节点
可以看到 remote_addr 是 10.186.64.161。
grep "YB420ABA40A3-00061A354A6E3DD4-0-0" observer.log* | grep "original error message"
9. 根据提示到 remote_addr ( 10.186.64.161) 的 observer.log 中检索当前的trace_id
报错 :PNIO packet wait too much time between proxy and server_cb
可能是如下四种情况导致:
两台机器之间时钟不同步,使用 clockdiff IP 命令来确认。 网络延迟大,通过 ping 大包来确认。 系统负载高导致,网络、CPU、内存使用异常。 OBServer 进程被 gdb 或者 pstack 了,导致线程被暂停。
grep "YB420ABA40A3-00061A354A6E3DD4-0-0" observer.log* | grep "packet wait too much time"
10. 查看与时钟源的时间差
可以看到 zone3 的 OBServer 机器与时钟源存在落后 65s 的时间偏差。
clockdiff 10.186.64.160
5解决方法
将租户 leader 切至 zone3 所在的 OBServer 节点(临时解决,不建议)。 将 zone3 所在 OBServer 节点系统时间调整为正确时间(合理解决,建议),本文采用。
1. 将时间回调正常
systemctl stop ntpd
date && ntpdate 10.186.64.160 && date
systemctl start ntpd && systemctl status ntpd
clockdiff 10.186.64.160
2. 查看合并状态
可以看到 zone3 已经合并成功。
select * from cdb_ob_zone_major_compaction;
6结论
合并卡住的原因是更新 __all_tablet_meta_table
系统表 OB_TRANS_TIMEOUT
(超时),zone3 上各分区的新 major sstable 已生成,但是由于时间偏差(zone3 节点 OBServer 机器时钟落后 65s),zone3 无法将 compaction_scn 汇报到 __all_tablet_meta_table
表,导致 RS 判断合并未完成,zone3 合并状态一直处于 COMPACTING 状态。
7优化措施
合理配置时钟源和时钟服务自启动 关注时钟延迟相关告警信息
温馨提示
可以使用 obdiag 或者 OBStack 进行合并卡住问题分析
参考资料
《如何排查合并卡住问题》:https://www.oceanbase.com/knowledge-base/oceanbase-database-1000000000685150?back=kb 《OceanBase 数据库 V4.x 版本 RS 端合并卡住排查手册》:https://www.oceanbase.com/knowledge-base/oceanbase-database-1000000000816610?back=kb 《如何调整 OBServer 的操作系统时间》:https://www.oceanbase.com/knowledge-base/oceanbase-database-20000000070?back=kb 《compaction_diagnose 视图使用指南》:https://www.oceanbase.com/knowledge-base/oceanbase-database-1000000000209906?back=kb 《OceanBase 数据库中启用 pkt-nio 功能时 RPC 的 fly_ts 耗时长的原因》:https://www.oceanbase.com/knowledge-base/oceanbase-database-1000000000699896?back=kb
本文关键字:#OceanBase# #时间偏差#
✨ Github:https://github.com/actiontech/sqle
📚 文档:https://actiontech.github.io/sqle-docs/
💻 官网:https://opensource.actionsky.com/sqle/
👥 微信群:请添加小助手加入 ActionOpenSource
🔗 商业支持:https://www.actionsky.com/sqle