在Linux系统中,将“主内存”称为核心 (core),而核心映像(core image)就是“进程”(process)执行当时的内存内容。当进程发生错误或收到“信号” (signal) 而终止执行时, 系统会将核心映像写入一个文件,以作为调试之用,这就是所谓的核心转储 (core dump)。当在一个程序崩溃时,系统会在指定目录下生成一个core 文件,就可以通过core文件来对造成程序崩贵的原因进行调试定位。
MySQL Core dump
在Linux环境中运行的MySQL也提供core dump功能。core file记录正在运行的进程的状态和内存映像。MySQL8.0里两个参数生成cor文件。
1.core-file
如果MySQL服务意外退出,是否写入核心文件。此变量控制。这里core dump里去掉buffer pool的内容。
2.innodb_buffer_pool_in_core_file
在8.0.14版本中新增了参数innodb_buffer_pool_in_core_file可以动态修改,默认是启用.可以禁用来禁止缓冲池页被写入到核心文件中,从而减少核心文件的大小。因为buffer-pool一般设置内存的50%以上,如果当mysqld进程失效时,具有大型缓冲池的系统可以生成大型核心文件。大型核心文件可能会出现问题,原因有很多,包括写入所需的时间、所消耗的磁盘空间量,以及与传输大型文件相关的挑战。
在启用core_file变量同时,操作系统需要支持madvise函数。madvise函数是Linux系统提供的一个操作系统调用(system call),用于控制系统内存管理。调用madvise函数可以对指定的内存区域设置适当的使用策略,从而优化系统整体性能和内存利用率。
如果innodb_buffer_pool_in_core_file变量被禁用,但操作系统不支持MADV_DONTDUMP,或者发生madvise()故障,则会在MySQL服务器错误日志中写入警告,并禁用core_file变量,以防止写入无意中包含缓冲池页面的核心文件。
下表显示了配置和MADV_DONTDUMP支持场景,用于确定是否生成核心文件以及它们是否包括缓冲池页面。
core_file variable | innodb_buffer_pool_in_core_file variable | madvise() MADV_DONTDUMP Support | Outcome |
---|---|---|---|
OFF (default) | Not relevant to outcome | Not relevant to outcome | Core file is not generated |
ON | ON (default) | Not relevant to outcome | Core file is generated with buffer pool pages |
ON | OFF | Yes | Not relevant to outcome |
ON | OFF | No | Core file is not generated, core_file is disabled, and a warning is written to the server error log |
通过禁用innodb_buffer_pool_in_core_file变量实现的核心文件大小的减少取决于缓冲池的大小,但也受innodb页面大小的影响。较小的页面大小意味着相同数量的数据需要更多的页面,而更多的页面意味着更多的页面元数据。下表提供了不同页面大小的1GB缓冲池的大小缩减示例。
innodb_page_size Setting | Buffer Pool Pages Included (innodb_buffer_pool_in_core_file=ON) | Buffer Pool Pages Excluded (innodb_buffer_pool_in_core_file=OFF) |
---|---|---|
4KB | 2.1GB | 0.9GB |
64KB | 1.7GB | 0.7GB |
查看mysql core dump是否开启:
mysql> show variables like '%core%';
+---------------------------------+-------+
| Variable_name | Value |
+---------------------------------+-------+
| core_file | OFF |
| innodb_buffer_pool_in_core_file | ON |
+---------------------------------+-------+
2 rows in set (0.01 sec)
需要在配置文件开启。并重新启动mysql服务。
[mysqld]
core_file
Linux生成core文件限制
1.还需要查看系统是否对core file 有限制。0表示未开启,unlimited表示无限制。
shell$> ulimit -c
unlimited
备注:ulimit -c filesize,限制生成core文件的大小,ulimit -c 0表示不开启,ulimit -c 1000表示限制core文件限制为1000KB,ulimit -c unlimited无限制。
2.core文件生成路径
#查看目录
shell$> cat /proc/sys/kernel/core_pattern
/usr/lib/systemd/systemd-coredump %P %u %g %s %t %c %h %e
#创建目录,赋予权限
shell$> mkdir -p /corefile
shell$> chmod 0777 /corefile
#设置core文件输出路径和sysctl应用
shell$> vim /etc/sysctl.conf
kernel.core_pattern = /home/mysql/corefile/core-%e-%p
kernel.core_uses_pid = 0
shell$> sysctl -p
#mysql 通常会以 suid 方式启动,所以需要打开 suid_dumpable
shell$> echo 1 >/proc/sys/kernel/core_uses_pid
Core文件查看
1.模拟崩溃
如下生成core dump文件。
shell$> ps -ef |grep mysql
root 1123 1074 0 10:53 pts/0 00:00:00 mysqld_safe --defaults-file=/etc/my8.0.cnf --user=mysql
mysql 2490 1123 3 10:53 pts/0 00:00:01 mysqld --defaults-file=/etc/my8.0.cnf --basedir=/opt/idc/mysql8.0 --datadir=/opt/data8.0/data --port=3380
#kill pid
shell$> kill -SEGV 2490
shell$> /mysqld_safe: line 199: 2490 Segmentation fault (core dumped) env MYSQLD_PARENT_PID=1123 LD_PRELOAD=/usr/lib64/libjemalloc.so.2 nohup mysqld --defaults-file=/etc/my8.0.cnf --port=3380
/dev/null 2>&1
2023-10-09T02:54:49.570357Z mysqld_safe Number of processes running now: 0
2023-10-09T02:54:49.575222Z mysqld_safe mysqld restarted
。。。
shell$> ll /corefile
total 518892
-rw------- 1 mysql mysql 911060992 Oct 9 10:54 core-mysqld-2490
2.GDB查看core文件堆栈信息
gdb [exec file] [core file],启动gdb进入core文件.
shell$> gdb /opt/idc/mysql8.0/bin/mysqld core-mysqld-2490
#1.设置输出的文件名称
(gdb) set logging file thread_info.txt
#2.输入这个命令后,此后的调试信息将输出到指定文件
(gdb) set logging on
Copying output to thread_info.txt.
#3.打印说有线程栈信息,查看程序的崩溃现场所有信息
(gdb) thread apply all bt full
#4.输入这个命令,关闭到指定文件的输出
(gdb) set logging off
Done logging to thread_info.txt.
#5.退出gdb
(gdb) quit
通过对信息,分析具体问题。
shell$> less thread_info.txt.
Thread 37 (LWP 2532):
#0 0x00007fccd50b048c in ?? ()
No symbol table info available.
#1 0x0000000000000000 in ?? ()
No symbol table info available.
0x00007f11d70e397c in pthread kill () from /lib64/libpthread.so.0
symbol table info available .
0x00000000007ed750 in handle fatal signal (sig=11) at /home/buildbot/buildbot/build/sgl/signal handler.cc:343
curr time = 1693902706
tm = (tm sec = 46,tm min = 31, tm hour = 16, tm mday = 5, tm mon = 8, tm year = 123, tm wday = 2, tm yday = 247, tm isdst = 0, tm gmtoff = 23800
tm zone = 0x35b4720 "CST"]
thd = 0x7f106c0008c8
print invalid query pointer =
。。。
上述问题是因为value optimized out导致的。
总结
有时MySQL突然宕机,需要分析具体原因,可以通过查看core文件,找到问题点。但很多环境下突然宕机,一般情况下为了尽快恢复业务,会马上拉起mysqld进程(有可能会继续crash,有可能通过mysql内部recover机制修复错误),继续提供服务。但core dump生成需要时间和一定的空间。如:innodb buffer pool设置越大生成core文件的时间越长,空间需要更大。因此谨慎配置core dump参数。