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 查询改写
sql·oceanbase·分布式数据库
OceanBase数据库官方博客2 天前
解析在OceanBase创建分区的常见问题|OceanBase 用户问题精粹
oceanbase·分布式数据库·分区
OceanBase数据库官方博客2 天前
半连接转内连接规则的原理与代码解析 |OceanBase查询优化
sql·oceanbase·分布式数据库
IT培训中心-竺老师4 天前
OceanBase 数据库分布式与集中式 能力
数据库·分布式·oceanbase
靖顺5 天前
【OceanBase 诊断调优】—— OceanBase 数据库网络速率配置方案
网络·数据库·oceanbase
尚雷558012 天前
OceanBase 社区版 4.0 离线方式升级bp1至bp2 指南(含避坑总结)
oceanbase
五月高高12 天前
Linux部署oceanbase
linux·oceanbase
靖顺16 天前
【OceanBase 诊断调优】—— 统计信息自动收集超时导致的估行不准 SQL 选择错索引
数据库·sql·oceanbase
it界的哈士奇16 天前
Oceanbase离线集群部署
oceanbase