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功能解密的更多相关文章

  1. Dash 2.9.0版本重磅新功能一览

    本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/dash-master 大家好我是费老师,就在昨晚,Dash框架发布了其2.9.0版本更新,在一众更新 ...

  2. ICG_System之全自动代码生成器V2.0版本

    大家好! 早在2014年本人就已经利用业余时间开发自己的ICG之代码生成器系统.依靠bootstrap的崛起本人也在不断完善此应用.目的是为了减少开发人员的工作量. 减少不必要的复制粘贴操作,该系统已 ...

  3. 意料之外,情理之中,Spring.NET 3.0 版本发布-

    意料之外,情理之中,Spring.NET 3.0 版本发布- 备受社区和企业开发者广泛关注的Spring.NET在上周发布了3.0版本,并且目前已经保持着持续的更新,让我们一起来看一看他究竟发布了哪些 ...

  4. 百度echarts 3.0版本和2.0版本的兼容问题

    前一段时间,项目中要用到统计图表,之前也用过jqplot的图表插件,这次开发的内容中基于地图的展示还很多,所以后来选择了百度的echarts插件(echarts.baidu.com).刚开始用的时候, ...

  5. nlog 2.0 强制转换使用 4.0 版本

    今天下午研发代码,发现调用其他小组研发的代码,发现其中有使用nlog功能,但nlog版本是2.0 ,而我的项目使用4.0 版本 导致部分功能不能使用,故在web配置文件中加入以下代码即可 <de ...

  6. 帝国CMS 6.0功能解密之新版结合项功能,帝国结合项使用

    可以用来做A-Z信息检索    某字段等于多少,输出  等等 帝国CMS6.0在继承以往版本结合项功能的基础上又新增很多特性,更强大.今天我们就专门来讲解6.0的结合项改进. 回顾下以往版本的结合项语 ...

  7. 开源社交系统ThinkSNS+ V0.8.0 正式发布(一期功能版本)

    智士软件旗下开源sns社交系统ThinkSNS即将进入10周年,推出并行两代系统ThinkSNSV4和ThinkSNS+,以专业易用的技术源码输出,驱动互联网社交软件建设及创业,使用ThinkSNS改 ...

  8. 学霸系统UI项目功能说明书 v1.0版本

    发布人员:软件工程实践小队. 发布内容:学霸系统UI项目说明书. 版本:学霸v1.0版本. 学霸系统UI项目说明书 v1.0版本分为以下部分: Part 1:用户须知: Part 2:功能实现: Pa ...

  9. Apache Flink 1.9.0版本新功能介绍

    摘要:Apache Flink是一个面向分布式数据流处理和批量数据处理的开源计算平台,它能够基于同一个Flink运行时,提供支持流处理和批处理两种类型应用的功能.目前,Apache Flink 1.9 ...

  10. 体育类1.2.0版本 带有社交性质的 app 并且有内购功能

    上架经历 体育类1.2.0版本 应用是体育类的,带有社交性质的 app 并且有内购功能 - 关于内购 最初级的应该是内购的 产品类型 在开发者一开始设置的时候没有注意到区别: 消耗型产品 非消耗型 非 ...

随机推荐

  1. 【Azure K8S】记录AKS VMSS实例日志收集方式

    问题描述 如何从AKS的VMSS集群中收集实例日志? 参考步骤 第一步:登陆VMSS实例 参考官网步骤:使用 SSH 连接到 Azure Kubernetes 服务 (AKS) 群集节点以进行维护或故 ...

  2. Spring Cloud跟Dubbo区别?

    Spring Cloud是一个微服务框架,提供了微服务中很多功能组件,Dubbo一开始时RPC调用框架,核心是解决服务调用间的问题, Spring Cloud是一个大而全的框架,Dubbo更侧重于服务 ...

  3. Redis基础_五大数据类型和常用命令

    ## 1. Redis基本介绍 1.1 传统数据存储出现的问题 海量用户 高并发 罪魁祸首--关系型数据库: 性能瓶颈:磁盘IO性能低下 扩展瓶颈:数据关系复杂,扩展性差,不便于大规模集群 解决思路 ...

  4. 从 HPC 到 AI:探索文件系统的发展及性能评估

    随着 AI 技术的迅速发展,模型规模和复杂度以及待处理数据量都在急剧上升,这些趋势使得高性能计算(HPC)变得越来越必要.HPC 通过集成强大的计算资源,比如 GPU 和 CPU 集群,提供了处理和分 ...

  5. Mysql数据库未添加索引引发的生产事故

    最近开发的新功能主要是首页的红点提示功能,某个用户登录系统app,然后进入某一个功能模块, 在该功能下面有很多地方可以操作,新功能就是根据用户信息查询当月是否存在新的数据.总共有四五 个地方如果出现增 ...

  6. java.lang.Long cannot be cast to java.util.Map-Oracle查询异常处理

    Map<String, Object> map一.问题由来 测试环境中进行测试时,某一个接口频繁报一个错,java.lang.Long cannot be cast to java.uti ...

  7. 基于python的每日固定时间执行实例解析

    一 概念 datetime模块属性如下所示:   二 源码解析 该源码中,对时间库datetime应用十分到位,可以看作如下所示: import datetime import threading d ...

  8. Codeforces Round #844:C. Equal Frequencies

    一.来源:Problem - C - Codeforces 二.题面 三.思路 先考虑一个子问题模型:我们现在有用\(m_1\)种随机字母组成的n个数,各字母个数未定,现在需要使这n个数变为\(m_2 ...

  9. day01-SpringBoot基本介绍

    SpringBoot基本介绍 1.SpringBoot是什么? 官网地址:https://spring.io/projects/spring-boot 学习文档:https://docs.spring ...

  10. springboot实现post请求

    找了一堆,发现还是这个靠谱 package com.qishiyun.poplar.qlib.util; import cn.hutool.json.JSONUtil; import com.alib ...