vc mysql init 崩溃_故障分析 | 崩溃恢复巨慢原因分析

作者:xuty

本文来源:原创投稿

*爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。

一、现象

有个 MySQL 5.7 开发库异常挂掉后,奔溃恢复一直处于如下位置,且持续了 2 小时左右才起来。非常疑惑这段时间 MySQL 到底做了什么事情?居然需要这么长时间。虽说这里虚拟机的 IOPS 并不是很高,但也绝对不需要这么久吧?而且从日志输出来看,这块应该也不是在做真正的数据恢复,那么也可以排除是大事务回滚导致的耗时长,那么原因到底是啥呢?

值得注意的是,这台开发库上面有将近 1500 个库和上万张表,难道MySQL 崩溃恢复时长和表的数量也存在一定关系嘛?

476197aedad1a84db6109402d76bcaff.png

二、分析栈帧

在 MySQL 崩溃恢复时,用pstack打了栈帧,再用pt-pmp工具分析栈帧后显示如下:

pread64(libpthread.so.0),os_file_io(os0file.cc:5435),os_file_pread(os0file.cc:5612),os_file_read_page(os0file.cc:5612),os_file_read_no_error_handling_func(os0file.cc:6069),pfs_os_file_read_no_error_handling_func(os0file.ic:341),Datafile::read_first_page(os0file.ic:341),Datafile::validate_first_page(fsp0file.cc:551),Datafile::validate_to_dd(fsp0file.cc:404),fil_ibd_open(fil0fil.cc:3969),dict_check_sys_tables(dict0load.cc:1465),dict_check_tablespaces_and_store_max_id(dict0load.cc:1525),innobase_start_or_create_for_mysql(srv0start.cc:2329),innobase_init(ha_innodb.cc:4048),ha_initialize_handlerton(handler.cc:838),plugin_initialize(sql_plugin.cc:1197),plugin_init(sql_plugin.cc:1538),init_server_components(mysqld.cc:4033),mysqld_main(mysqld.cc:4673),__libc_start_main(libc.so.6),_start根据函数名字,感觉像是在遍历校验每个表空间文件的有效性?,难道 MySQL 崩溃恢复时会额外进行校验操作?貌似和表数量扯上点关系了。

三、GDB 调试Server version: 5.7.26-log MySQL Community Server (GPL)

直接去分析源码感觉有点找不到切入点,因为不知道正常启动是不是也是这样的函数调用。为了知道正常启动与崩溃恢复的区别,先在本地的 MySQL 5.7.26 环境中用 GDB 调试 MySQL 启动过程,看下正常启动和崩溃恢复的函数调用有哪些区别,再针对性的去分析源码比较好。

-- 将之前的栈帧弄成了树状,便于分析>innobase_init| >innobase_start_or_create_for_mysql| | >dict_check_tablespaces_and_store_max_id| | | >dict_check_sys_tables| | | | >fil_ibd_open| | | | | >Datafile::validate_to_dd| | | | | | >Datafile::validate_first_page| | | | | | | >Datafile::read_first_page| | | | | | | | >pfs_os_file_read_no_error_handling_func| | | | | | | | | >os_file_read_no_error_handling_func| | | | | | | | | | >os_file_read_page| | | | | | | | | | | >os_file_pread| | | | | | | | | | | | >os_file_io

正常启动 GDB 调试结果:

从上到下,每次打一个断点函数,发现到Datafile::validate_to_dd这个函数时,MySQL 正常启动就不会执行,看样子是fil_ibd_open函数中做了某些判断。

崩溃恢复 GDB 调试结果:

一边用 sysbench 压,一边直接 kill -9 进程就可以模拟崩溃恢复,同样从上到下,依次打断点函数,发现会走到Datafile::validate_to_dd这个函数中,Continue 后会一直断点在这个函数上,说明外层包装了一层循环会遍历所有表,如果继续增加断点函数的话,发现绝大部分表会继续走下去,直到os_file_io,而小部分表则不会继续走下去。

四、源码分析

4.1. fil_ibd_open

我们先去fil_ibd_open函数中看下,进入Datafile::validate_to_dd函数的判断条件,发现主要和一个validate参数有关,如果为false则可以跳过检测,为true则需要进入Datafile::validate_to_dd函数。

6efda04ba408aeac9bae7efef07d1ed9.png

