DM8 打印数据库堆栈+分析问题

简介

DM 实例故障,即数据库进程 dmserver 出现异常,表现为异常中止,进程存在但无响应或者无法登录的状态,出现此类问题都属于比较严重的故障,一般情况下我们需要尽可能的收集到所需要的信息进行故障分析,这里我们将把故障分为两类,来讲下出现类似场景时需要收集哪些有价值内容供后续处理。

先简单说明下我们可能会用到的工具和一些术语:

  1. core 文件:程序异常时操作系统保留的完整进程的内存镜像文件。
  2. gdb:用于调试执行程序或者 core 文件的工具。
  3. 堆栈:程序执行中的运行情况,详细包含了运行时函数调用数据以及数据相关信息。
  4. dmrdc:DM 数据库提供的自带对 core 文件进行简单分析的小工具,以 core 文件作为输入参数,dmrdc 可以从 core 文件中读出所有异常时活动会话上的 SQL 语句信息。

查看core以及core生成的路径

1. 设置core生成

临时设置core文件

  1. 查看生成core文件的开关是否开启;
[root@VM-0-17-centos bin]# ulimit -a

说明:第一行core文件大小为0,没有开启。
在这里插入图片描述

2.使用#ulimit -c [kbytes]可以设置系统允许生成的core文件大小;

ulimit -c 0 不产生core文件
ulimit -c 100 设置core文件最大为100k
ulimit -c unlimited 不限制core文件大小

[root@VM-0-17-centos bin]# ulimit -c unlimited
[root@VM-0-17-centos bin]# ulimit -a

在这里插入图片描述

永久设置core文件

  1. 修改/etc/profile文件添加参数;
1. 在profile文件中加入ulimit -c unlimited
[root@VM-0-17-centos bin]# vim   /etc/profile
ulimit -c unlimited

[root@VM-0-17-centos bin]# source /etc/profile

2. 设置core文件的名称和文件路径

默认生成路径:输入可执行文件运行命令的同一路径下
默认生成名字:默认命名为core。新的core文件会覆盖旧的core文件

设置pid作为文件扩展名

  • 1:添加pid作为扩展名,生成的core文件名称为core.pid
  • 0:不添加pid作为扩展名,生成的core文件名称为core
[root@VM-0-17-centos bin]# cat  /proc/sys/kernel/core_uses_pid 
0
-- 修改 /proc/sys/kernel/core_uses_pid 文件内容为: 1 有下面的两种方式 随便选一种
[root@VM-0-17-centos bin]# echo "1" > /proc/sys/kernel/core_uses_pid
[root@VM-0-17-centos bin]# sysctl -w kernel.core_uses_pid=1 kernel.core_uses_pid = 1

控制core文件保存位置和文件名格式

-- 查询现在的值 缺省值为core 
-- core文件默认的存储位置与对应的可执行程序在同一目录下,文件名是core,大家可以通过下面的命令看到core文件的存在位置:
[root@VM-0-17-centos bin]# cat /proc/sys/kernel/core_pattern
core

--  core文件统一生成指定到/corefile目录下,产生的文件名为core-命令名-pid-时间戳
[root@VM-0-17-centos bin]# mkdir /corefile
[root@VM-0-17-centos bin]# echo "/corefile/core-%e-%p-%t" > /proc/sys/kernel/core_pattern
[root@VM-0-17-centos bin]# sysctl -w kernel.core_pattern=/corefile/core.%e.%p.%s.%E

以下是参数列表:
%p - insert pid into filename 添加pid(进程id)
%u - insert current uid into filename 添加当前uid(用户id)
%g - insert current gid into filename 添加当前gid(用户组id)
%s - insert signal that caused the coredump into the filename 添加导致产生core的信号
%t - insert UNIX time that the coredump occurred into filename 添加core文件生成时的unix时间
%h - insert hostname where the coredump happened into filename 添加主机名
%e - insert coredumping executable name into filename 添加导致产生core的命令名

综上所述

1.编辑环境配置文件,让shell启动时自动设置ulimit
2.更改core文件生成路径
3.sysctl配置生效

[root@VM-0-17-centos bin]# vi /etc/profile
[root@VM-0-17-centos bin]# ulimit -c unlimited > /dev/null 2>&1
[root@VM-0-17-centos bin]# vi /etc/sysctl.conf
kernel.core_uses_pid = 1
kernel.core_pattern=/tmp/core-%e-%p
[root@VM-0-17-centos bin]# sysctl -p /etc/sysctl.conf

3. 测试core有没有生成

  1. 新建test.c文件
#include<stdio.h>

void test(){
    int *p = NULL;
      *p = 0;
}

int main()
{
      test();
      return 0;
}
  1. 编译文件
