第15章:存储引擎和表类型 / 15.2. InnoDB存储引擎 / 15.2.8. 备份和恢复InnoDB数据库

15.2.8.1. 强制恢复

15.2.8.2. 检查点

安全数据库管理的关键是定期做备份。

InnoDB热备份工具是一个在线备份工具,你可以用它来在InnoDB数据库运行之时备份你的InnoDB数据库。InnoDB热备份工具不要求你关闭数据库,并且它不设置任何锁定或干扰你 正常的数据库处理。InnoDB热备份工具是非免费(商业的)附加软件,它每年的证书费用是每台MySQL服务器运行的计算机€390。请参阅InnoDB热备份主页以获得更详细的信息以及屏幕截图。

如果你可以关闭你的MySQL服务器,你可以生成一个包含InnoDB用来管理它的表的所有文件的二进制备份。使用如下步骤:

1.    关闭MySQL服务器,确信它是无错误关闭。

2.  复制你所有数据文件(ibdata文件和.ibd文件)到一个安全的地方。 

3.   复制你所有ib_logfile文件到一个安全的地方。

4.    复制my.cnf配置文件或文件到一个安全的地方。

5.    为你InnoDB表复制.frm文件到一个安全的地方。

复制对InnoDB表起作用,所以你可以使用MySQL复制能力来在需要高可用性的数据库站点保有一份数据库的复制。

除了刚才描述的二进制备份,你也应该周期性地用mysqldump转储你的数据库。这么做的原因是,二进制文件可能被破坏而你没有注意到。转储的文件被存储成为人可读的文本文件,所以定点表的损坏 修复变得更容易。再者,因为形式更简单,严重数据损坏的机会就更小。mysqldump 也有一个--single-transaction选项,你可以用它来做一个一致的快照而不用把其它客户端排除在外面。

要能够从上述的二进制备份恢复InnoDB数据库到现在,你必须让二进制日志功能打开正在运行的MySQL服务器。 然后你可以应用二进制日志到备份数据库以实现point-in-time恢复:

mysqlbinlog yourhostname-bin.123 | mysql

要从MySQL服务器的崩溃恢复,唯一需要的是重新启动它。InnoDB自动检查日志并执行到现在的数据库前滚。InnoDB自动回滚在崩溃时 呈现的未提交的事务。在恢复过程中,mysqld显示如下一些输出:

InnoDB: Database was not shut down normally.
InnoDB: Starting recovery from log files...
InnoDB: Starting log scan based on checkpoint at
InnoDB: log sequence number 0 13674004
InnoDB: Doing recovery: scanned up to log sequence number 0 13739520
InnoDB: Doing recovery: scanned up to log sequence number 0 13805056
InnoDB: Doing recovery: scanned up to log sequence number 0 13870592
InnoDB: Doing recovery: scanned up to log sequence number 0 13936128
...
InnoDB: Doing recovery: scanned up to log sequence number 0 20555264
InnoDB: Doing recovery: scanned up to log sequence number 0 20620800
InnoDB: Doing recovery: scanned up to log sequence number 0 20664692
InnoDB: 1 uncommitted transaction(s) which must be rolled back
InnoDB: Starting rollback of uncommitted transactions
InnoDB: Rolling back trx no 16745
InnoDB: Rolling back of trx no 16745 completed
InnoDB: Rollback of uncommitted transactions completed
InnoDB: Starting an apply batch of log records to the database...
InnoDB: Apply batch completed
InnoDB: Started
mysqld: ready for connections

如果数据库被损坏或磁盘出错,你必须从备份做恢复。在损坏的情况下,你首先应该找出一个没有被损坏的备份。恢复数据库备份之后,从二进制日志文件恢复。

在一些数据库损坏的情况下,仅仅转储,移除并重建一个或数个被破坏的表是足够的。你可以用CHECK TABLE SQL语句来检查表是否损坏,虽然CHECK TABLE正常地不检查每种可能的损坏,你可以使用innodb_tablespace_monitor来检查表空间文件内文件空间管理的完整性。

