《MySQL技术内幕:InnoDB存储引擎第2版》——2.7 启动、关闭与恢复

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介: 本节书摘来自华章计算机《MySQL技术内幕:InnoDB存储引擎第2版》一书中的第2章,第2.7节,作者:姜承尧著, 更多章节内容可以访问云栖社区“华章计算机”公众号查看。

2.7 启动、关闭与恢复

InnoDB是MySQL数据库的存储引擎之一,因此InnoDB存储引擎的启动和关闭,更准确的是指在MySQL实例的启动过程中对InnoDB存储引擎的处理过程。
在关闭时,参数innodb_fast_shutdown影响着表的存储引擎为InnoDB的行为。该参数可取值为0、1、2,默认值为1。
?0表示在MySQL数据库关闭时,InnoDB需要完成所有的full purge和merge insert buffer,并且将所有的脏页刷新回磁盘。这需要一些时间,有时甚至需要几个小时来完成。如果在进行InnoDB升级时,必须将这个参数调为0,然后再关闭数据库。
?1是参数innodb_fast_shutdown的默认值,表示不需要完成上述的full purge和merge insert buffer操作,但是在缓冲池中的一些数据脏页还是会刷新回磁盘。
?2表示不完成full purge和merge insert buffer操作,也不将缓冲池中的数据脏页写回磁盘,而是将日志都写入日志文件。这样不会有任何事务的丢失,但是下次MySQL数据库启动时,会进行恢复操作(recovery)。
当正常关闭MySQL数据库时,下次的启动应该会非常“正常”。但是如果没有正常地关闭数据库,如用kill命令关闭数据库,在MySQL数据库运行中重启了服务器,或者在关闭数据库时,将参数innodb_fast_shutdown设为了2时,下次MySQL数据库启动时都会对InnoDB存储引擎的表进行恢复操作。
参数innodb_force_recovery影响了整个InnoDB存储引擎恢复的状况。该参数值默认为0,代表当发生需要恢复时,进行所有的恢复操作,当不能进行有效恢复时,如数据页发生了corruption,MySQL数据库可能发生宕机(crash),并把错误写入错误日志中去。
但是,在某些情况下,可能并不需要进行完整的恢复操作,因为用户自己知道怎么进行恢复。比如在对一个表进行alter table操作时发生意外了,数据库重启时会对InnoDB表进行回滚操作,对于一个大表来说这需要很长时间,可能是几个小时。这时用户可以自行进行恢复,如可以把表删除,从备份中重新导入数据到表,可能这些操作的速度要远远快于回滚操作。
参数innodb_force_recovery还可以设置为6个非零值:1~6。大的数字表示包含了前面所有小数字表示的影响。具体情况如下:
?1(SRV_FORCE_IGNORE_CORRUPT):忽略检查到的corrupt页。
?2(SRV_FORCE_NO_BACKGROUND):阻止Master Thread线程的运行,如Master Thread线程需要进行full purge操作,而这会导致crash。
?3(SRV_FORCE_NO_TRX_UNDO):不进行事务的回滚操作。
?4(SRV_FORCE_NO_IBUF_MERGE):不进行插入缓冲的合并操作。
?5(SRV_FORCE_NO_UNDO_LOG_SCAN):不查看撤销日志(Undo Log),InnoDB存储引擎会将未提交的事务视为已提交。
?6(SRV_FORCE_NO_LOG_REDO):不进行前滚的操作。
需要注意的是,在设置了参数innodb_force_recovery大于0后,用户可以对表进行select、create和drop操作,但insert、update和delete这类DML操作是不允许的。
现在来做一个实验,模拟故障的发生。在第一个会话中(session),对一张接近1?000万行的InnoDB存储引擎表进行更新操作,但是完成后不要马上提交:

mysql>START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)

mysql>UPDATE Profile SET password='';
Query OK, 9587770 rows affected (7 min 55.73 sec)
Rows matched: 9999248  Changed: 9587770  Warnings: 0

START TRANSACTION语句开启了事务,同时防止了自动提交(auto commit)的发生,UPDATE操作则会产生大量的UNDO日志(undo log)。这时,人为通过kill命令杀掉MySQL数据库服务器:

[root@nineyou0-43 ~]# ps -ef | grep mysqld
root    28007     1  0 13:40 pts/1    00:00:00 /bin/sh./bin/mysqld_safe --datadir =/usr/local/mysql/data --pid-file=/usr/local/mysql/data/nineyou0-43.pid
mysql   28045 28007 42 13:40 pts/1    00:04:23 /usr/local/mysql/bin/mysqld -- basedir =/usr/local/mysql --datadir=/usr/local/mysql/data --user=mysql --pid-file=/usr/local/mysql/data/nineyou0-43.pid --skip-external-locking --port=3306 --socket=/tmp/mysql.sock
root    28110 26963  0 13:50 pts/11    00:00:00 grep mysqld
[root@nineyou0-43 ~]# kill -9 28007
[root@nineyou0-43 ~]# kill -9 28045