4.2. innobase_start_or_create_for_mysql

然后我们需要看下validate参数的定义,分析崩溃恢复与正常启动的区别。发现validate 参数最早是在innobase_start_or_create_for_mysql函数中定义的,并且其注释已经解释的非常详细。1. 正常启动:直接为每张表的创建 space object 即可,不需要打开 ibd 文件的 header page 进行表空间校验。2. 崩溃恢复:为了数据字典的一致性,需要遍历打开所有 ibd 文件的 header page 进行表空间校验。

validate 这个参数表明当一个表空间被打开时,同时会去读取其 ibd 文件的头页(header page)来验证数据字典的一致性,而当数据库包含许多 ibd 文件时,这个过程就会比较久,所以只在崩溃恢复且非强制恢复时执行表空间校验操作!

83499c010be0e8bfc3bae8b91604a2ed.png

4.3. recv_needed_recovery & srv_force_recovery

接着我们来看下决定 validate 值的 2 个参数:recv_needed_recovery与srv_force_recovery,默认崩溃恢复时,recv_needed_recovery = 1 而 srv_force_recovery = 0 ,所以 validate = true,即需要进行表空间校验。

bool validate = recv_needed_recovery && srv_force_recovery == 0;//跳过表空间校验validate = false//执行表空间校验validate = true先看下recv_needed_recovery参数,默认为 0。MySQL 在启动时会比对checkpoint_lsn与flush_lsn。如果不相等,就会调用recv_init_crash_recovery方法将recv_needed_recovery置为。只有当 MySQL 正常关闭时,这 2 个 lsn 才会相等。另外一个小发现,MySQL 5.7 中服务起来后,什么操作都不做,checkpoint_lsn 永远会落后 9,所以即使你什么都不做,直接 kill -9 进程,也算是崩溃重启。

LOG---Log sequence number 2563079308Log flushed up to 2563079308Pages flushed up to 2563079308Last checkpoint at 2563079299

bb5d5dd8483a8e709043c9f90b882071.png

再来看下srv_force_recovery参数,默认值为 0,如果设置了 innodb_force_recovery ,那么 srv_force_recovery 的值就等于 innodb_force_recovery 的值,即只要配置了强制恢复,srv_force_recovery 就会大于 0。

4.4. dict_check_tablespaces_and_store_max_id

最后看下dict_check_tablespaces_and_store_max_id函数,根据注释介绍,这个函数会检查所有在数据字典中发现的表空间, 先检查每个共享表空间,然后检查每个独立表空间。

在崩溃恢复中,部分表空间已经在处理 redolog 时被打开(对应之前 GDB 调试时部分表未继续走下去),而其他没有被打开的表空间,将会通过比较数据字典中的 space_id 与表空间文件是否一致的方式进行验证(也就是之前所说的表空间校验过程)。

fd972f10b183db7bf1f11d80036c512d.png

五、测试验证

到这里,原理大概已经知道了,主要就是:MySQL 在崩溃恢复时,会遍历打开所有 ibd 文件的 header page 验证数据字典的准确性,如果 MySQL 中包含了大量表,这个校验过程就会比较耗时。那么我们可以模拟下这个场景,进一步验证,比如在测试库中用 sysbench 建 50W 张空表,然后模拟非正常关闭,对比下崩溃恢复时长。

06b871b9044ea0ab4b7d56d1af4b1008.png

可以看到 MySQL 下崩溃恢复确实和表数量有关,表总数越大,崩溃恢复时间越长。另外磁盘 IOPS 也会影响崩溃恢复时间,像这里开发库的 HDD IOPS 较低,因此面对大量的表空间,校验速度就非常缓慢。另外一个发现,MySQL 8 下正常启用时居然也会进行表空间校验,而故障恢复时则会额外再进行一次表空间校验,等于校验了 2 遍。不过 MySQL 8.0 里多了一个特性,即表数量超过 5W 时,会启用多线程扫描,加快表空间校验过程。

fbb1b695acc3f2faba36b5bf1d9b3a5e.png

MySQL 8.0.21 开始可以通过innodb_validate_tablespace_paths参数关闭正常启动时的表空间校验过程。

4da9a97943f54bbe633d5390d4bbb197.png

六、如何跳过校验