[root@VM-24-17-centos bin]# vim test.c
[root@VM-24-17-centos bin]# gcc -o test1 test.c
[root@VM-24-17-centos bin]# ./test 1
段错误 (核心已转储)
[root@VM-24-17-centos bin]# ll /corefile/*
-rw------- 1 root root 249856 418 19:20 /corefile/core-test1-2291735-1650281826
[root@VM-24-17-centos corefile]# gdb /opt/dmdbms/bin/test1 core-test1-2291735-1650281826
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x0000000000400546 in test ()
Missing separate debuginfos, use: yum debuginfo-install glibc-2.28-151.el8.x86_64
(gdb) bt
#0  0x0000000000400546 in test ()
#1  0x000000000040055d in main ()

宕掉DM生成core

设置环境变量ulimit -c unlimited,程序崩溃后就会在当前目录下生成core文件

  1. 执行以下sql语句,创建一张测试表,并且插入一些数据,保证有较长的执行时间。
CREATE TABLE TESTCOER(ID INT);
INSERT INTO TESTCOER SELECT LEVEL FROM DUAL CONNECT BY LEVEL <10000500;
  1. 使用以下命令查询数据库进程PID,并且使用kill -11强杀进程
-- 命令查询数据库进程PID,并且使用kill -11强杀进程。core文件就会指定的目录下生成

[root@VM-24-17-centos bin]# ps -ef|grep dms
dmdba    2297221       1  8 20:16 pts/0    00:00:04 /opt/dmdbms/bin/dmserver path=/opt/dmdata/DAMENG/dm.ini -noconsole
root     2297413 2289093  0 20:17 pts/0    00:00:00 grep --color=auto dms
[root@VM-24-17-centos bin]# kill -11 2297221
[root@VM-24-17-centos bin]# kill -11 2297221
[root@VM-24-17-centos bin]# kill -11 2297221

//查找生成的core文件
[root@VM-24-17-centos bin]# ll -lht core.*
-rw------- 1 dmdba dinstall 4033536000 418 20:17 core.2297221

分析core文件

1. gdb读取core文件

**当数据库异常中断宕机产生core文件,通过GDB分析core文件来判断造成数据库宕机的原因。 **

// 1. 查找生成的core文件
[dmdba@VM-0-17-centos bin]$ ll -lht core.*
-rw------- 1 dmdba dinstall 1.4G 324 15:49 core.12593
// 2. gdb读取core文件
[dmdba@VM-0-17-centos bin]$ gdb ./dmserver core.12593 
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-120.el7
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"

在这里插入图片描述


// 3. 定义存储堆栈的文件名
(gdb) set logging file core_12593.txt
(gdb) set logging on
Copying output to core_12593.txt.

// 4. 记录当前所有崩溃线程堆栈
(gdb)  thread apply all bt
Thread 67 (Thread 0x7f2e3e816700 (LWP 18366)):

// 5. 关闭向文件中写入
(gdb) set logging off
Done logging to core_12593.txt.

// 6.记录当前崩溃线程堆栈
(gdb) bt
#0  0x000000000007875e in ?? ()
#1  0x00007f2ea574c9c9 in CRYPTO_THREAD_run_once () from ./libcrypto.so
#2  0x00007f2ea5712401 in RAND_get_rand_method () from ./libcrypto.so
#3  0x00007f2ea571268d in RAND_add () from ./libcrypto.so
#4  0x0000000000879e0d in dm_dh_gen_respective_key ()
#5  0x000000000150dd72 in ntsk_process_startup ()
#6  0x000000000150fcde in ntsk_process_cop ()
#7  0x0000000001415c80 in uthr_db_main_for_sess ()
#8  0x00007f2ea7f9cea5 in start_thread () from /lib64/libpthread.so.0
#9  0x00007f2ea74b7b0d in clone () from /lib64/libc.so.6

