obdiag如何实现一键采集20+故障场景的诊断信息——《OceanBase诊断系列》之九

作者简介:靖顺,OcenaBase 开发工程师,专注于数据库诊断与调优


1. 前言

在2024年初,我与一线运维人员交流时,他们纷纷提及在运维过程中遭遇的难题------OceanBase 出现问题时,排查工作不容易,有时需要依赖原厂的支持人员。然而,线上交流效率不高,故障排查的时间又尤为宝贵,他们反馈说,花费在信息采集上的时间过多,这无疑影响了服务的SLA。因此,我向他们推荐了obdiag这个工具,并建议他们使用一行命令进行信息采集。几位支持人员给出了反馈,他们认为目前obdiag的诊断信息采集虽然功能全面,但各项采集任务是独立的,如采集日志、主机信息、SQL信息等,这对于单个问题的排查来说仍显繁琐。他们期望能针对常见的故障场景提供套餐式的一键采集功能,以更高效地完成信息采集工作。

本着客户第一的原则。这个需求必须高效优先去做。就有了2024年1月31号发布的obdiag 1.6版本,支持场景化的一键诊断信息采集

2. obdiag 场景化信息采集使用

2.1 支持的场景列表

执行如下命令可查看支持的场景

obdiag gather scene list

结果如下:

#obdiag gather scene list

[Other Problem Gather Scenes]:
---------------------------------------------------------------------------------------
command                                                   info_en               info_cn
---------------------------------------------------------------------------------------
obdiag gather scene run --scene=other.application_error   [application error]   [应用报错问题]
---------------------------------------------------------------------------------------

[Obproxy Problem Gather Scenes]:
----------------------------------------------------------------------------------
command                                           info_en             info_cn
----------------------------------------------------------------------------------
obdiag gather scene run --scene=obproxy.restart   [obproxy restart]   [obproxy无故重启]
----------------------------------------------------------------------------------

[Observer Problem Gather Scenes]:
---------------------------------------------------------------------------------------------------------------------------------------------------------------------
command                                                                                                            info_en                         info_cn
---------------------------------------------------------------------------------------------------------------------------------------------------------------------
obdiag gather scene run --scene=observer.backup                                                                    [backup problem]                [数据备份问题]
obdiag gather scene run --scene=observer.backup_clean                                                              [backup clean]                  [备份清理问题]
obdiag gather scene run --scene=observer.clog_disk_full                                                            [clog disk full]                [clog盘满]
obdiag gather scene run --scene=observer.cluster_down                                                              [cluster down]                  [集群无法连接]
obdiag gather scene run --scene=observer.compaction                                                                [compaction]                    [合并问题]
obdiag gather scene run --scene=observer.cpu_high                                                                  [High CPU]                      [CPU高]
obdiag gather scene run --scene=observer.delay_of_primary_and_backup                                               [delay of primary and backup]   [主备库延迟]
obdiag gather scene run --scene=observer.io                                                                        [io problem]                    [io问题]
obdiag gather scene run --scene=observer.log_archive                                                               [log archive]                   [日志归档问题]
obdiag gather scene run --scene=observer.long_transaction                                                          [long transaction]              [长事务]
obdiag gather scene run --scene=observer.memory                                                                    [memory problem]                [内存问题]
obdiag gather scene run --scene=observer.perf_sql --env "{db_connect='-hxx -Pxx -uxx -pxx -Dxx', trace_id='xx'}"   [SQL performance problem]       [SQL性能问题]
obdiag gather scene run --scene=observer.recovery                                                                  [recovery]                      [数据恢复问题]
obdiag gather scene run --scene=observer.restart                                                                   [restart]                       [observer无故重启]
obdiag gather scene run --scene=observer.rootservice_switch                                                        [rootservice switch]            [有主改选或者无主选举的切主]
obdiag gather scene run --scene=observer.sql_err --env "{db_connect='-hxx -Pxx -uxx -pxx -Dxx', trace_id='xx'}"    [SQL execution error]           [SQL 执行出错]
obdiag gather scene run --scene=observer.suspend_transaction                                                       [suspend transaction]           [悬挂事务]
obdiag gather scene run --scene=observer.unit_data_imbalance                                                       [unit data imbalance]           [unit迁移/缩小 副本不均衡问题]
obdiag gather scene run --scene=observer.unknown                                                                   [unknown problem]               [未能明确问题的场景]
---------------------------------------------------------------------------------------------------------------------------------------------------------------------