在一些情况下,明显地数据库损坏是因为操作系统损坏它自己的文件缓存,磁盘上的数据可能完好,最好是首先重启计算机。它可以消除那些显得是数据库页损坏的错误。

15.2.8.1. 强制恢复

如果数据库页被破坏,你可能想要用SELECT INTO OUTFILE从从数据库转储你的表,通常以这种方法获取的大多数数据是完好的。即使这样,损坏可能导致SELECT * FROM tbl_name或者InnoDB后台操作崩溃或断言,或者甚至使得InnoDB前滚恢复崩溃。 尽管如此,你可以用它来强制InnoDB存储引擎启动同时阻止后台操作运行,以便你能转储你的表。例如:你可以在重启服务器之前,在选项文件的[mysqld]节添加如下的行:

[mysqld]
innodb_force_recovery = 4

innodb_force_recovery被允许的非零值如下。一个更大的数字包含所有更小数字的预防措施。如果你能够用一个多数是4的选项值来转储你的表,那么你是比较安全的,只有一些在损坏的单独页面上的数据会丢失。一个为6的值更夸张,因为数据库页被留在一个陈旧的状态,这个状态反过来可以引发对B树和其它数据库结构的更多破坏。

·         1 (SRV_FORCE_IGNORE_CORRUPT)

即使服务器检测到一个损坏的页,也让服务器运行着;试着让SELECT * FROM tbl_name 跳过损坏的索引记录和页,这样有助于转储表。

·         2 (SRV_FORCE_NO_BACKGROUND)

阻止主线程运行,如果崩溃可能在净化操作过程中发生,这将阻止它。

·         3 (SRV_FORCE_NO_TRX_UNDO)

恢复后不运行事务回滚。

·         4 (SRV_FORCE_NO_IBUF_MERGE)

也阻止插入缓冲合并操作。如果你可能会导致一个崩溃。最好不要做这些操作,不要计算表统计表。

·         5 (SRV_FORCE_NO_UNDO_LOG_SCAN)

启动数据库之时不查看未完成日志:InnoDB把未完成的事务视为已提交的。

·         6 (SRV_FORCE_NO_LOG_REDO)

不要在恢复连接中做日志前滚。

数据库不能另外地带着这些选项中被允许的选项来使用。作为一个安全措施,当innodb_force_recovery被设置 为大于0的值时,InnoDB阻止用户执行INSERT, UPDATE或DELETE操作.

即使强制恢复被使用,你也可以DROP或CREATE表。如果你知道一个给定的表正在导致回滚崩溃,你可以移除它。你也可以用这个来停止由失败的大宗导入或失败的ALTER TABLE导致的失控 回滚。你可以杀掉mysqld进程,然后设置innodb_force_recovery为3,使得数据库被 挂起而不需要回滚,然后舍弃导致失控回滚的表。

15.2.8.2. 检查点

InnoDB实现一种被认识为“模糊”查点设置的检查点机制。InnoDB以小批量从缓冲池 刷新已修改的数据库页。没必要以单个批次刷新缓冲池,单批次刷新实际操作中可能会在检查点设置进程中停止用户SQL语句的处理。

在崩溃恢复中,InnoDB找寻被写进日志的检查点标签。它知道所有在该标签之前对数据库的修改被呈现在数据库的磁盘映像中。然后InnoDB从检查点往前扫描日志文件,对数据库应用已写入日志的修改。

InnoDB以循环方式写日志文件。所有使得缓冲池里的数据库页与磁盘上的映像不同的已提交修改必须出现在日志文件中 ,以备万一InnoDB需要做一个恢复。这意味着,当InnoDB开始重新使用一个日志文件,它需要确认在磁盘上的数据库页映像包含已写进InnoDB准备重新使用的日志文件里的修改。换句话 说,InnoDB必须创建一个检查点,这经常涉及已修改 数据库页到磁盘的刷新。

前面的叙述解释了为什么使你的日志文件非常大会在设置检查点中节约磁盘I/O。设置日志文件总的大小和缓冲池一样大或者甚至比缓冲池大通常是有意义的。大日志文件的缺点是崩溃恢复要花更长的时间,因为有更多写入日志的信息要应用到数据库上。