// 7. 记录当前崩溃线程号
//输入 info threads 记录当前崩溃线程号:
(gdb)  info threads
//备注 
//前面有*为当前线程,LWP后面为线程号
Id   Target Id                           Frame 
* 1    Thread 0x7f7daae63740 (LWP 2297221) 0x000000000155a117 in assert_fun ()
2    Thread 0x7f7d27b4f700 (LWP 2297225) 0x00007f7daa8292fc in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
3    Thread 0x7f7d27237700 (LWP 2297228) 0x00007f7daa8292fc in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
4    Thread 0x7f7d27338700 (LWP 2297227) 0x00007f7daa8292fc in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
5    Thread 0x7f7c4bfff700 (LWP 2297309) 0x00007f7da9c2ca41 in poll () from /lib64/libc.so.6
6    Thread 0x7f7d27136700 (LWP 2297229) 0x00007f7daa8292fc in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
7    Thread 0x7f7d25b6c700 (LWP 2297248) 0x00007f7daa8292fc in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
8    Thread 0x7f7d26429700 (LWP 2297242) 0x00007f7daa8296e8 in pthread_cond_timedwait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
9    Thread 0x7f7c4b7fe700 (LWP 2297310) 0x00007f7da9c2ca41 in poll () from /lib64/libc.so.6
10   Thread 0x7f7d26f34700 (LWP 2297231) 0x00007f7daa8292fc in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
11   Thread 0x7f7d2596a700 (LWP 2297250) 0x00007f7daa8292fc in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
12   Thread 0x7f7c601af700 (LWP 2297325) 0x00007f7daa82cfb0 in nanosleep () from /lib64/libpthread.so.0
13   Thread 0x7f7c485f7700 (LWP 2297326) 0x00007f7da9c2f29f in select () from /lib64/libc.so.6
14   Thread 0x7f7d26d32700 (LWP 2297233) 0x00007f7daa8292fc in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
15   Thread 0x7f7d25edd700 (LWP 2297255) 0x00007f7daa8292fc in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
16   Thread 0x7f7d2652a700 (LWP 2297241) 0x00007f7daa8292fc in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
17   Thread 0x7f7c3fff7700 (LWP 2297380) 0x00007f7daa82c8e4 in read () from /lib64/libpthread.so.0
18   Thread 0x7f7d26c31700 (LWP 2297234) 0x00007f7daa8292fc in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
19   Thread 0x7f7c610b7700 (LWP 2297269) 0x00007f7daa8296e8 in pthread_cond_timedwait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
20   Thread 0x7f7c3e8f5700 (LWP 2297381) 0x00007f7daa8292fc in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
21   Thread 0x7f7d26b30700 (LWP 2297235) 0x00007f7daa8292fc in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
22   Thread 0x7f7d26a2f700 (LWP 2297236) 0x00007f7daa8292fc in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
23   Thread 0x7f7d2692e700 (LWP 2297237) 0x00007f7daa8292fc in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0(gdb) info threads


// 8.使用dmrdc工具生成SQL语句
[root@VM-24-17-centos bin]# ./dmrdc sfile=core.12593
dmrdc V8
Analysing: 0/4033536000
Analysing: 31457268/4033536000
Analysing: 62914536/4033536000
-- 中间部分省略
Analysing: 3995073036/4033536000
Analysing: 4026530304/4033536000
ֻ¸򺽳̹²»¨·Ϡ   5.898 s

// 9. 生成的文件为core_tmp.2297221
[root@VM-24-17-centos bin]# ll -lht core.*
-rw------- 1 dmdba dinstall 4033536000 418 20:17 core.12593
-rw-r--r-- 1 root  root            282 418 20:19 core_tmp.12593

// 10. 查看core语句
// 结合dmrdc的结果对应的SQL语句(从dmrdc的结果中找对应的2297381线程号,!#%&*^$@[线程号]):!#%&*^$@[2297381] 与 info threads可以查看崩溃线程号相对应
// 然后开始分析该语句
[root@VM-24-17-centos bin]# cat core_tmp.12593
!#%&*^$@[2297381]:INSERT INTO TESTCOER SELECT LEVEL FROM DUAL CONNECT BY LEVEL <10000500;
!#%&*^$@[2297380]:SELECT EP1.EP_PORT FROM V$DCR_EP EP1, V$DCR_EP EP2, V$INSTANCE INST WHERE EP1.SHM_SIZE > 0 AND EP1.EP_SEQNO=INST.DSC_SEQNO AND EP2.EP_NAME=INST.NAME;

2. 手动生成core文件

当系统出现异常的时候,dmserver服务又没有宕机,没有自动生成core 时,就需要手动生产core文件
1如果是集群环境,必须先将dmmonitor进程关掉,再将 dmwatcher进程关掉

[dmdba@VM-0-17-centos bin]$ ps -ef|grep dms
dmdba     2426134     1  0 4月13 ?       00:06:28 /opt/dmdbms/bin/dmserver /opt/dmdata/DAMENG/dm.ini -noconsole mount
dmdba    26034 22154  0 21:48 pts/1    00:00:00 grep --color=auto dms
 ## 1. gdb调试进程
[dmdba@VM-0-17-centos bin]$ gdb dmserver 
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-120.el7
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /opt/dmdbms/bin/dmserver...(no debugging symbols found)...done.
## 2. 通过进程号,attach进入到进程里
(gdb) attach 2426134

## 3. 手动生成core文件
(gdb) generate-core-file
warning: target file /proc/2426134/cmdline contained unexpected null characters
Saved corefile core.2426134