2.2 使用说明

运行如下命令即可一键采集某个场景下所有的故障信息

obdiag gather scene run --scene={SceneName}

--scene={SceneName}

SceneName 是对需要执行收集的场景

Example1:
obdiag gather scene run --scene=observer.unknown

选项说明如下:

选项名 是否必选 数据类型 默认值 说明
--scene string 默认为空 场景名,可以通过obdiag gather scene list 查看当前版本支持哪些场景
--from string 默认为空 日志收集的开始时间,格式为: yyyy-mm-dd hh:mm:ss,不需要加引号,例如 1970-01-01 12:00:00
--to string 默认为空 日志收集的结束时间,格式为: yyyy-mm-dd hh:mm:ss,不需要加引号,例如 1970-01-01 13:00:00
--since string 默认为空 日志收集最近的某段时间,格式为: \<n> <m|h|d>,其中,n 表示待输入的时间数字,m 表示分钟,h 表示小时,d 表示天,例如 30m表示收集最近 30 分钟的日志。
--env string 默认为空 部分场景需要额外的参数才能支持,统一放到了--env这个参数里边
--store_dir string 默认为命令执行的当前路径 存储结果的本地路径。
-c string ~/.obdiag/config.yml 配置文件路径

例子:

应用报错问题
obdiag gather scene run --scene=other.application_error

obproxy无故重启
obdiag gather scene run --scene=obproxy.restart

数据备份问题
obdiag gather scene run --scene=observer.backup

备份清理问题
obdiag gather scene run --scene=observer.backup_clean

clog盘满
obdiag gather scene run --scene=observer.clog_disk_full 

合并问题
obdiag gather scene run --scene=observer.compaction 

CPU高
obdiag gather scene run --scene=observer.cpu_high

主备库延迟
obdiag gather scene run --scene=observer.delay_of_primary_and_backup 

日志归档问题
obdiag gather scene run --scene=observer.log_archive

长事务
obdiag gather scene run --scene=observer.long_transaction 

内存问题
obdiag gather scene run --scene=observer.memory

SQL性能问题, 此处env中的trace_id对应gv$ob_sql_audit的trace_id
obdiag gather scene run --scene=observer.perf_sql --env "{db_connect='-hxx -Pxx -uxx -pxx -Dxx', trace_id='xx'}"   

数据恢复问题
obdiag gather scene run --scene=observer.recovery 

observer无故重启
obdiag gather scene run --scene=observer.restart  

有主改选或者无主选举的切主
obdiag gather scene run --scene=observer.rootservice_switch  

SQL 执行出错, 此处env中的trace_id对应gv$ob_sql_audit的trace_id
obdiag gather scene run --scene=observer.sql_err --env "{db_connect='-hxx -Pxx -uxx -pxx -Dxx', trace_id='xx'}"    

悬挂事务
obdiag gather scene run --scene=observer.suspend_transaction 

unit迁移/缩小 副本不均衡问题
obdiag gather scene run --scene=observer.unit_data_imbalance 

未能明确问题的场景
obdiag gather scene run --scene=observer.unknown

io问题
obdiag gather scene run --scene=observer.io

3. 自定义添加场景

场景化信息采集有两种方式:

  • yaml编排:通过yaml的方式进行采集项的编排,添加后执行器会按照编排顺序依次执行,采集所需要的信息。(适用于简单场景,普通用户都可添加)
  • hardcode方式:通过硬编码(写python脚本)的方式进行采集,流程自主控制,执行器执行的时候会自动跳转到hardcode模式进行采集。(需要下载obdiag源代码,新增后编译使用,适用于开发者)

3.1 yaml 编排添加场景

在用户目录下增加~/.obdiag/gather/tasks场景即可,注意:一个yaml对应一个场景, 如下:

