进程崩溃难以定位,日志分析五步搞定|OceanBase故障排查实践

作者:胡呈清,爱可生 DBA 团队成员,擅长故障分析、性能优化。

背景

Server 进程崩溃的常见原因包括程序bug、文件损坏、磁盘坏块以及内存坏块,这类故障通常较难分析和定位。

在OceanBase 集群部署时,系统会自动配置coredump文件。一旦 OBServer进程崩溃,就会自动生成coredump文件,该文件能够捕获进程崩溃时的内存状态。它包含了程序失败时的状态快照以及所有线程的堆栈信息,适合用于调试,也是分析崩溃问题的有力工具。

但某些时候,coredump 文件 不一定能顺利生成,这个时候就需要从 observer.log 中获取崩溃时的堆栈,分析崩溃位置的代码,以此来寻找原因。本文介绍的就是这个方法。

本文的方法适用于 OceanBase 的所有版本。

分析步骤

1. 找到 Crash 日志

OBServer 在 Crash 后会在 observer.log 里打这么一段类似的日志,基本上你只要去搜索 “CRASH ERROR” 关键字就行:

CRASH ERROR!!! sig=11, sig_code=2, \
sig_addr=7f3edd31dffb, timestamp=1725496052323606, \
tid=57605, tname=TNT_L0_1002, \
trace_id=20970917872454-1707004480400037, \
extra_info=((null)), lbt=0x9baead8 \
0x9b9f358 0x7f43d58e562f \
0x7f43d52525fc 0x95eeda9 \
0x95ec568 0x95e6c0c \
0x95e4c33 0x9cbf4c7 \
0x93be9ee 0x939e320 \
0x93bd64e 0x939c105 \
0x939c6e6 0x2cff1c1 \
0x9918a74 0x9917461 0x9913f1e

这里手动增加换行,提高阅读性

2. 得到崩溃的线程堆栈

堆栈信息可以通过解析内存地址得到(每个内存地址对应一个栈桢):

addr2line -pCfe /home/admin/oceanbase/bin/observer \
0x9baead8 0x9b9f358 0x7f43d58e562f 0x7f43d52525fc \
0x95eeda9 0x95ec568 0x95e6c0c 0x95e4c33 0x9cbf4c7 \
0x93be9ee 0x939e320 0x93bd64e 0x939c105 0x939c6e6 \
0x2cff1c1 0x9918a74 0x9917461 0x9913f1e

这里手动增加换行,提高阅读性

输出如下:

  • 堆栈信息是从下往上看,最上面 4 行是处理 Crash 的固定栈(不用管)
  • 崩溃的位置在第 5 行 ObMPStmtExecute::copy_or_convert_str 这个函数