## 4. detach --离开进程
(gdb) detach
Detaching from program: /opt/dmdbms/bin/dmserver, process 2426134
[Inferior 1 (process 2426134) detached]

## 5. quit 退出gdb
(gdb) quit


## 6. 分析完成后,先开启dmwatcher,再将dmmonitor开启

3.直接分析堆栈

**如果是集群环境,必须先将dmmonitor进程关掉,再将dmwatcher进程关掉 **

[dmdba@VM-0-17-centos bin]$ ps -ef|grep dms
dmdba     2426134     1  0 4月13 ?       00:06:28 /opt/dmdbms/bin/dmserver /opt/dmdata/DAMENG/dm.ini -noconsole mount
dmdba    26034 22154  0 21:48 pts/1    00:00:00 grep --color=auto dms
 ## 1. gdb调试进程
[dmdba@VM-0-17-centos bin]$ gdb dmserver 
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-120.el7
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /opt/dmdbms/bin/dmserver...(no debugging symbols found)...done.
## 2. 通过进程号,attach进入到进程里
(gdb) attach 2426134
## 3. 定义存储堆栈的文件名
(gdb) set logging file core_2426134.txt
(gdb) set logging on
Copying output to core_12593.txt.

## 4. 记录当前所有崩溃线程堆栈 -一直回车到什么都不输出
(gdb)  thread apply all bt
Thread 67 (Thread 0x7f2e3e816700 (LWP 18366)):

## 5. 关闭向文件中写入
(gdb) set logging off
Done logging to core_12593.txt.


## 6. detach --离开进程
(gdb) detach
Detaching from program: /opt/dmdbms/bin/dmserver, process 2426134
[Inferior 1 (process 2426134) detached]

## 7. quit 退出gdb
(gdb) quit



分析完成后,先开启dmwatcher,再将dmmonitor开启

4.gdb启动数据库

使用gdb的方式启动数据库,再出现异常时打印堆栈

#gdb启动数据库
1. .4备机停watcher,server
2. .4备机gdb启动 命令:gdb dmserver
3. .4备机运行数据库 r /dmdata/OA/dm.ini mount
4. .4备机脚本启动dmwatcher
5. 等待集群恢复正常 执行切换,继续让.4当主机




当出现异常时
1.查看当前崩溃线程 并记录 命令 bt
2.打印所有线程 thread apply all bt
3.生成堆栈 generate-core-file

5.打印线程堆栈

[root@VM-24-16-centos ~]# ps -ef|grep dmdba
dmdba     6994     1  0 5月10 ?       00:09:47 /opt/dmdbms/bin/dmserver path=/opt/dmdata/DAMENG/dm.ini -noconsole
dmdba     9516     1  0 5月10 ?       00:00:07 /opt/dmdbms/bin/dmap
root     16010 15962  0 22:28 pts/0    00:00:00 grep --color=auto dmdba

2. 通过TOP -H -p 进程ID,找到具体的线程占用情况,Shift+H可以开启关闭线程显示
[root@VM-24-16-centos ~]# top -Hp 6994

3、通过命令pstack 进程ID显示线程堆栈,LWP 6997对应线程ID的堆栈,就是占用CPU最高的堆栈,可以具体分析什么原因造成的。
[root@VM-24-16-centos ~]#  pstack 6997


概念

什么是Core Dump?

Core的意思是内存, Dump的意思是扔出来, 堆出来.开发和使用Unix程序时, 有时程序莫名其妙的down了, 却没有任何的提示(有时候会提示core dumped). 这时候可以查看一下有没有形如core.进程号的文件生成, 这个文件便是操作系统把程序down掉时的内存内容扔出来生成的, 它可以做为调试程序的参考.
core dump又叫核心转储, 当程序运行过程中发生异常, 程序异常退出时, 由操作系统把程序当前的内存状况存储在一个core文件中, 叫core dump.

为什么没有core文件生成呢?


有时候程序down了, 但是core文件却没有生成. core文件的生成跟你当前系统的环境设置有关系, 可以用下面的语句设置一下, 然后再运行程序便成生成core文件.
ulimit -c unlimited
core文件生成的位置一般于运行程序的路径相同, 文件名一般为core.进程号

当获得了core文件以后,就可以利用命令gdb进行查找,参数一是应用程序的名称,参数二是core文件
如: gdb […]xmsd […]/xmsd_PID1065_SIG11.core
然后输入bt或者where找到错误发生的位置和相应的堆栈信息。就可知道发生错误时的函数调用关系,然后可以使用up或者down查看上一条和下一条具体详细信息。这样便能对问题进行大概定位,然后看源代码,进行分析。

达梦支持

=======================================

有任何问题请到技术社区反馈。

24小时免费服务热线:400 991 6599

达梦技术社区:https://eco.dameng.com

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值