MySQL OCP888题解008-InnoDB recovery原理

1、原题

1.1、英文原题

Which two statements describe how InnoDB recovery works?[1]
A. InnoDB handles most crash recoveries automatically.
B. InnoDB blocks some operations when innodb force recovery is set to greater than 0.
C. There will in general be lost committed transactions after a crash using the default settings.
D. It is required to enable binlog_gtid_simple_recovery to perform a crash recovery.
E. It is recommended to set innodb_force_recovery=1 as part of normal operations.
F. It is always required to enable innodb_force_recovery to perform a crash recovery.

1.2、中文翻译

哪两个陈述描述了InnoDB恢复的工作原理?
A、InnoDB自动处理大多数崩溃恢复。
B、当InnoDB将innodb_force_recovery设置为大于0时,InnoDB会阻止一些操作。
C、使用默认设置,崩溃后通常会丢失已提交的事务。
D、需要启用binlog_gtid_simple_recovery以执行崩溃恢复。
E、建议将innodb_force_recovery设置为1,作为正常操作的一部分。
F、总是需要启用innodb_force_recovery以执行崩溃恢复。

1.3、答案

A、B

2、题目解析

2.1、题干解析

本题考察InnoDB恢复机制。

2.2、选项解析

2.2.1、选项A解析

对于发生崩溃,MySQL一般只需重启,在重启时会回滚未提交的事务,即可完成崩溃恢复,所以崩溃恢复一般自动处理。所以选项A正确。

2.2.2、选项B解析

innodb_force_recovery默认为0,当其值大于0时,InnoDB在启动时会通过阻止一些操作的发生从而强制启动。因此选项B正确。

2.2.3、选项C解析

崩溃恢复不会丢失已提交的事务,只会回滚崩溃时未提交的事务。

2.2.4、选项D解析

binlog_gtid_simple_recovery变量控制当MySQL启动或重新启动时,在搜索GTIDs期间如何迭代二进制日志文件,跟崩溃恢复没关系。因此选项D错误。

2.2.5、选项E解析

innodb_force_recovery默认为0,设置为大于0时会在启动时跳过一些操作,并可能导致数据文件损坏,因此不能默认为1。所以选项E错误。

2.2.6、选项F解析

绝大多数情况下不需要做任何操作,只需要重启MySQL即可完成崩溃恢复,并不需要设置innodb_force_recovery。所以选项F错误。

3、知识点

3.1、知识点1:InnoDB恢复机制

3.1.1、Point-in-Time Recovery(时间点恢复)

时间点恢复是指恢复到某一特定时间点的数据变化。通常情况下,这种类型的恢复是在恢复一个完整的备份后进行的,该备份将服务器恢复到备份时的状态。时间点恢复将服务器从完整备份的时间逐步恢复到最近的时间。要将InnoDB数据库从进行物理备份的时间恢复到当前,你必须在启用二进制日志的情况下运行MySQL服务器,甚至在进行备份之前。为了在恢复备份后实现时间点恢复,你可以应用备份后发生的二进制日志的变化。

官方参考文档

3.1.1.1、使用二进制日志做时间点恢复

时间点恢复的信息来源是完整备份操作之后产生的一组二进制日志文件。因此,为了使服务器能够恢复到时间点,必须在其上启用二进制日志。

  1. 要从二进制日志中恢复数据,可以通过mysql> SHOW BINARY LOGS;显示当前二进制日志文件的名称和位置。
  2. 要确定当前二进制日志文件的名称,可以通过mysql> SHOW MASTER STATUS;
  3. 可以通过mysqlbinlog工具将二进制日志文件中的事件从二进制格式转换为文本格式,以便可以查看或应用。应用二进制日志的事件会导致它们所代表的数据修改被重新执行。这使得恢复给定时间范围内的数据变化。为了应用二进制日志中的事件,使用mysql客户端处理mysqlbinlog输出:mysqlbinlog binlog_files | mysql -u root -p

官方参考文档

3.1.1.2、使用事件位置做时间点恢复

作为一个例子,假设在2020年5月27日13:00:00左右,一个SQL语句被执行,删除了一个表。你可以执行一个时间点恢复,将服务器恢复到表被删除前的状态。以下是实现这一目的的一些示例步骤。

  • 恢复在感兴趣的时间点(称之为tp,在我们的例子中是2020年5月27日13:00:00)之前创建的最后一个完整备份。完成后,注意你恢复服务器的二进制日志位置,以便以后使用,并重新启动服务器。
  • 找到与你想恢复数据库的时间点相对应的精确二进制日志事件位置。在我们的例子中,鉴于我们知道表删除发生的大致时间(tp),我们可以通过使用mysqlbinlog工具检查该时间点附近的日志内容来找到日志位置。使用-start-datetime和-stop-datetime选项,指定tp周围的一个短的时间段,然后在输出中寻找该事件。比如说如下:从mysqlbinlog的输出中,可以在1868年的#行和1985年的#行之间的二进制日志段中找到DROP TABLE pets.cats语句,这意味着该语句发生在1868年的日志位置之后,而日志在DROP TABLE语句之后的1985位置。