safe_backtrace at ??:?
oceanbase::common::coredump_cb(int, siginfo_t*) at ??:?
?? ??:0
?? ??:0
oceanbase::observer::ObMPStmtExecute::copy_or_convert_str(oceanbase::common::ObIAllocator&, oceanbase::common::ObCollationType, oceanbase::common::ObCollationType, oceanbase::common::ObString const&, oceanbase::common::ObString&, long) at ??:?
oceanbase::observer::ObMPStmtExecute::parse_basic_param_value(oceanbase::common::ObIAllocator&, unsigned int, oceanbase::common::ObCharsetType, oceanbase::common::ObCollationType, oceanbase::common::ObCollationType, char const*&, oceanbase::common::ObTimeZoneInfo const*, oceanbase::common::ObObj&) at ??:?
oceanbase::observer::ObMPStmtExecute::parse_param_value(oceanbase::common::ObIAllocator&, unsigned int, oceanbase::common::ObCharsetType, oceanbase::common::ObCollationType, oceanbase::common::ObCollationType, char const*&, oceanbase::common::ObTimeZoneInfo const*, oceanbase::sql::TypeInfo*, oceanbase::sql::TypeInfo*, oceanbase::common::ObObjParam&, short) at ??:?
oceanbase::observer::ObMPStmtExecute::before_process() at ??:?
oceanbase::rpc::frame::ObReqProcessor::run() at ??:?
oceanbase::omt::ObWorkerProcessor::process_one(oceanbase::rpc::ObRequest&, int&) at ??:?
oceanbase::omt::ObWorkerProcessor::process(oceanbase::rpc::ObRequest&) at ??:?
oceanbase::omt::ObThWorker::process_request(oceanbase::rpc::ObRequest&) at ??:?
oceanbase::omt::ObThWorker::worker(long&, long&, int&) at ??:?
non-virtual thunk to oceanbase::omt::ObThWorker::run(long) at ??:?
oceanbase::lib::CoKThreadTemp<oceanbase::lib::CoUserThreadTemp<oceanbase::lib::CoSetSched> >::start()::{lambda()#1}::operator()() const at ??:?
oceanbase::lib::CoSetSched::Worker::run() at ??:?
oceanbase::lib::CoRoutine::__start(boost::context::detail::transfer_t) at ??:?
trampoline at safe_snprintf.c:?

3. 获取崩溃点具体的代码位置

如何确认具体执行到 ObMPStmtExecute::copy_or_convert_str 函数的哪一行?需要在 debug 版本上使用 gdb (要求不低于 9.0 版本)来解析内存地址:

##下载对应版本的 debug 安装包(企业版需要问官方获取)
https://mirrors.aliyun.com/oceanbase/community/stable/el/7/x86_64/##安装debug包
rpm2cpio oceanbase-ce-debuginfo-3.1.5-100010012023060910.el7.x86_64.rpm |cpio -div##然后用gdb打开二进制文件
gdb ./usr/lib/debug/home/admin/oceanbase/bin/observer.debug##解析内存地址
(gdb) list *0x95eeda9
0x95eeda9 is in oceanbase::observer::ObMPStmtExecute::copy_or_convert_str(oceanbase::common::ObIAllocator&, oceanbase::common::ObCollationType, oceanbase::common::ObCollationType, oceanbase::common::ObString const&, oceanbase::common::ObString&, long) (./src/observer/mysql/obmp_stmt_execute.cpp:1428).
(gdb) list *0x95ec568
0x95ec568 is in oceanbase::observer::ObMPStmtExecute::parse_basic_param_value(oceanbase::common::ObIAllocator&, unsigned int, oceanbase::common::ObCharsetType, oceanbase::common::ObCollationType, oceanbase::common::ObCollationType, char const*&, oceanbase::common::ObTimeZoneInfo const*, oceanbase::common::ObObj&) (./src/observer/mysql/obmp_stmt_execute.cpp:1237).
(gdb) list *0x95e6c0c
0x95e6c0c is in oceanbase::observer::ObMPStmtExecute::parse_param_value(oceanbase::common::ObIAllocator&, unsigned int, oceanbase::common::ObCharsetType, oceanbase::common::ObCollationType, oceanbase::common::ObCollationType, char const*&, oceanbase::common::ObTimeZoneInfo const*, oceanbase::sql::TypeInfo*, oceanbase::sql::TypeInfo*, oceanbase::common::ObObjParam&, short) (./src/observer/mysql/obmp_stmt_execute.cpp:1372).
(gdb) list *0x95e4c33
0x95e4c33 is in oceanbase::observer::ObMPStmtExecute::before_process() (./src/observer/mysql/obmp_stmt_execute.cpp:512).
507    in ./src/observer/mysql/obmp_stmt_execute.cpp

拓展阅读:

本案例的调用栈为:

...
->ObMPStmtExecute::before_process() 
-->ObMPStmtExecute::parse_param_value(oceanbase::common::ObIAllocator&, unsigned int, oceanbase::common::ObCharsetType, oceanbase::common::ObCollationType, oceanbase::common::ObCollationType, char const*&, oceanbase::common::ObTimeZoneInfo const*, oceanbase::sql::TypeInfo*, oceanbase::sql::TypeInfo*, oceanbase::common::ObObjParam&, short)
--->ObMPStmtExecute::parse_basic_param_value(oceanbase::common::ObIAllocator&, unsigned int, oceanbase::common::ObCharsetType, oceanbase::common::ObCollationType, oceanbase::common::ObCollationType, char const*&, oceanbase::common::ObTimeZoneInfo const*, oceanbase::common::ObObj&)
---->ObMPStmtExecute::copy_or_convert_str(oceanbase::common::ObIAllocator&, oceanbase::common::ObCollationType, oceanbase::common::ObCollationType, oceanbase::common::ObString const&, oceanbase::common::ObString&, long) 

4. 代码分析

最后崩溃在 ObMPStmtExecute::copy_or_convert_str 函数,代码位置 obmp_stmt_execute.cpp:1428

在该文件的第 1428 行

函数的作用

ObMPStmtExecute::copy_or_convert_str 函数的主要功能是根据给定的字符集类型,将输入的字符串 src (statement协议里的请求参数)进行复制或字符集转换,并将结果保存在 out 中。崩溃信息中 sig=11,也就是 signal 11,表示程序访问了无效的内存地址,通常是由于空指针引用或者访问了已经释放的内存。

崩溃位置代码 MEMCPY(buf + extra_buf_len, src.ptr(), src.length()); 意思是:通过 MEMCPY 函数将源字符串的内容复制到分配的内存区域中:

  • buf + extra_buf_len :复制时目标地址是缓冲区指针 buf 的偏移地址(加上 extra_buf_len)。
  • src.ptr() :源字符串的指针。
  • src.length() :源字符串的长度,表示要复制的字节数。

所以这里基本可以确认 src.ptr() 是个空指针,如果有 coredump 文件,只需要用 gdb 打印一下这个指针变量就知道了。

5. 搜索知识库

然后带着 copy_or_convert_str 关键字(也就是崩溃的那个函数)搜一下官方的知识库,找到对应了的 bug。

崩溃位置的这段代码的逻辑与 bug 描述吻合:在处理 execute 协议时,send long data 协议还没有把 param_data 信息处理完,因此 execute 协议在转换 param_data时读到了空指针,引发了 crash。

小结

通常,按照以上五个步骤对日志进行分析,可以快速定位导致 OBServer 进程 Crash 的原因。希望本文对你有所帮助~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/59685.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[spring源码]spring配置类解析

解析配置类 在启动Spring时&#xff0c;需要传入一个AppConfig.class给ApplicationContext&#xff0c;ApplicationContext会根据AppConfig类封装为一个BeanDefinition&#xff0c;这种BeanDefinition我们把它称为配置类BeanDefinition AnnotationConfigApplicationContext a…

低压电容器衰减的计算方法

低压电容器的衰减&#xff08;通常指电容器容量的衰减&#xff09;是指电容器在长时间运行或经历一些不良工作环境下&#xff0c;电容值随时间逐渐减少的现象。这个衰减会影响电容器的工作性能&#xff0c;尤其是在无功补偿和功率因数校正等应用中。计算电容器衰减的具体方法可…

Maven的安装配置

文章目录 一、MVN 的下载二、配置maven2.1、更改maven/conf/settings.xml配置2.2、配置环境变量一、MVN 的下载 还是那句话,要去就去官网或者github,别的地方不要去下载。我们下载binaries/ 目录下的 cd /opt/server wget https://downloads.apache.org/maven/maven-3/3.9.6/…

构建Java教学新生态:SpringBoot应用实例

2相关技术 2.1 MYSQL数据库 MySQL是一个真正的多用户、多线程SQL数据库服务器。 是基于SQL的客户/服务器模式的关系数据库管理系统&#xff0c;它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等&#xff0c;非常…

ctfshow(316)--XSS漏洞--反射性XSS

Web316 进入界面&#xff1a; 审计 显示是关于反射性XSS的题目。 思路 首先想到利用XSS平台解题&#xff0c;看其他师傅的wp提示flag是在cookie中。 当前页面的cookie是flagyou%20are%20not%20admin%20no%20flag。 但是这里我使用XSS平台&#xff0c;显示的cookie还是这样…

【设计模式系列】建造者模式(十)

目录 一、什么是建造者模式 二、建造者模式的角色 三、建造者模式的典型应用 四、建造者模式在StringBuilder中的应用 五、典型建造者模式的案例 一、什么是建造者模式 建造者模式&#xff08;Builder Pattern&#xff09;是一种创建型设计模式&#xff0c;用于构建复杂对…

NVR批量管理软件/平台EasyNVR多个NVR同时管理的智能化革新

随着安防监控技术的不断进步和普及&#xff0c;视频监控系统在各行各业中的应用愈发广泛。无论是大型企业、工业园区&#xff0c;还是公共场所、住宅小区&#xff0c;视频监控都成为了保障安全、提升管理效率的重要手段。 NVR批量管理软件/平台EasyNVR&#xff0c;作为一款集多…

【公司新闻】实力出圈!开放传神(OpenCSG)登上《IT时报》!

2024年11月1日&#xff08;星期五&#xff09;&#xff0c;《IT时报》刊登了关于开放传神&#xff08;以下简称&#xff1a;OpenCSG&#xff09;的新闻内容&#xff0c;这期报道究竟揭示了哪些亮点&#xff1f;让我们一起来深入了解。 来源&#xff1a;《 IT时报 》 本报记者 &…

python的安装环境Miniconda(Conda 命令管理依赖配置)

这一段时间&#xff0c;对AI大模型 有了兴趣就想研究一下。 在研究之前肯定要先把需要的编程技能掌握了。经过我查阅资料&#xff0c;今天就先学一下 python的 环境安装。 Node.js 包管理工具&#xff1a;npm 依赖配置文件&#xff1a;package.json 环境管理&#xff1a;nvm&am…

初级图像处理工具

图像处理-初级 1、功能概览 初级图像处理工具旨在为用户提供一个易于使用的界面来执行常见的图像处理任务。该工具集成了多项实用功能&#xff0c;从显示和调整图像的基本属性到应用各种滤镜效果&#xff0c;用户都可以通过简单的命令行交互来完成。 我们的初级图像处理工具…

【docker】5. 背景知识(了解)

Docker 是什么 Docker 本质 Docker 本质其实是 LXC 之类的增强版&#xff0c;它本身不是容器&#xff0c;而是容器的易用工具。容器是 linux 内核中的技术&#xff0c;Docker 只是把这种技术在使用上简易普及了。Docker 在早期的版本其核心就是 LXC 的二次封装发行版。 Docke…

【react框架之dvajs】如何创建一个初始的dva项目工程

dvajs作为react的框架&#xff0c;一度火爆市场&#xff0c;只是新框架层出不穷&#xff0c;也是越做越成熟了&#xff0c;很多老的框架被淹没&#xff0c;使用的越来越少。dva框架还是有不少的公司有项目在使用&#xff01; dva项目的搭建步骤 在系统检测是否安装了dva&…

5分钟科普:AI网关是什么?应用场景是什么?有没有开源的选择?

AI网关的功能及其定义 AI网关位于企业应用与内外部大模型调用的交汇点&#xff0c;能够灵活地将请求转发给内部自建模型或外部大模型服务提供商&#xff0c;甚至海外的服务商。它管理着企业所有的AI出口流量&#xff0c;为企业内的不同团队提供了多方面的优势。 对于开发团队…

Spring中的 InitializingBean、BeanPostProcessor、@PostConstruct 等初始化动作的执行时机分析

初始化Bean的时序图如下&#xff1a; 小结说明&#xff1a; 1、相同点&#xff1a;InitializingBean 的(afterPropertiesSet方法)、BeanPostProcessor、PostConstruct 都是在bean的属性注入完毕之后才执行&#xff0c;都可以用来进行bean的初始化动作 2、初始化执行顺序优先级…

java ssm 校园快递物流平台 校园快递管理系统 物流管理 源码 jsp

一、项目简介 本项目是一套基于SSM的校园快递物流平台&#xff0c;主要针对计算机相关专业的和需要项目实战练习的Java学习者。 包含&#xff1a;项目源码、数据库脚本、软件工具等。 项目都经过严格调试&#xff0c;确保可以运行&#xff01; 二、技术实现 ​后端技术&#x…

最新整理:Selenium自动化测试面试题

1.selenium中如何判断元素是否存在? find_elements查找到的元素个数为0&#xff0c;find_element报错意味着元素不存在 2.如何判断元素是否出现? 判断元素是否出现&#xff0c;存在两种情况&#xff0c;一种是该元素压根就没有&#xff0c;自然不会出现;另外一种是有这样的…

【The Art of Unit Testing 3_自学笔记06】3.4 + 3.5 单元测试核心技能之:函数式注入与模块化注入的解决方案简介

文章目录 3.4 函数式依赖注入技术 Functional injection techniques3.5 模块化依赖注入技术 Modular injection techniques 写在前面 上一篇的最后部分对第三章后续内容做了一个概括性的梳理&#xff0c;并给出了断开依赖项的最简单的实现方案&#xff0c;函数参数值注入法。本…

用Puppeteer点击与数据爬取:实现动态网页交互

用Puppeteer与代理IP抓取51job招聘信息&#xff1a;动态网页交互与数据分析 引言 在数据采集领域&#xff0c;传统的静态网页爬虫方式难以应对动态加载的网页内容。动态网页通常依赖JavaScript加载数据&#xff0c;用户需要与页面交互才能触发内容显示。因此&#xff0c;我们…

10天进阶webpack---(1)为什么要有webpack

首先就是我们的代码是运行在浏览器上的&#xff0c;但是我们开发大多都是利用node进行开发的&#xff0c;在浏览器中并没有node提供的那些环境。这就造成了运行和开发上的不同步问题。 -----引言 浏览器模块化的问题&#xff1a; 效率问题&#xff1a;精细的模块划分带来了更…

Qt多边形填充/不填充绘制

1 填充多边形绘制形式 void GraphicsPolygonItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) {Q_UNUSED(option);Q_UNUSED(widget);//painter->setPen(pen()); // 设置默认画笔//painter->setBrush(brush()); // 设置默…