MySQL客户端连接登入hang住原因分析

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介: MySQL客户端连接登入hang住原因分析

一、问题来源

问题来自一位朋友

mysql客户端无法登陆,查看服务器负载没有发现高负载信息。通过pstack查看线程栈信息,没有发现异常信息。


二、问题诊断和解决

一般来讲出现这种情况,我们会使用pstack看看新建立的线程为在什么函数上卡住了,然后很容易就能找到原因。但是出现这个问题过后,当mysql发起连接后卡住后,使用pstack查看mysqld服务端的进程,发现根本就没有线程与之进行交互,因此mysqld怀疑监听线程是不是出了什么问题,因此对mysql客户端连接进程进行了pstack发现如下:

#0  0x00007f262e7889c0 in __connect_nocancel () from /lib64/libpthread.so.0
#1  0x0000000000435123 in inline_mysql_socket_connect (src_file=0x504490 "../../mysql-8.0.20/vio/viosocket.cc", src_line=1054, len=110, addr=0x7fffb38daa20, mysql_socket=...) at ../../mysql-8.0.20/include/mysql/psi/mysql_socket.h:647
#2  vio_socket_connect (vio=0x110d2c0, addr=addr@entry=0x7fffb38daa20, len=len@entry=110, nonblocking=<optimized out>, timeout=-1, connect_done=connect_done@entry=0x7fffb38da9ef) at ../../mysql-8.0.20/vio/viosocket.cc:1054
#3  0x0000000000422ad6 in csm_begin_connect (ctx=0x7fffb38daad0) at ../../mysql-8.0.20/sql-common/client.cc:250
#4  0x000000000041fe99 in mysql_real_connect (mysql=mysql@entry=0xaf16a0 <mysql>, host=host@entry=0x0, user=user@entry=0x10defc0 "root", passwd=passwd@entry=0x10deff0 "xsh0923", db=db@entry=0x0, port=<optimized out>, unix_socket=0x10e0860 "/data/mysql3306/tmp/mysql.sock", client_flag=66560) at ../../mysql-8.0.20/sql-common/client.cc:5600
#5  0x000000000040ddb6 in sql_real_connect (silent=0, password=0x10deff0 "xsh0923", user=0x10defc0 "root", database=0x0, host=0x0) at ../../mysql-8.0.20/client/mysql.cc:4515
#6  sql_connect (host=0x0, database=0x0, user=0x10defc0 "root", password=0x10deff0 "xsh0923", silent=<optimized out>) at ../../mysql-8.0.20/client/mysql.cc:4670
#7  0x000000000040968b in main () at ../../mysql-8.0.20/client/mysql.cc:1326
#8  0x00007f262ce3e495 in __libc_start_main () from /lib64/libc.so.6
#9  0x000000000040a4e1 in _start () at ../../mysql-8.0.20/include/my_alloc.h:86


实际上mysql卡住connect函数上面如下,

因此mysql客户端和mysqld服务端都还没有建立好连接,netstat查看如下:

unix  2      [ ACC ]     STREAM     LISTENING     8584712  29676/mysqld         /tmp/mysqlx.sock

unix 7 [ ACC ] STREAM LISTENING 8584713 29676/mysqld /data/mysql3306/tmp/mysql.sock
unix 2 [ ] STREAM CONNECTING 0 - /data/mysql3306/tmp/mysql.sock
unix 2 [ ] STREAM CONNECTING 0 - /data/mysql3306/tmp/mysql.sock
unix 2 [ ] STREAM CONNECTING 0 - /data/mysql3306/tmp/mysql.sock
大量connectint状态的连接

正常的情况下这里应该是poll和accept然后开启新的(或者从缓存线程中拿一个)线程来处理交互信息了。但是这里我们可以清晰的看到出现了SIGSTOP信号。随即查看正mysqld线程的状态,所有的线程都处于T状态下,这个状态正是由于信息SIGSTOP引起的。因此我们发一个SIGCONT信号给mysqld进程就好了如下:

kill -18 29676


三、关于信号

下面是我学习信号的时候一些笔记。

在Linux中信号是一种由内核处理的一种软中断机制,他满足简单、不能携带大量信息、并且要满足一定条件才会发送等特征。信号会经历如下过程:

  • 产生-->阻塞信号集-->未决信号集-->信号递达-->信号处理方式

首先信号的产生可以有多种方式比如我们经常用的kill命令就是发起信号的一种手段如下:

[root@mgr4 8277]# kill -l
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP
6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR
31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3
38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8
43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7
58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2
63) SIGRTMAX-1 64) SIGRTMAX



我们经常的按键也可以产生

  • Ctrl+c 2)SIGINT
  • Ctrl+\ 3)SIGQUIT
  • Ctrl+z 4)SIGTSTP

当然还有很多其他触发方式比如硬件异常,raise函数,abort函数,alarm函数等等。其次是阻塞信号集,阻塞信号集能够对想除(9/19号信号以外)的信号进行屏蔽,如果屏蔽后信号自然不会到达 递达 状态,也就谈不上处理了。通过sigprocmask函数进行阻塞信号集的设置,但之前必须要设置sigset_t 集合,通过sigaddset、sigdelset、sigemptyset、sigfillset等函数设置。

未决信号集是不能被操作的,只能被获取通过sigpending函数获取,但是他和阻塞信号集一起可以控制信号的递达。