.
├── obproxy
│   └── restart.yaml
├── observer
│   ├── backup_clean.yaml
│   ├── backup.yaml
│   ├── clog_disk_full.yaml
│   ├── cluster_down.yaml
│   ├── compaction.yaml
│   ├── delay_of_primary_and_backup.yaml
│   ├── io.yaml
│   ├── log_archive.yaml
│   ├── long_transaction.yaml
│   ├── memory.yaml
│   ├── recovery.yaml
│   ├── restart.yaml
│   ├── rootservice_switch.yaml
│   ├── suspend_transaction.yaml
│   ├── unit_data_imbalance.yaml
│   └── unknown.yaml
└── other
    └── application_error.yaml

可在observer增加一个~/.obdiag/gather/tasks/observer/test.yaml的场景

具体编写详情参见官网文档链接

例子:

info_en: "[io problem]"
info_cn: "[io问题]"
command: obdiag gather scene run --scene=observer.io
task:
  - version: "[2.0.0.0, 4.0.0.0]"
    steps:
      - type: sql
        sql: "show variables like 'version_comment';"
        global: true
      - type: sql
        sql: "SELECT * FROM oceanbase.v$ob_cluster"
        global: true
      - type: sql
        sql: "SELECT * FROM oceanbase.__all_zone WHERE name='idc';"
        global: true
      - type: sql
        sql: "select svr_ip,zone,with_rootserver,status,block_migrate_in_time,start_service_time,stop_time,build_version from oceanbase.__all_server order by zone;"
        global: true
      - type: sql
        sql: "SELECT zone, concat(svr_ip, ':', svr_port) observer, cpu_capacity, cpu_total, cpu_assigned, cpu_assigned_percent, mem_capacity, mem_total, mem_assigned, mem_assigned_percent, unit_Num, round(`load`, 2) `load`, round(cpu_weight, 2) cpu_weight, round(memory_weight, 2) mem_weight, leader_count FROM oceanbase.__all_virtual_server_stat ORDER BY zone,svr_ip;"
        global: true
      - type: sql
        sql: "select tenant_id,tenant_name,primary_zone,compatibility_mode from oceanbase.__all_tenant;"
        global: true
      - type: sql
        sql: "show parameters like '%syslog_level%';"
        global: true
      - type: sql
        sql: "show parameters like '%syslog_io_bandwidth_limit%';"
        global: true
      - type: sql
        sql: "select count(*),tenant_id,zone_list,unit_count from oceanbase.__all_resource_pool group by tenant_id,zone_list,unit_count;"
        global: true
      - type: ssh
        ssh: "df -h"
        global: false
      - type: ssh
        ssh: "cat /proc/sys/fs/aio-nr"
        global: false
      - type: ssh
        ssh: "cat /proc/sys/fs/aio-max-nr"
        global: false
      - type: log
        global: false
        grep: "IO"
      - type: sysstat
        global: false
        sysstat: ""
  - version: "[4.0.0.0, *]"
    steps:
      - type: sql
        sql: "show variables like 'version_comment';"
        global: true
      - type: sql
        sql: "SELECT * FROM oceanbase.DBA_OB_ZONES;"
        global: true
      - type: sql
        sql: "SELECT * FROM oceanbase.DBA_OB_SERVERS;"
        global: true
      - type: sql
        sql: "SELECT * FROM oceanbase.GV$OB_SERVERS;"
        global: true
      - type: sql
        sql: "SELECT * FROM oceanbase.DBA_OB_UNIT_CONFIGS;"
        global: true
      - type: sql
        sql: "SELECT * FROM oceanbase.DBA_OB_RESOURCE_POOLS;"
        global: true
      - type: sql
        sql: "SELECT * FROM oceanbase.DBA_OB_TENANTS;"
        global: true
      - type: sql
        sql: "SELECT c.TENANT_ID, e.TENANT_NAME, concat(c.NAME, ': ', d.NAME) `pool:conf`,concat(c.UNIT_COUNT, ' unit: ', d.min_cpu, 'C/', ROUND(d.MEMORY_SIZE/1024/1024/1024,0), 'G') unit_info FROM oceanbase.DBA_OB_RESOURCE_POOLS c, oceanbase.DBA_OB_UNIT_CONFIGS d, oceanbase.DBA_OB_TENANTS e WHERE c.UNIT_CONFIG_ID=d.UNIT_CONFIG_ID AND c.TENANT_ID=e.TENANT_ID AND c.TENANT_ID>1000 ORDER BY c.TENANT_ID;"
        global: true
      - type: sql
        sql: "SELECT a.TENANT_NAME,a.TENANT_ID,b.SVR_IP FROM oceanbase.DBA_OB_TENANTS a, oceanbase.GV$OB_UNITS b WHERE a.TENANT_ID=b.TENANT_ID;"
        global: true
      - type: sql
        sql: "show parameters like '%syslog_level%';"
        global: true
      - type: sql
        sql: "show parameters like '%syslog_io_bandwidth_limit%';"
        global: true
      - type: sql
        sql: "select * from __all_virtual_io_quota limit 20"
        global: true
      - type: ssh
        ssh: "df -h"
        global: false
      - type: ssh
        ssh: "cat /proc/sys/fs/aio-nr"
        global: false
      - type: ssh
        ssh: "cat /proc/sys/fs/aio-max-nr"
        global: false
      - type: log
        global: false
        grep: "IO"
      - type: sysstat
        global: false
        sysstat: ""