MySQL 5.7 下有方法可以跳过崩溃恢复时的表空间校验过程嘛?查阅了资料,方法主要有两种:1. 配置 innodb_force_recovery可以使 srv_force_recovery != 0 ,那么 validate = false,即可以跳过表空间校验。实际测试的时候设置 innodb_force_recovery =1,也就是强制恢复跳过坏页,就可以跳过校验,然后重启就是正常启动了。通过这种临时方式可以避免崩溃恢复后非常耗时的表空间校验过程,快速启动 MySQL,个人目前暂时未发现有什么隐患。2. 使用共享表空间替代独立表空间这样就不需要打开 N 个 ibd 文件了,只需要打开一个 ibdata 文件即可,大大节省了校验时间。自从听了姜老师讲过使用共享表空间替代独立表空间解决 drop 大表时性能抖动的原理后,感觉共享表空间在很多业务环境下,反而更有优势。

bool validate = recv_needed_recovery && srv_force_recovery == 0;

//跳过表空间校验

validate = false

//执行表空间校验

validate = true

临时冒出另外一种解决想法,即用 GDB 调试崩溃恢复,通过临时修改 validate 变量值让 MySQL 跳过表空间验证过程,然后让 MySQL 正常关闭,重新启动就可以正常启动了。但是实际测试发现,如果以 debug 模式运行,确实可以临时修改 validate 变量,跳过表空间验证过程,但是 debug 模式下代码运行效率大打折扣,反而耗时更长。而以非 debug 模式运行,则无法修改 validate 变量,想法破灭。

b9e24476f7e79f429cdb012a492d29fe.png

c9777a222b3283e275afa5b8e46172a2.png

附录:

https://dev.mysql.com/worklog/task/?id=7142

http://blog.symedia.pl/2015/11/mysql-56-and-57-crash-recovery.html

https://www.percona.com/community-blog/2019/07/23/impact-of-innodb_file_per_table-option-on-crash-recovery-time/

https://jira.mariadb.org/browse/MDEV-18733

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/396528.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

surfaceview结束后怎么处理_污泥压滤机处理后的污泥怎么处置

在污泥处理处置中,污泥压滤机处理污泥只是对污泥进行脱水,并没有实现污泥资源化处置。再进行污泥“减量化、无害化、资源化”处理时,许多企业用污泥压滤机对污泥脱水处理后就不知道怎么继续处置了,从而使污泥饼无处可去&#xff0…

js数组详解

1,什么是数组数组是值得有序集合,每个值叫做一个元素,而每个元素在数组中有一个位置,以数字表示,称为索引。js的数组是无类型的,数组元素可以是任意类型,同一个数组中的不同元素可能是对象或数组…

[转载]linux内存映射mmap原理分析

转自:http://blog.csdn.net/yusiguyuan/article/details/23388771 内存映射,简而言之就是将用户空间的一段内存区域映射到内核空间,映射成功后,用户对这段内存区域的修改可以直接反映到内核空间,同样,内核空…

冒泡、快速排序小结

1.冒泡排序 (1) 比较领近的两个数 (2) 如果左边的比右边的数字大,则交换位置 (3) 向右移动一位,继续比较相邻的两个数 排序示例: 一轮排序结束后,最大值的位置已经移动最右端,再次如此循环,最终经过n-1次则…

synchronized 异常_由浅入深,Java 并发编程中的 Synchronized

synchronized 作用synchronized 关键字是 Java 并发编程中线程同步的常用手段之一。1.1 作用:确保线程互斥的访问同步代,锁自动释放,多个线程操作同个代码块或函数必须排队获得锁,保证共享变量的修改能够及时可见,获得…

Linux内存分配机制之伙伴系统和SLAB

转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6539590.html 内核内存管理的一项重要工作就是如何在频繁申请释放内存的情况下,避免碎片的产生。这就要求内核采取灵活而恰当的内存分配策略。通常,内存分配一般有两种情况&#xff1a…

this.$modal.confirm 自定义按钮关闭_自定义函数,让你玩转Excel得心应手

让“自动更正”输入统一的文本,你是不是经常为输入某些固定的文本,如《电脑报》而烦恼呢?那就往下看吧。1.执行“工具→自动更正”命令,打开“自动更正”对话框。2.在“替换”下面的方框中输入“pcw”(也可以是其他字符,“pcw”用小写),在“替换为”下面的方框中输…