信号递达后就需要处理信号,默认的行为上面都列举了,但是信号(9/19号信号以外)是可以被捕获改变其处理方式的,我们可以自定义函数作为某个信号的处理方式,这可以通过signal函数和sigaction函数进行捕获和处理,sigaction函数相对复杂需要有一个struct sigaction的结构体变量,其中包含了sa_handler\sa_mask\sa_flags\sa_siaction 成员,这里不做解释可以自行查看Linux man page。

上面是单进程下的信号处理方式,在多线程下,线程之间公用处理方式,但是可以有不同的信号屏蔽集,在多线程下一般采用设置统一的信号屏蔽字和信号处理方式使用pthread_mask函数继承到各个线程,同时使用sigwait/sigwaitinfo等函数设置一个单独的信号处理线程来进行统一处理,MySQL就是这样处理的。MySQL实际上有一个信号处理线程,

|     36 |         1927 | sql/signal_handler              |    NULL | BACKGROUND | NULL   | NULL         |

如果需要了解可以参考如下文章: MySQL中对信号的处理(SIGTERM,SIGQUIT,SIGHUP等), http://blog.itpub.net/7728585/viewspace-2142060/

四、pstack和SIGSTOP

这里简单提一下pstack抓取线程栈的时候会触发一个SIGSTOP信号,因为pstack实际上调用的就是gdb的如下命令:

/usr/bin/gdb --quiet -nx /proc/8277/exe 8277
thread apply all bt
输出所有线程信息

gdb通常会发起SIGSTOP信号来停止进程的运行,因此我们在线上执行pstack命令的时候一定要小心,pstack可能导致你的MySQL停止运行一小会,特别是高压力线程很多负载很高的情况下,可能需要很长的时候,pstack应该作为线上重要数据库最后不得已而为之的诊断方式

如下我们使用pstack 来获取mysqld的栈,运行一开始就关闭窗口,此时我们的mysqld已经处于停止状态.

因此使用pstack一定要格外小心。一般来讲从库线程不多压力不大重要性不高可以使用pstack进行信息采集。当然也可以手动发起SIGSTOP信号来达到测试效果。


五、捕获所有的信号

下面一个小代码可以捕获所有的信号供测试:

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include "unistd.h"

void handler(int sig)
{
printf("get signal %d\n",sig);
}

void test()
{
;
}

int main(void)
{
struct sigaction s;
int* a=NULL;
int i=0;

a=(int*)calloc(32,sizeof(int));

for(i=0;i<32;i++)
{
*(a+i) = (i+1);
}

s.sa_handler=handler;

for(i=0;i<32;i++)
{
sigaction(*(a+i),&s,NULL);
}

while(1)
{
test();
sleep(1);
}

return 0;
}

全文完。

Enjoy MySQL :)

            </div>
相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
5月前
|
安全 关系型数据库 MySQL
mysql服务器hang死的原因
mysql服务器hang死的原因
|
关系型数据库 MySQL Windows
MySQL启动时显示:发生系统错误 5。拒绝访问解决办法
MySQL启动时显示:发生系统错误 5。拒绝访问解决办法
MySQL启动时显示:发生系统错误 5。拒绝访问解决办法
|
关系型数据库 MySQL 数据库
MySQL连接错误,使用Navicat连接MySQL出现访问被拒错误的情况:
MySQL连接错误,使用Navicat连接MySQL出现访问被拒错误的情况:
1141 0
MySQL连接错误,使用Navicat连接MySQL出现访问被拒错误的情况:
|
缓存 NoSQL 关系型数据库
MySQL客户端连接登入hang住原因分析
MySQL客户端连接登入hang住原因分析
132 0
|
SQL 安全 关系型数据库
【解决方法】mysql5.5安装不成功:最后一步未响应
【解决方法】mysql5.5安装不成功:最后一步未响应
【解决方法】mysql5.5安装不成功:最后一步未响应
|
SQL Oracle 关系型数据库
Oracle 数据库利用sql语句杀掉用户session进程,“ORA-01940: 无法删除当前连接的用户“问题解决办法
Oracle 数据库利用sql语句杀掉用户session进程,“ORA-01940: 无法删除当前连接的用户“问题解决办法
315 0
Oracle 数据库利用sql语句杀掉用户session进程,“ORA-01940: 无法删除当前连接的用户“问题解决办法
|
SQL 弹性计算 缓存
记一次mysql客户端执行sql后hung住
背景: 客户反馈,执行sql后无返回,同时抓包没有抓到对应的sql发起访问(实际复现的时候抓到了报文),以及mysql客户端加不加-A 速度不一(不加 -A 要在本地创建一个库表缓存,加了就不创建这个),实际分析下来并没有很难,本文主要为了分享一下该类问题分析的小技巧 1,需要循环执行sql,.
1532 0
记一次mysql客户端执行sql后hung住
|
关系型数据库 MySQL
Mysql 本地计算机无法启动 mysql 服务 错误 1067:进程意外终
1、重装后启动mysql服务,提示 本地计算机无法启动 mysql 服务 错误 1067:进程意外终止。2、查看mysql根目录下有一 计算机名.err 打开一看全是英文的错误提示; 3、根据其中的有一条错误,分析; 4、打开my.ini或my.cnf文件,找到default-storage-engine这一行,把它改成default-storage-engine=MyISAM。
1633 0

推荐镜像

更多