3.2 硬编码添加场景

源代码下载: GitHub - oceanbase/oceanbase-diagnostic-tool: OceanBase Diagnostic Tool is designed to help OceanBase users quickly gather necessary information and analyze the cause of the problem.

开发者在该目录下增加{project_dir}/handler/gather/scene场景, 建议一个场景一个.py文件。

│   ├── gather/ 一键收集功能
│   │   ├── gather_awr.py awr报告收集代码
│   │   ├── gather_log.py 日志收集代码
│   │   ├── gather_obadmin.py 解析clog/slog的代码
│   │   ├── gather_obproxy_log.py 收集obproxy代码
│   │   ├── gather_obstack2.py 收集堆栈信息的代码
│   │   ├── gather_perf.py 收集火焰图的代码
│   │   ├── gather_plan_monitor.py 收集并行SQL的代码
│   │   ├── gather_scenes.py 场景化收集的入口代码
│   │   ├── gather_sysstat.py 收集主机信息的代码
│   │   ├── scenes/ 场景化信息采集的处理代码
│   │   │   ├── base.py
│   │   │   ├── cpu_high.py cpu高场景
│   │   │   ├── list.py 场景列表展示的代码
│   │   │   ├── register.py 硬编码场景注册代码
│   │   │   └── sql_problem.py sql问题采集的代码
│   │   ├── step/ 场景化采集的执行器
│   │   │   ├── base.py 
│   │   │   ├── sql.py sql执行器
│   │   │   └── ssh.py ssh执行器
│   │   └── tasks/ 收集场景的yaml文件
3.2.1 模版
#!/usr/bin/env python
# -*- coding: UTF-8 -*
# Copyright (c) 2022 OceanBase
# OceanBase Diagnostic Tool is licensed under Mulan PSL v2.
# You can use this software according to the terms and conditions of the Mulan PSL v2.
# You may obtain a copy of Mulan PSL v2 at:
#          http://license.coscl.org.cn/MulanPSL2
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
# See the Mulan PSL v2 for more details.

"""
@file: test.py
@desc:
"""

class TestScene(object):
    def __init__(self, nodes, cluster, report_path, task_variable_dict=None, args=None, env={}):
        if task_variable_dict is None:
            self.task_variable_dict = {}
        else:
            self.task_variable_dict = task_variable_dict
        self.nodes = nodes
        self.cluster = cluster
        self.report_path = report_path
        self.args = args
        self.env = env
        self.is_ssh = True

    def execute(self): # 执行函数
        pass

    def xxx(self):
        pass
3.2.2 例子
#!/usr/bin/env python
# -*- coding: UTF-8 -*
# Copyright (c) 2022 OceanBase
# OceanBase Diagnostic Tool is licensed under Mulan PSL v2.
# You can use this software according to the terms and conditions of the Mulan PSL v2.
# You may obtain a copy of Mulan PSL v2 at:
#          http://license.coscl.org.cn/MulanPSL2
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
# See the Mulan PSL v2 for more details.

