大数跨境
0
0

OB 运维|一则 OceanBase 集群不可用问题排查案例

OB 运维|一则 OceanBase 集群不可用问题排查案例 爱可生开源社区
2025-11-27
0
导读:一套完整的 OOM 排查过程。

作者:任仲禹,爱可生数据库工程师,OBCE/OceanBase 2025 年度布道师。

爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。

本文约 2900 字,预计阅读需要 10 分钟。



1. 背景

某日 19 点左右,收到客户业务反馈:某 OceanBase 业务集群不可用,OCP 中该集群显示为异常状态,需要紧急处理。

环境信息

环境为 3 节点 1-1-1 架构,421 版本集群:

  • OBServer1:88.88.88.32
  • OBServer2:88.88.88.33
  • OBServer3:88.88.88.34

2. 应急处理过程

为保证尽快恢复业务,略过根因分析,尝试重启集群。故障期间 OCP 平台中该集群处于异常状态:

  • 节点 32 OBServer1 正常运行
  • 节点 33 OBServer1 异常
  • 节点 34 OBServer1 异常

2.1 启动 OBServer2

分析 OBServer2 时,发现节点 33 的 OBServer 进程已经不存在,所以选择直接启动。

  • 进程不存在的原因搁置,后文进行分析
# 切换到 admin 用户
su - admin

# 查出 OBServer 进程号
ps -ef | grep OBServer 

# 启动 OBServer 进程
cd /home/admin/oceanbase/
/home/admin/oceanbase/bin/OBServer

# 查出 OBServer 进程
ps -ef | grep OBServer 

2.2 启动 OBServer3

处理 OBServer3 时,发现节点 34 的 OBServer 进程已经不存在,所以选择直接启动。

  • 进程不存在的原因搁置,后文进行分析
# 切换到 admin 用户
su - admin

# 查出 OBServer 进程号
ps -ef | grep OBServer 

# 启动 OBServer 进程
cd /home/admin/oceanbase/
/home/admin/oceanbase/bin/OBServer

# 查出 OBServer 进程
ps -ef | grep OBServer 

2.3 检查集群是否正常

OBServer 节点全部启动后,通过元数据视图进行状态检查。

# 登录集群的 sys 租户
obclient -h88.88.88.32 -P2883 -uroot@sys#obdemo -pxxxxxxxxxxx -A

# 执行如下命令
obclient> select gmt_modified,svr_ip,status,stop_time,start_service_time from __all_server;
+----------------------------+-------------+--------+-----------+--------------------+
| gmt_modified               | svr_ip      | status | stop_time | start_service_time |
+----------------------------+-------------+--------+-----------+--------------------+
| 2025-05-07 07:39:56.581325 | 88.88.88.32 | active |         0 |   1746574794656340 |
| 2025-05-07 07:41:29.154517 | 88.88.88.33 | active |         0 |   1746574886937797 |
| 2025-05-07 07:40:08.583806 | 88.88.88.34 | active |         0 |   1746574807774666 |
+----------------------------+-------------+--------+-----------+--------------------+
3 rows in set (0.01 sec)

确保如下字段的值全部满足必要条件,即表示 OBServer 节点为正常运行。

  • Status:节点状态;必须为 active
  • Stop_time:节点停止时间;必须为 0
  • Start_service_time:节点服务运行时间:必须不为 0

3. 故障原因排查

3.1 节点 33 故障原因分析

3.1.1 检查 OBServer 日志

登录到节点 33,进入 /home/admin/oceanbase/log/ 目录,查询  OBServer.log 日志进行分析。

得到的线索如下:

  1. 07:37 分手工处置之前,2025年4月21日12:23:00 该 33 节点已停止打印日志,此时数据库进程已经不在。
  2. 日志有显示:clog disk may be hang or something error has happen! 即数据库写 redo 日志所在的磁盘出现 hang 的情况或其它错误。

3.1.2 检查 OS-message 日志

根据线索,继续排查操作系统的 message 日志。

部分关键 message 日志如下:

