openGauss3.1.0 版本的gs_stack功能解密
openGauss3.1.0 版本的 gs_stack 功能解密
不管是测试还是研发,工作中总有遇到各种各样的问题。比如,你有没有遇到过在数据库中执行某个 SQL,却一直不返回结果,这时候的你是不是非常想看一下代码执行到了哪个函数?或者是数据库不响应连接,需要查看数据库当前线程的执行情况呢?
在实际生产中,获取生产系统进程堆栈比较麻烦,需要在服务端后台执行 gstack 命令。本期主要介绍内置 gs_stack 工具,可以通过函数调用的方式输出指定线程的堆栈,用于解决现网环境缺少 gs_stack 工具,无法获取调用栈的问题。
内置 gs_stack 工具介绍
在 openGauss 的很多客户场景中,gdb、gstack 等工具都是无法使用的,当系统出现 hang、慢等问题时,无法通过调用栈进行进一步的定位。还有一种情况就是登录客户数据库的流程非常繁杂,需要经过层层审批,这时通过 gsql 等工具连接数据库就相对容易一些。针对以上痛点,通过复用 openGauss 未使用操作系统信号,并在信号处理函数中获取调用栈的方式开发了调用栈工具,以获得服务端 openGauss 的调用栈。
获取调用栈主要包含两种方式,一种是通过执行 SQL 语句获取,另一种是通过 gs_ctl 工具执行命令获取~
1、在客户端工具执行 gs_stack([tid])函数
使用具有monadmin或者sysadmin用户权限的用户,通过 gsql 或者其他工具连接数据库;
执行命令:
openGuass=# select * from gs_stack();
返回当前 openGauss 所有线程的调用栈:
tid | lwtid | stack
---------------+------ +------------------------------------------------------------------
14026731434848 | 2626 | _poll + 0x2d +
| | WaitLatch0rSocket(Latch volatile,int,int,long) + 0x29f +
| | WaitLatch(Latch voatile,int,long) + 0x2e +
| | start_thread +oxc5 +
| | clone + OXC5 +
140116075071232| 23864 |__poll + 0x2d + | | poll + 0x81 +
| | WaitLatchOrSocket(Latch volatile, int, int, long) + 0x6af +
| | WaitLatch(Latch volatile, int, long) + 0x2e +
| | ckpt_pagewriter_sub_thread_loop() + 0x284 +
| | ckpt_pagewriter_main() + 0x92e +
| | int GaussDbAuxiliaryThreadMain<(knl_thread_role)46>(knl_thread_arg) + 0x482 +
| | int GaussDbThreadMain<(knl_thread_role)46>(knl_thread_arg) + 0x854 +
| | InternalThreadFunc(void) + 0x5c +
| | ThreadStarterFunc(void) + 0xa4 +
| | start_thread + 0xc5 +
| | clone + 0x6d +
只需要查看某一个线程的调用栈时,执行命令:
openGuass=# select gs_stack(xxx);
xxx 为为某个线程的 thread_id,能够返回 thread_id 为 xxx 的线程的调用栈:
gs_stack
pthread_sigmask + 0x2a +
gs_signal_recover_mask(__sigset_t) + 0x17 +
gs_signal_send(unsigned long, int, int) + 0x2f9 +
signal_child(unsigned long, int, int) + 0x36 +
get_stack_according_to_tid(unsigned long, StringInfoData) + 0x191 +
gs_stack(FunctionCallInfoData) + 0xcb +
unsigned long ExecMakeFunctionResult<false, false, true>(FuncExprState, ExprContext, bool, ExprDoneCond) + 0x554 +
ExecEvalFunc(FuncExprState, ExprContext, bool, ExprDoneCond) + 0x147 +
ExecTargetList(List, ExprContext, unsigned long, bool, ExprDoneCond, ExprDoneCond) + 0x15d +
ExecProject(ProjectionInfo, ExprDoneCond) + 0x40f +
ExecResult(ResultState) + 0x1da +
ExecResultWrap(PlanState) + 0x18 +
ExecProcNode(PlanState) + 0xde +
ExecutePlan(EState, PlanState, CmdType, bool, long, ScanDirection, _DestReceiver) + 0x1a6 +
standard_ExecutorRun(QueryDesc, ScanDirection, long) + 0x3d9 +
explain_ExecutorRun(QueryDesc, ScanDirection, long) + 0x109 +
ExecutorRun(QueryDesc, ScanDirection, long) + 0x1ad +
PortalRunSelect(PortalData, bool, long, _DestReceiver) + 0x294 +
PortalRun(PortalData, long, bool, _DestReceiver, _DestReceiver, char) + 0x62e +
exec_simple_query(char const, MessageType, StringInfoData) + 0x12b0 +
PostgresMain(int, char**, char const, char const) + 0x2e10 +
BackendRun(Port) + 0x327 +
int GaussDbThreadMain<(knl_thread_role)1>(knl_thread_arg) + 0x5a8 +
InternalThreadFunc(void) + 0x2d +
ThreadStarterFunc(void*) + 0xa4 +
start_thread + 0xc5 +
clone + 0x6d +
openGauss=# select gs_stack(140115727259392);
gs_stack
__select + 0x33 +
pg_usleep(long) + 0xa1 +
pg_sleep(FunctionCallInfoData) + 0xeb +
unsigned long ExecMakeFunctionResultNoSets<false, false>(FuncExprState, ExprContext, bool, ExprDoneCond) + 0x206f +
ExecEvalFunc(FuncExprState, ExprContext, bool, ExprDoneCond) + 0x622 +
ExecTargetList(List, ExprContext, unsigned long, bool, ExprDoneCond, ExprDoneCond) + 0x45d +
ExecProject(ProjectionInfo, ExprDoneCond) + 0xc2d +
ExecResult(ResultState) + 0x79b +
ExecResultWrap(PlanState) + 0x18 +
ExecProcNode(PlanState) + 0x2db +
ExecutePlan(EState, PlanState, CmdType, bool, long, ScanDirection, _DestReceiver) + 0x765 +
standard_ExecutorRun(QueryDesc, ScanDirection, long) + 0xbb5 +
explain_ExecutorRun(QueryDesc, ScanDirection, long) + 0x1f7 +
ExecutorRun(QueryDesc, ScanDirection, long) + 0x947 +
PortalRunSelect(PortalData, bool, long, _DestReceiver) + 0x7d2 +
PortalRun(PortalData, long, bool, _DestReceiver, _DestReceiver, char) + 0xe11 +
exec_simple_query(char const, MessageType, StringInfoData) + 0x3929 +
PostgresMain(int, char**, char const, char const) + 0x61f8 +
BackendRun(Port) + 0x64d +
int GaussDbThreadMain<(knl_thread_role)1>(knl_thread_arg) + 0x9c7 +
InternalThreadFunc(void) + 0x5c +
ThreadStarterFunc(void) + 0xa4 +
start_thread + 0xc5 +
clone + 0x6d +
2、在服务器端使用 gs_ctl stack –D data_dir 命令
当线程池满,无法通过 gsql 连接数据库的时候,可以使用 gs_ctl 工具执行命令获取线程调用栈:
使用集群用户登录服务器,执行命令 gs_ctl stack –D data_dir,data_dir 是指定 gaussdb 的数据目录的绝对路径:
gs_ctl stack –D /path/to/install/data/
可以取 gaussdb 所有线程的调用栈。
[user@euler omm]$ gs_ctl stack -D /path/to/install/data/opengauss
[2022-11-03 20:17:59.288][19256][][gs_ctl]: gs_stack start:
Thread 0 tid<140120252633600> lwtid<23675>
__poll + 0x2d
poll + 0x81
CommWaitPollParam::caller(int ()(pollfd, unsigned long, int), unsigned long) + 0xb1
int comm_socket_call<CommWaitPollParam, int ()(pollfd, unsigned long, int)>(CommWaitPollParam, int ()(pollfd, unsigned long, int)) + 0x28
comm_poll(pollfd, unsigned long, int) + 0x388
ServerLoop() + 0xb77
PostmasterMain(int, char**) + 0x612e
main + 0xaeb
__libc_start_main + 0xf5
0x55feac9a9907
Thread 1 tid<140116236076800> lwtid<23848>
__poll + 0x2d
poll + 0x81
WaitLatchOrSocket(Latch volatile, int, int, long) + 0x6af
SysLoggerMain(int) + 0x17c9
int GaussDbThreadMain<(knl_thread_role)17>(knl_thread_arg) + 0x860
InternalThreadFunc(void) + 0x5c
ThreadStarterFunc(void) + 0xa4
start_thread + 0xc5
clone + 0x6d
只需要查看某一个线程的调用栈时,执行命令:
gs_ctl stack –D data_dir –I xx
data_dir 是指定 gaussdb 的数据目录的绝对路径,xxx 指的是线程的 lwpid(taskid),可以通过 top –Hp 的方式获取线程的 lwpid, 也可以通过 cat /proc/yyyy/task 获取线程的 lwpid 。yyyy 指的是进程 id,可以通过 ps –ux | grep gaussdb 获取。
[uesr@euler omm]$ gs_ctl stack -D /path/to/install/data -I 23860
[2022-11-03 20:22:01.327][40608][][gs_ctl]: gs_stack start:
tid<140116142843648> lwtid<23860>
__poll + 0x2d
poll + 0x81
WaitLatchOrSocket(Latch volatile, int, int, long) + 0x6af
WaitLatch(Latch volatile, int, long) + 0x2e
ckpt_pagewriter_sub_thread_loop() + 0x284
ckpt_pagewriter_main() + 0x92e
int GaussDbAuxiliaryThreadMain<(knl_thread_role)46>(knl_thread_arg) + 0x482
int GaussDbThreadMain<(knl_thread_role)46>(knl_thread_arg) + 0x854
InternalThreadFunc(void) + 0x5c
ThreadStarterFunc(void) + 0xa4
start_thread + 0xc5
clone + 0x6d
总结
通过以上我们介绍的 openGauss 的 gs_stack 功能,我们可以很方便地定位某个 openGauss 线程正在做的事情,并可以根据这些函数调用情况判断当前 openGauss 任务是否出现了问题,以及发现性能瓶颈。后续,我们将会进一步在这个功能上进行演进,不断增强 openGauss 的核心竞争力。
openGauss3.1.0 版本的gs_stack功能解密的更多相关文章
- Dash 2.9.0版本重磅新功能一览
本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/dash-master 大家好我是费老师,就在昨晚,Dash框架发布了其2.9.0版本更新,在一众更新 ...
- ICG_System之全自动代码生成器V2.0版本
大家好! 早在2014年本人就已经利用业余时间开发自己的ICG之代码生成器系统.依靠bootstrap的崛起本人也在不断完善此应用.目的是为了减少开发人员的工作量. 减少不必要的复制粘贴操作,该系统已 ...
- 意料之外,情理之中,Spring.NET 3.0 版本发布-
意料之外,情理之中,Spring.NET 3.0 版本发布- 备受社区和企业开发者广泛关注的Spring.NET在上周发布了3.0版本,并且目前已经保持着持续的更新,让我们一起来看一看他究竟发布了哪些 ...
- 百度echarts 3.0版本和2.0版本的兼容问题
前一段时间,项目中要用到统计图表,之前也用过jqplot的图表插件,这次开发的内容中基于地图的展示还很多,所以后来选择了百度的echarts插件(echarts.baidu.com).刚开始用的时候, ...
- nlog 2.0 强制转换使用 4.0 版本
今天下午研发代码,发现调用其他小组研发的代码,发现其中有使用nlog功能,但nlog版本是2.0 ,而我的项目使用4.0 版本 导致部分功能不能使用,故在web配置文件中加入以下代码即可 <de ...
- 帝国CMS 6.0功能解密之新版结合项功能,帝国结合项使用
可以用来做A-Z信息检索 某字段等于多少,输出 等等 帝国CMS6.0在继承以往版本结合项功能的基础上又新增很多特性,更强大.今天我们就专门来讲解6.0的结合项改进. 回顾下以往版本的结合项语 ...
- 开源社交系统ThinkSNS+ V0.8.0 正式发布(一期功能版本)
智士软件旗下开源sns社交系统ThinkSNS即将进入10周年,推出并行两代系统ThinkSNSV4和ThinkSNS+,以专业易用的技术源码输出,驱动互联网社交软件建设及创业,使用ThinkSNS改 ...
- 学霸系统UI项目功能说明书 v1.0版本
发布人员:软件工程实践小队. 发布内容:学霸系统UI项目说明书. 版本:学霸v1.0版本. 学霸系统UI项目说明书 v1.0版本分为以下部分: Part 1:用户须知: Part 2:功能实现: Pa ...
- Apache Flink 1.9.0版本新功能介绍
摘要:Apache Flink是一个面向分布式数据流处理和批量数据处理的开源计算平台,它能够基于同一个Flink运行时,提供支持流处理和批处理两种类型应用的功能.目前,Apache Flink 1.9 ...
- 体育类1.2.0版本 带有社交性质的 app 并且有内购功能
上架经历 体育类1.2.0版本 应用是体育类的,带有社交性质的 app 并且有内购功能 - 关于内购 最初级的应该是内购的 产品类型 在开发者一开始设置的时候没有注意到区别: 消耗型产品 非消耗型 非 ...
随机推荐
- 【Azure K8S】记录AKS VMSS实例日志收集方式
问题描述 如何从AKS的VMSS集群中收集实例日志? 参考步骤 第一步:登陆VMSS实例 参考官网步骤:使用 SSH 连接到 Azure Kubernetes 服务 (AKS) 群集节点以进行维护或故 ...
- Spring Cloud跟Dubbo区别?
Spring Cloud是一个微服务框架,提供了微服务中很多功能组件,Dubbo一开始时RPC调用框架,核心是解决服务调用间的问题, Spring Cloud是一个大而全的框架,Dubbo更侧重于服务 ...
- Redis基础_五大数据类型和常用命令
## 1. Redis基本介绍 1.1 传统数据存储出现的问题 海量用户 高并发 罪魁祸首--关系型数据库: 性能瓶颈:磁盘IO性能低下 扩展瓶颈:数据关系复杂,扩展性差,不便于大规模集群 解决思路 ...
- 从 HPC 到 AI:探索文件系统的发展及性能评估
随着 AI 技术的迅速发展,模型规模和复杂度以及待处理数据量都在急剧上升,这些趋势使得高性能计算(HPC)变得越来越必要.HPC 通过集成强大的计算资源,比如 GPU 和 CPU 集群,提供了处理和分 ...
- Mysql数据库未添加索引引发的生产事故
最近开发的新功能主要是首页的红点提示功能,某个用户登录系统app,然后进入某一个功能模块, 在该功能下面有很多地方可以操作,新功能就是根据用户信息查询当月是否存在新的数据.总共有四五 个地方如果出现增 ...
- java.lang.Long cannot be cast to java.util.Map-Oracle查询异常处理
Map<String, Object> map一.问题由来 测试环境中进行测试时,某一个接口频繁报一个错,java.lang.Long cannot be cast to java.uti ...
- 基于python的每日固定时间执行实例解析
一 概念 datetime模块属性如下所示: 二 源码解析 该源码中,对时间库datetime应用十分到位,可以看作如下所示: import datetime import threading d ...
- Codeforces Round #844:C. Equal Frequencies
一.来源:Problem - C - Codeforces 二.题面 三.思路 先考虑一个子问题模型:我们现在有用\(m_1\)种随机字母组成的n个数,各字母个数未定,现在需要使这n个数变为\(m_2 ...
- day01-SpringBoot基本介绍
SpringBoot基本介绍 1.SpringBoot是什么? 官网地址:https://spring.io/projects/spring-boot 学习文档:https://docs.spring ...
- springboot实现post请求
找了一堆,发现还是这个靠谱 package com.qishiyun.poplar.qlib.util; import cn.hutool.json.JSONUtil; import com.alib ...