"""
@file: test.py
@desc:
"""
import os
from utils.shell_utils import SshHelper
from common.logger import logger
from handler.gather.gather_obstack2 import GatherObstack2Handler
from handler.gather.gather_perf import GatherPerfHandler

class TestScene(object):
    def __init__(self, nodes, cluster, report_path, task_variable_dict=None, args=None, env={}):
        if task_variable_dict is None:
            self.task_variable_dict = {}
        else:
            self.task_variable_dict = task_variable_dict
        self.nodes = nodes
        self.cluster = cluster
        self.report_path = report_path
        self.args = args
        self.env = env
        self.is_ssh = True

    def execute(self): # 执行函数
        self.__gather_obstack() # 例
        self.__gather_perf()
        self.__gather_cmd_info()

    def __gather_obstack(self):
        logger.info("gather obstack start")
        obstack = GatherObstack2Handler(nodes=self.nodes, gather_pack_dir=self.report_path, is_scene=True)
        obstack.handle(self.args)
        logger.info("gather obstack end")

    def __gather_perf(self):
        logger.info("gather perf start")
        perf = GatherPerfHandler(nodes=self.nodes, gather_pack_dir=self.report_path, is_scene=True)
        self.args = ParserAction.add_attribute_to_namespace(self.args, 'scope', "all")
        perf.handle(self.args)
        logger.info("gather perf end")

4. 附录

|-----|----------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 第一篇 | 如何修炼成"神医"------《OceanBase诊断系列》之一 |
| 第二篇 | 走进SQL审计视图------《OceanBase诊断系列》之二 |
| 第三篇 | 快速收集诊断信息,敏捷诊断工具obdiag应用实践------《OceanBase诊断系列》之三 |
| 第四篇 | 如何快速分析OB集群日志,敏捷诊断工具obdiag分析能力实践------《OceanBase诊断系列》之四 |
| 第五篇 | 防患未然,OceanBase巡检工具应用实践------《OceanBase诊断系列》之五 |
| 第六篇 | obdiag帮你读懂全链路诊断日志------《OceanBase诊断系列》之六 |
| 第七篇 | 如何排查合并问题------《OceanBase诊断系列》之七 |
| 第八篇 | 轻松掌握锁冲突问题的排查方法------《OceanBase诊断系列》之八 |
| 第九篇 | obdiag如何实现一键采集20+故障场景的诊断信息------《OceanBase诊断系列》之九 |

相关推荐
OceanBase数据库官方博客1 天前
OceanBase 中常用的查询语句
sql·oceanbase·分布式数据库·查询语句
OceanBase数据库官方博客4 天前
如何解决JAVA程序通过obloader并发导数导致系统夯住的问题 | OceanBase 运维实践
java·运维·oceanbase·分布式数据库
OceanBase数据库官方博客4 天前
如何配置 Flink CDC 连接 OceanBase 实现数据实时同步
大数据·flink·oceanbase·分布式数据库
OceanBase数据库官方博客4 天前
如何实现主备租户的无缝切换 | OceanBase应用实践
oceanbase·分布式数据库·高可用
靖顺6 天前
【OceanBase 诊断调优】—— ocp上针对OB租户CPU消耗计算逻辑
oceanbase
一名数据库爱好者6 天前
OceanBase 闪回查询
数据库·oceanbase·dba
OceanBase数据库官方博客6 天前
ODC 如何精确呈现SQL耗时 | OceanBase 开发者工具解析
sql·oceanbase·分布式数据库·开发者·生态工具
一名数据库爱好者7 天前
OceanBase单表恢复(4.2.1.8)
adb·oceanbase
靖顺7 天前
【OceanBase 诊断调优】—— OceanBase 数据库统计信息被禁用,状态为 broken 的原因和解决方法
数据库·oceanbase
OceanBase数据库官方博客10 天前
如何在 Ubuntu 上 部署 OceanBase
ubuntu·oceanbase·分布式数据库·安装部署