Apr 21 12:23:00 ob2 systemd[1]: [114136712.106915] Stopped Journal Service.
Apr 21 12:23:00 ob2 systemd[1]: [114136712.108908] Starting Journal Service...
Apr 21 12:23:00 ob2 systemd[1]: [114136802.198799] Failed to start Journal Service.
Apr 2112:23:00 ob2 systemd[1]: [114136811.949713] Stopped Network Service.
Apr 2112:23:00 ob2 systemd[1]: [114136811.951961Starting Network Service...
Apr 2112:23:00 ob2 systemd[1]: [114136902.197882] systemd-networkd.service: start operation timed out. Terminating.
Apr 2112:23:00 ob2 systemd[1]: [114136902.197882] systemd-networkd.service: start operation timed out. Terminating.
Apr 2112:23:00 ob2 kernel: [114137610.805255] smartpqi 0000:5e:00.0resetof scsi 15:1:0:0SUCCESS
Apr 2112:23:00 ob2 kernel: [114137610.846264] sd 15:1:0:0: timing out command, waited 180s
Apr 2112:23:00 ob2 kernel: [114137610.846273] sd 15:1:0:0: [sda] tag#889 FAILED Result: hostbyte=DID_IMM_RETRY driverbyte=DRIVER_OK
Apr 2112:23:00 ob2 kernel: [114137610.846276] sd 15:1:0:0: [sda] tag#889 CDB: Read(16) 88 00 00 00 00 00 00 54 de c0 00 00 00 08 00 00
Apr 2112:23:00 ob2 kernel: [114137610.846279] print_req_error: 96 callbacks suppressed
Apr 2112:23:00 ob2 kernel: [114137610.846281] print_req_error: I/O error, dev sda, sector 5562048
Apr 2112:23:00 ob2 kernel: [114137610.846286Read-erroron swap-device (253:1:3052224)
Apr 2112:23:00 ob2 kernel: [114137610.846444] print_req_error: I/O error, dev sda, sector 632512664
Apr 2112:23:00 ob2 kernel: [114137610.846499] print_req_error: I/O error, dev sda, sector 805802552
Apr 2112:23:00 ob2 kernel: [114137610.846523] sd 15:1:0:0: timing out command, waited 180s
Apr 2112:23:00 ob2 kernel: [114137610.846499] print_req_error: I/O error, dev sda, sector 805802552
Apr 2112:23:00 ob2 kernel: [114137610.846523] sd 15:1:0:0: timing out command, waited 180s
Apr 2112:23:00 ob2 kernel: [114137610.846594] print_req_error: I/O error, dev sda, sector 632524944
Apr 2112:23:00 ob2 kernel: [114137610.846613] sd 15:1:0:0: timing out command, waited 180s

得到的线索如下:

1. 节点 33 的操作系统日志,在 12:23:00 确实有涉及 os-kernel 的信息输出。

Apr 21 12:23:00 ob2 kernel: [114136267.896464] smartpqi 0000:5e:00.0: resetting scsi 15:1:0:0
  • 根据日志信息,smartpqi 驱动在尝试重置 SCSI 总线时触发了磁盘离线问题,可能涉及驱动程序与硬件的兼容性或稳定性问题。
Apr 21 12:23:00 ob2 kernel: [114137610.846444] print_req_error: I/O error, dev sda, sector 632512664
Apr 21 12:23:00 ob2 kernel: [114137610.846499] print_req_error: I/O error, dev sda, sector 805802552
  • 根据信息,操作系统在访问磁盘时发生了 输入/输出(I/O)错误,具体是设备 /dev/sda 的xx 扇区 无法正常读写;猜测是磁盘坏块/不可用导致。

2. 磁盘 I/O 错误期间,部分系统重要服务也被异常停止,例如日志服务和网络服务。

Apr 21 12:23:00 ob2 systemd[1]: [114136712.106915] Stopped Journal Service.
Apr 21 12:23:00 ob2 systemd[1]: [114136712.108908] Starting Journal Service...
Apr 21 12:23:00 ob2 systemd[1]: [114136802.198799] Failed to start Journal Service.
Apr 21 12:23:00 ob2 systemd[1]: [114136811.949713] Stopped Network Service.
Apr 21 12:23:00 ob2 systemd[1]: [114136811.951961Starting Network Service...

3. 将问题报与硬件工程师沟通

  • 经确认,当时该节点数据盘确实坏了 1 块,后续已经修好。

3.2 节点34故障原因分析

3.2.1 检查 OBServer 日志

登录到节点 34,进入 /home/admin/oceanbase/log/ 目录,查询 OBServer.log 日志进行分析。

得到线索如下:

  • 07:39 分手工处置之前,2025年5月07日04:55:42 该 34 节点已停止打印日志,此时数据库进程不在。

3.2.2 检查 OS-message 日志

继续排查操作系统的 message 日志。

能看到,在5月7日04:55:42秒左右,节点 34 的 OBServer 进程被 Linux-OOM-killer 杀死。

  • 查看节点34 的物理内存大小。

为什么 OOM-Killer 要杀死 OBServer 进程?

OOM Killer 是 Linux 内核设计的一种机制,在内存不足时选择一个进程杀死,释放内存来满足内存分配的的需求,避免系统 crash。

通常我们要求 OBServer 服务器为 OceanBase 数据库独占,不建议同时在 OBServer 服务器上部署其他应用。当 OBServer 其他应用共享服务器时,如果操作系统发生 OOM(Out-of-Memory),因为 OBServer 进程使用的内存较多,操作系统很可能杀掉 OBServer 进程来释放内存。

3.2.3 当时 Linux 的可用内存多少?OBServer 用了多少?

1. message 日志有打印,OBServer 进程当前用的实际物理内存是 187603704 kB,即 178G。

  • rss 表示进程的 驻留集大小,即当前实际驻留在物理内存(RAM)中的内存量,单位为 KB。
May  7 04:55:42 ob3 kernel: [115486651.142354] Killed process 3391142 (OBServer) total-vm:216443928kB, anon-rss:187603704kB, file-rss:87512kB, shmem-rss:0kB

2. OBServer 用的内存符合预期吗?

该集群配置的内存使用上限参数是 80; 80% * 251(机器总内存)= 200G。

  • 实际 OBServer 使用 178G 符合预期的(没超过 OB 的最大可用内存上限 200G)。

根据监控也能看到,当时 Linux 实际 used 内存为 188G 左右。

3. 当时 Linux 可用内存多少?

根据 message 日志与 tsar 监控,故障时节点 34 的操作系统实际使用 188.2G 内存,有 16470296 个缓存页可用。

  • 16470296 * 4kb(Linux 默认页大小) =  62.8G
  • 根据监控:62.8G 缓冲 + 188G USED = 251 【Linux 总内存】 根据 Linux 操作系统原理,缓冲内存也是实际可用内存。但是为何还是发生了 OOM-killer?

3.2.4 简单浅析 Linux OOM Kill 触发机制与缓存页的联系

1. 缓存页的可回收性

Page Cache 缓存页本质上是可回收的,但回收过程需要时间(如同步脏数据到磁盘)。当系统物理内存不足时,内核优先触发缓存回收,但遇到以下场景会导致回收效率不足:

  • 脏页比例过高‌:需写入磁盘后才能释放内存,若 I/O 性能瓶颈导致回收延迟,无法满足进程的实时内存需求。
  • 缓存页被锁定‌:某些场景(如文件内存映射 mmap)会锁定部分缓存页,导致无法立即回收。

2. OOM 触发条件

OOM Killer 的激活取决于实时可用物理内存量而非缓存总量:

  • 当进程申请内存时,若物理内存不足且缓存回收速度无法跟上需求,直接触发 OOM。
  • 即使缓存总量大,若短时间内进程集中申请大量物理内存(如 malloc + memset 强制分配),可能绕过缓存回收直接耗尽内存。

4. 结论

4.1 集群异常导致业务不可用的原因

根据故障处理时间线:

  1. 4月21日12点23分节点 33 就已 crash 了,有生成 coredump 文件。
  2. 5月7日04点55分节点 34 crash,此时不满足多数派,集群不可用。
  3. 5月7日早上7点左右应急处理:手工启动 33、34,重启 32。

原因可以明晰:

  • 7号04点55分,集群中 3 节点,连续挂了 2 个,不满足 OB 多数派,集群异常符合预期。

4.2 两个节点陆续宕机的原因

4.2.1 节点 33 宕机原因

根据上文分析,该 33 节点的 OBServer 进程宕机是因为数据磁盘坏块导致,经过与硬件工程师确认,故障时刻,数据盘确实坏了 1 块。

4.2.2 节点 34 宕机原因

根据上文分析,该 34 节点 OB 宕机原因是所在 Linux 物理机实际物理内存耗尽,导致物理内存不足且缓存【脏页】回收速度无法跟上需求,直接触发 OOM。

如何规避该问题?

内存的缓存页实际存储的是操作系统的 “脏数据”,我们可以调整脏数据的占比在当前场景来规避该问题。

# 添加到 /etc/sysctl.conf
vm.dirty_background_ratio = 10  # 设置脏页占比阈值至 10% ; 即内存可以填充“脏数据”的百分比。这些“脏数据”在稍后是会写入磁盘的,pdflush/flush/kdmflush这些后台进程会稍后清理脏数据。举一个例子,我有250G内存,那么有 25G 的内存可以待着内存里,超过 25 G的话就会有后来进程来清理它。
vm.dirty_ratio = 20       # 设置脏数据的硬限制为 20%,内存里的脏数据百分比不能超过这个值。如果脏数据超过这个数量,新的IO请求将会被阻挡,直到脏数据被写进磁盘。这是保证内存中不会存在过量脏数据的保护机制。

sysctl -p


本文关键字:#OceanBase #OOM #





带宽被 OBServer 备份 “榨干”,集群陷入 “无主” 危机
一个案例掌握 OMS 校验方式及适用场景
OBLogProxy 在 Binlog 模式下的故障案例解析
计算 OceanBase 可用 CPU 的核心逻辑
3.X vs 4.X:OceanBase 手动收集统计信息的天壤之别!


✨ Github:https://github.com/actiontech/sqle

📚 文档:https://actiontech.github.io/sqle-docs/

💻 官网:https://opensource.actionsky.com/sqle/

👥 微信群:请添加小助手加入 ActionOpenSource

🔗 商业支持:https://www.actionsky.com/sqle


【声明】内容源于网络
0
0
爱可生开源社区
爱可生开源社区,提供稳定的MySQL企业级开源工具及服务,每年1024开源一款优良组件,并持续运营维护。
内容 1953
粉丝 0
爱可生开源社区 爱可生开源社区,提供稳定的MySQL企业级开源工具及服务,每年1024开源一款优良组件,并持续运营维护。
总阅读1.9k
粉丝0
内容2.0k