天天看点

MySQL InnoDB表恢复

14.18.2 InnoDB 恢复

本章节讲述InnoDB表恢复。内容包括:

Point-in-Time恢复

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

InnoDB崩溃恢复

崩溃恢复中的表空间发现(5.7引进)

从物理备份创建的时间节点开始恢复InnoDB库到当前时间,MySQL服务器必须开启二进制日志记录,甚至先于备份。从一份备份文件恢复后实现point-in-time恢复,可以应用二进制日志中记录的发生于文件备份之后的修改。参考Section 7.5, “Point-in-Time (Incremental) Recovery Using the Binary Log”。

如果数据库损坏或者发生磁盘故障,必须使用一个备份执行恢复。至于数据库损坏,首先要找一个完好的备份。恢复完这份基础备份之后,通过 mysqlbinlog和 mysql从二进制日志文件中实施一个point-in-time恢复,以恢复发生于文件备份之后的修改。

在某些数据库损坏的情况下,dump、drop然后re-create一张或者几张损坏的表足矣。可以使用CHECK TABLE语句来检查一张表是否损坏,即便CHECK TABLE本身并不能发现所有可能的损坏。

某些情况下,表面上的数据库数据页损坏实际上是源于操作系统自身文件缓存的损坏,而磁盘上的数据可能是OK的。首先最好尝试着重启一下电脑。这样可能消除出现数据库页损坏的错误。由于InnoDB的事务一致性问题,如果MySQL仍然有启动故障,参考Section 14.21.2, “Forcing InnoDB Recovery”以恢复模式逐步启动数据库实例来dump数据。

从MySQL服务器崩溃恢复唯一需要做的事情就是重启MySQL。InnoDB自动检查日志然后执行一个达到数据库当前状态的前滚操作。InnoDB自动回滚崩溃时执行的尚未提交的事务。在恢复过程中,mysqld显示类似于此的输出:

InnoDB: Log scan progressed past the checkpoint lsn 369163704

InnoDB: Doing recovery: scanned up to log sequence number 374340608

InnoDB: Doing recovery: scanned up to log sequence number 379583488

InnoDB: Doing recovery: scanned up to log sequence number 384826368

InnoDB: Doing recovery: scanned up to log sequence number 390069248

InnoDB: Doing recovery: scanned up to log sequence number 395312128

InnoDB: Doing recovery: scanned up to log sequence number 400555008

InnoDB: Doing recovery: scanned up to log sequence number 405797888

InnoDB: Doing recovery: scanned up to log sequence number 411040768

InnoDB: Doing recovery: scanned up to log sequence number 414724794

InnoDB: Database was not shutdown normally!

InnoDB: Starting crash recovery.

InnoDB: 1 transaction(s) which must be rolled back or cleaned up in

total 518425 row operations to undo

InnoDB: Trx id counter is 1792

InnoDB: Starting an apply batch of log records to the database...

InnoDB: Progress in percent: 0 1 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

InnoDB: Apply batch completed

...

InnoDB: Starting in background the rollback of uncommitted transactions

InnoDB: Rolling back trx with id 1511, 518425 rows to undo

InnoDB: Waiting for purge to start

InnoDB: 5.7.18 started; log sequence number 414724794

./mysqld: ready for connections.

InnoDB的crash recovery包含若干步骤:

表空间发现(5.7引进)

表空间发现是一个InnoDB用来识别应用重做日志所需要的表空间的过程。参考Tablespace Discovery During Crash Recovery。

应用重做日志

先于接受连接,初始化的时候执行重做日志。关机或者崩溃的时候,如果所有的数据库修改已经从buffer pool刷新回tablespaces(ibdata和.ibd文件),应用重做日志将被跳过。如果启动的时候重做日志文件丢失,InnoDB同样跳过应用重做日志。

移除重做日志以加速恢复是不值得推荐的,即便丢失一些数据是可以接受的。仅仅在设置innodb_fast_shutdown为0或者1而完全关闭MySQL后,才可以考虑移除重做日志。

关于InnoDB用来识别应用重做日志所需要的表空间的过程的信息,参考Tablespace Discovery During Crash Recovery。

回退未完成的事务

未完成的事务是数据库崩溃或者fast shutdown时正在执行的事务。依赖于服务器加载能力,回退一个未完成事务所花费的时间可能三四倍于中断前执行一个事务的时间。

无法取消正在回退中的事务。极端情况下,如果回退一个事务预计需要花费特别长的时间,可以通过设置innodb_force_recovery为3或者更大来加快启动InnoDB。参考Section 14.21.2, “Forcing InnoDB Recovery”。

合并Change buffer

从change buffer(部分为system tablespace)应用数据库修改到辅助索引的叶子页。因为索引页会被读进缓冲池。

Purge

删除被标识为待删除状态的不再对有效事务可见的记录。

除了记录日志,应用重做日志之后的步骤不再依赖于重做日志,以并行方式正常处理。这其中只有回退未完成的事务对于崩溃恢复是特别的。合并insert buffer和purge在正常处理时执行。

在大多数情况下,即便MySQL服务器在繁重的工作中意外地挂掉了,恢复处理自动进行而不需要DBA干预。如果硬件故障或者服务器系统错误损坏InnoDB数据,MySQL可能拒绝启动。在这种情况下,参考Section 14.21.2, “Forcing InnoDB Recovery”。

关于二进制日志和InnoDB崩溃恢复的信息,参考Section 5.4.4, “The Binary Log”。

崩溃恢复中,InnoDB如果遇到上一个checkpoint以后的重做日志写出,这些重做日志必须应用到相关受影响的表空间。崩溃恢复中识别相关受影响表空间的处理过程称作表空间发现。

通过扫描自上个checkpoint以来到重做日志末尾的写于表空间页修改时的MLOG_FILE_NAME记录来执行表空间发现。一个MLOG_FILE_NAME记录包含表空间的space ID和文件名。

崩溃恢复启动时,InnoDB打开系统表空间和重做日志。如果自上个checkpoint以来有重做日志记录写出,基于MLOG_FILE_NAME记录,受影响的表空间文件被打开。

MLOG_FILE_NAME会记录所有的连续性的表空间类型,包括file-per-table tablespace,general tablespace,system tablespace和undo log tablespace。

基于重做日志的表空间发现有如下特性:

自上个checkpoint以来只有修改过的表空间.ibd文件被访问。

应用重做日志时与InnoDB实例无关的表空间.ibd文件被忽略。

如果重做日志扫描部分引用的表空间文件丢失,崩溃恢复启动将被拒绝。

对于表空间*.ibd文件的丢失,只有当重做日志中有文件删除记录(MLOG_FILE_DELETE)时才会被忽略。例如,在没有MLOG_FILE_DELETE记录的情况下,一个表重命名错误可能导致一个“missing” .ibd文件。在这种情况下,可以手动重命名表空间文件然后重启崩溃恢复,或者使用innodb_force_recovery选项以恢复模式重启MySQL服务器。以恢复模式启动服务器时,丢失.ibd文件将被忽略。

基于重做日志的表空间发现,引进于MySQL 5.7,通过构造一个应用重做日志所需要的“space ID-to-tablespace file name”映射,替换MySQL早前版本中使用的目录扫描

————————————————

相信坚持的力量,日复一日的习惯.