$> mysqlbinlog --start-datetime="2020-05-27 12:59:00" --stop-datetime="2020-05-27 13:06:00"  --verbose /var/lib/mysql/bin.123456 | grep -C 12 "DROP TABLE"
  • 将二进制日志文件中的事件应用到服务器上,从你在步骤1中找到的日志位置开始(假设是1006),到你在步骤2中找到的、在你感兴趣的时间点(即1868)之前的位置结束。
$> mysqlbinlog --start-position=1006 --stop-position=1868 /var/lib/mysql/bin.123456  | mysql -u root -p
  • 在已经完成的时间点恢复之外,如果你还想重新执行你感兴趣的时间点之后的所有语句,再次使用mysqlbinlog将tp之后的所有事件应用到服务器。我们在第2步中注意到,在我们想跳过的语句之后,日志处于1985位置;我们可以用它来做-start-position选项,这样,该位置之后的任何语句都被包括在内。
$> mysqlbinlog --start-position=1985 /var/lib/mysql/bin.123456  | mysql -u root -p
  • 这样,你的数据库已经恢复了二进制日志文件中记录的最新语句,但跳过了选定的事件。

官方参考文档

3.1.2、从数据损坏或磁盘故障中恢复

  • 如果你的数据库被损坏或发生磁盘故障,你必须使用备份来进行恢复。在损坏的情况下,首先找到一个没有损坏的备份。在恢复基础备份后,使用mysqlbinlog和mysql从二进制日志文件中做一个时间点恢复,以恢复备份后发生的变化。
  • 在某些数据库损坏的情况下,只需转储、丢弃和重新创建一个或几个损坏的表即可。你可以使用CHECK TABLE语句来检查一个表是否损坏。

官方参考文档

3.1.3、InnoDB Crash Recovery(崩溃恢复)

要从一个意外的MySQL服务器退出中恢复,唯一需要做的是重新启动MySQL服务器。InnoDB会自动检查日志并执行数据库的回滚到当前,其中InnoDB会自动回滚崩溃时未提交的事务。

  • InnoDB的崩溃恢复包括几个步骤:
  1. 表空间发现:表空间发现是InnoDB用来识别需要应用重做日志的表空间的过程。
  2. 重做日志应用:重做日志应用是在初始化期间,在接受任何连接之前进行的。如果在关机或崩溃时,所有的变更都从缓冲池冲刷到了表空间(ibdata* 和 .ibd文件),那么重做日志的应用将被跳过。如果重做日志文件在启动时丢失,InnoDB也会跳过重做日志的应用。在重做日志应用之后的步骤并不依赖于重做日志(除了记录写入的内容)。在重做日志应用之后,InnoDB试图尽早接受连接,以减少停机时间。
  3. 回滚未完成的事务:不完整的事务是指在意外退出或快速关机时正在活动的任何事务。不能取消正在回滚的事务。在极端情况下,当回滚事务预计需要特别长的时间时,在innodb_force_recovery设置为3或更高的情况下启动InnoDB可能会更快。
  4. change buffer合并:将change buffer(系统表空间的一部分)的变化应用于二级索引的叶子页,因为索引页被读到缓冲池中。
  5. 清除:删除有删除标记的记录,这些记录应该对活动事务不再可见。

官方参考文档

3.1.4、Forcing InnoDB Recovery(InnoDB强制恢复)

innodb_force_recovery系统变量默认值为0,如果在配置文件里设置该变量的值大于0且重启,则MySQL服务器在启动时会略过一些操作,这样可以让MySQL不会因为某些数据或文件的损坏而无法启动,从而强制让MySQL数据库恢复。innodb_force_recovery允许的非零值是1到6,值越大,则跳过的操作越多,但也意味着更危险,可能导致数据文件被永久损坏,特别是4或更大的数值。

强制恢复的配置方法是:在重启服务器之前,在选项文件的[mysqld]部分添加以下一行。

[mysqld]
innodb_force_recovery = 1

innodb_force_recovery系统变量

  • 默认为0(正常启动,没有强制恢复)。innodb_force_recovery允许的非零值是1到6。一个较大的值包括较小值的功能。例如,一个3的值包括了1和2的所有功能。
  • 只有在紧急情况下才将innodb_force_recovery设置为大于0的值,这样才能启动InnoDB并转储你的表。在这样做之前,确保你有一个数据库的备份,以备你需要重新创建它。4或更大的值会永久地损坏数据文件。当强制InnoDB恢复时,你应该总是从innodb_force_recovery=1开始,并且只在必要时逐步增加该值。
  • 如果你能够在innodb_force_recovery值为3或更小的情况下转储你的表,那么你是相对安全的,只有损坏的个别页面上的一些数据会丢失。4或更大的值被认为是危险的,因为数据文件可能被永久地损坏。6的值被认为是剧烈的,因为数据库页被留在一个过时的状态,这反过来可能会给B-树和其他数据库结构带来更多的损坏。

3.2、binlog_gtid_simple_recovery系统变量

这个变量控制当MySQL启动或重新启动时,在搜索GTIDs期间如何迭代二进制日志文件。

官方参考文档

4、总结

  • InnoDB如果发生崩溃,一般重启即可崩溃恢复。崩溃恢复时,会将崩溃时未提交的事务回滚。
  • InnoDB可以基于完整备份+二进制日志实现将数据库恢复到某个时间点。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值