通过kill命令可以模拟数据库的宕机操作。下次MySQL数据库启动时会对之前的UPDATE事务进行回滚操作,而这些信息都会记录在错误日志文件(默认后缀名为err)中。如果查看错误日志文件,可得如下结果:

090922 13:40:20  InnoDB: Started; log sequence number 6 2530474615
InnoDB: Starting in background the rollback of uncommitted transactions
090922 13:40:20  InnoDB: Rolling back trx with id 0 5281035, 8867280 rows to undo

InnoDB: Progress in percents: 1090922 13:40:20 
090922 13:40:20 [Note] /usr/local/mysql/bin/mysqld: ready for connections.
Version: '5.0.45-log'  socket: '/tmp/mysql.sock'  port: 3306  MySQL Community Server (GPL)
 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
InnoDB: Rolling back of trx id 0 5281035 completed
090922 13:49:21  InnoDB: Rollback of non-prepared transactions completed

可以看到,采用默认的策略,即将innodb_force_recovery设为0,InnoDB会在每次启动后对发生问题的表进行恢复操作。通过错误日志文件,可知这次回滚操作需要回滚8867280行记录,差不多总共进行了9分钟。
再做一次同样的测试,只不过这次在启动MySQL数据库前,将参数innodb_force_recovery设为3,然后观察InnoDB存储引擎是否还会进行回滚操作。查看错误日志文件,可得:

090922 14:26:23  InnoDB: Started; log sequence number 7 2253251193
InnoDB: !!!innodb_force_recovery is set to 3 !!!
090922 14:26:23 [Note] /usr/local/mysql/bin/mysqld: ready for connections.
Version: '5.0.45-log'  socket: '/tmp/mysql.sock'  port: 3306  MySQL Community Server (GPL)

这里出现了“!!!”,InnoDB警告已经将innodb_force_recovery设置为3,不会进行回滚操作了,因此数据库很快启动完成了。但是用户应该小心当前数据库的状态,并仔细确认是否不需要回滚事务的操作。

相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
1月前
|
存储 关系型数据库 MySQL
MySQL InnoDB数据存储结构
MySQL InnoDB数据存储结构
|
1月前
|
存储 缓存 关系型数据库
MySQL的varchar水真的太深了——InnoDB记录存储结构
varchar(M) 能存多少个字符,为什么提示最大16383?innodb怎么知道varchar真正有多长?记录为NULL,innodb如何处理?某个列数据占用的字节数非常多怎么办?影响每行实际可用空间的因素有哪些?本篇围绕innodb默认行格式dynamic来说说原理。
828 6
MySQL的varchar水真的太深了——InnoDB记录存储结构
|
1月前
|
存储 缓存 关系型数据库
Mysql的两种存储引擎以及区别
Mysql的两种存储引擎以及区别
14 1
|
1月前
|
存储 关系型数据库 MySQL
Mysql第七天,存储引擎
Mysql第七天,存储引擎
60 0
Mysql第七天,存储引擎
|
1月前
|
存储 关系型数据库 MySQL
【MySQL 数据库】5、存储引擎
【MySQL 数据库】5、存储引擎
98 0
|
1月前
|
存储 关系型数据库 MySQL
最全MySQL面试60题(含答案):存储引擎+数据库锁+索引+SQL优化等
最全MySQL面试60题(含答案):存储引擎+数据库锁+索引+SQL优化等
157 0
|
7天前
|
存储 关系型数据库 MySQL
MySQL引擎对决:深入解析MyISAM和InnoDB的区别
MySQL引擎对决:深入解析MyISAM和InnoDB的区别
20 0
|
1月前
|
存储 缓存 关系型数据库
MySQL两种存储引擎及区别
MySQL两种存储引擎及区别
21 4
MySQL两种存储引擎及区别
|
1月前
|
存储 关系型数据库 MySQL
MySQL中常见的存储引擎类型
【2月更文挑战第18天】
46 7
|
3月前
|
存储 SQL 关系型数据库
系统设计场景题—MySQL使用InnoDB,通过二级索引查第K大的数,时间复杂度是多少?
系统设计场景题—MySQL使用InnoDB,通过二级索引查第K大的数,时间复杂度是多少?
46 1
系统设计场景题—MySQL使用InnoDB,通过二级索引查第K大的数,时间复杂度是多少?