CCF-CSP 最大的矩形

问题描述在横轴上放了n个相邻的矩形,每个矩形的宽度是1,而第i(1 ≤ i ≤ n)个矩形的高度是hi。这n个矩形构成了一个直方图。例如,下图中六个矩形的高度就分别是3, 1, 6, 5, 2, 3。请找出能放在给定直方图里面积最大的矩…

MySQL的主从复制云栖社区_MySQL-主从复制

前言前篇说了作为运维在数据库块最起码要会两大技能,今天来说说第二技能--主从复制随着业务的增长,一台数据库服务器以满足不了需求了,负载过重,这时候就需要减压,实现负载均衡读写分离,一主一从或一主多从…

mysql 数据分析的步骤_数据分析8个主要步骤

# 在对数据进行分析时,主要细分为明确目标、应用思维和如下8个具体步骤:1、读取数据2、清洗数据3、操作数据4、转换数据5、整理数据6、分析数据7、展现数据8、总结报告接下来将介绍使用python来具体处理数据,包括上面几个步骤的实现&#xff…

一、win7下安装yii2

作者:PHP学习网 出处:http://www.viphper.com/?p1159 本文版权归作者,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。 之前在liunx上安装过yii…

vs dll必须和exe在同一个目录_Win10系统丢失 .dll 文件的三种解决方案教程

有时候开机或打开一个软件时,系统会提示无法启动程序,这是怎么回事呢?这是因为计算机丢失某个或某些dll文件,由于系统本身不存在这些运行库文件,需要进行添加才能使用该软件。方法一:下载丢失的.dll文件&am…

datagrid页面获取表单一条数据的例子

【问题背景】 最近在做ITOO考评的时候想从页面获取表单选中的数据: 【代码】 在数据网格(datagrid)组件包含两种方法来检索选中行数据: getSelected:取得第一个选中行数据,如果没有选中行,则返回…

Spring+SpringMVC+MyBatis+easyUI整合基础篇(十)SVN搭建

前言 前面一篇文章讲了一下版本控制,但其实这一篇并没有打算讲细节的,感觉应该自己去动手弄一下,后来考虑了一下,版本控制真的挺重要的,如果自己实在搭建不好反而不去使用的话,真的有点可惜,当然…

串口数据波形显示_【专题教程第6期】SEGGER的J-Scope波形上位机软件,RTT模式波形上传可飙到500KB/S...

【专题教程第6期】SEGGER的J-Scope波形上位机软件,RTT模式波形上传速度可狂飙到500KB/S左右说明:1、在实际项目中,很多时候,我们需要将传感器或者ADC的数值以波形的形式显示。通常的解决办法是用串口上位机,USB接口上位…

JavaScript-基础入门.0014.JavaScript内置对象

2019独角兽企业重金招聘Python工程师标准>>> 简单介绍: 说明: 内置对象就是不依赖宿主环境在程序执行之前已经存在的对象,不必显式的实例化内置对象,前面已经介绍了大部分内置对象,而Global和Math两个单体内置对象比较特殊,所以单独讲. Global对象: 说明: Js中不属于…

Java中字符串连接符(+)和append的区别

参考链接:https://www.jianshu.com/p/849f1d443b3a 文章结构: 第一部分:对的原理进行分析 第二部分: 和 append 循环对比(贴出代码,以及分别循环后的反编译字节码,来对两者进行对比)…

百度seo排名点击器_SEO整站优化思路 - 百度seo排名点击

原出处:超级排名系统原文链接:SEO整站优化思路 - 超级排名系统整站优化的大体思路包括哪些?下面超级排名系统小编详细给大家讲解下:一、建站优化我们在建立网站之前与建立网站的时候需要做的优化,包括标题优化、描述关…

unity 天空盒_Unity自定义可编程渲染管线(SRP)(二)——编写第一个自定义SRP

一句话描述,我们可以把SRP分解成两个部分,分别是SRP Asset,SRP Instance。SRP AssetSRP Asset是一个Unity Asset文件,用来存储渲染管线的特定配置信息,包含的信息有:游戏物体是否应该投射阴影;使…

【design pattern】工厂方法模式和抽象工厂模式

前言 设计模式分为三大类: 创建型模式:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式; 结构型模式:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式; 行为型模式&#xff1…