6 备份和恢复 InnoDB 数据库

安全的数据库管理就是使用正规的数据备份。

InnoDB Hot Backup 是一个在线备份工具,你可以在 InnoDB 数据库运行时使用它来实现在线备份。InnoDB Hot Backup 不需要你关闭你的服务器也不需要加任何锁或影响其它普通的数据操作。InnoDB Hot Backup 是一个非免费的附加工具,它的费用为每 MySQL 服务器每年 400 欧元。浏览网页 InnoDB Hot Backup homepage 可获得更多的信息以及程序屏幕截图。

如果你可以关闭你的 MySQL 服务,那么可以通过下面几个步骤进行数据库的“二进制”备份:

在需要高性能的数据库服务站点上,可以通过 MySQL 的复制特性来保持数据库的一个副本,MySQL 的复制特性同样适用于 InnoDB 表类型。

除了上面描述的二进制备份方式之外,最好定期地使用 mysqldump 转储数据表。原因是二进制文件可能会在你未注意时而被破坏,而表转储(dump)文件是以文本文件方式保存的,它与二进制文件相比更简单、有更好的的可读性。因为转储文件更简单所以更容易发现表损坏, 重要数据损环的可能性很小。

一个好的主意就是在对数据库做二进制备份的同时也做一个转储(dump)备份。为了得到一致的数据快照,必须关闭所有客户端的连接。然后就可以进行二进制备份,这样你就有了数据一致的两种格式的备份。

如了实现通过上面所述的二进制备份方法将 InnoDB 数据库恢复到当前状态,必须打开 MySQL 的二进制日志(binlogging)开关。这样你就可以二进制日志 与备份数据配合实现分时间点的恢复:

mysqlbinlog yourhostname-bin.123 | mysql
	

 

为了恢复一个崩溃了的 MySQL 服务进程,你所能做的唯一一件事就是重新启动。InnoDB 将自动地检查日志并完成数据库的前滚(roll-forward)到当前状态。同时,InnoDB 将自动回滚崩溃前未提交的事务。在恢复过程中,mysqld 将显示如下所示的提示:

heikki@donna:~/mysql-3.23.48/sql> mysqld
	020204 23:08:31  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 177573790
	InnoDB: Doing recovery: scanned up to log sequence number 0 177638912
	InnoDB: Doing recovery: scanned up to log sequence number 0 177704448
	InnoDB: Doing recovery: scanned up to log sequence number 0 177769984
	InnoDB: Doing recovery: scanned up to log sequence number 0 177835520
	InnoDB: Doing recovery: scanned up to log sequence number 0 177901056
	InnoDB: Doing recovery: scanned up to log sequence number 0 177966592
	InnoDB: Doing recovery: scanned up to log sequence number 0 178032128
	InnoDB: Doing recovery: scanned up to log sequence number 0 178097664
	InnoDB: Doing recovery: scanned up to log sequence number 0 178163200
	InnoDB: Doing recovery: scanned up to log sequence number 0 178228736
	InnoDB: After this prints a line for every 10th scan sweep:
	InnoDB: Doing recovery: scanned up to log sequence number 0 178884096
	...
	InnoDB: Doing recovery: scanned up to log sequence number 0 193302016
	InnoDB: Doing recovery: scanned up to log sequence number 0 193957376
	InnoDB: Doing recovery: scanned up to log sequence number 0 194612736
	020204 23:08:40  InnoDB: Starting an apply batch of log records to the database.
	..
	InnoDB: Progress in percents: 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 7
	3 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: Doing recovery: scanned up to log sequence number 0 195268096
	InnoDB: Doing recovery: scanned up to log sequence number 0 195923456
	...
	InnoDB: Doing recovery: scanned up to log sequence number 0 203132416
	InnoDB: Doing recovery: scanned up to log sequence number 0 203787776
	InnoDB: Doing recovery: scanned up to log sequence number 0 204443136
	InnoDB: 5 uncommitted transaction(s) which must be rolled back
	InnoDB: Trx id counter is 0 129792
	InnoDB: Starting rollback of uncommitted transactions
	InnoDB: Rolling back trx with id 0 129400
	InnoDB: Rolling back of trx id 0 129400 completed
	InnoDB: Rolling back trx with id 0 129217
	InnoDB: Rolling back of trx id 0 129217 completed
	InnoDB: Rolling back trx with id 0 129098
	InnoDB: Rolling back of trx id 0 129098 completed
	InnoDB: Rolling back trx with id 0 128743
	InnoDB: Rolling back of trx id 0 128743 completed
	InnoDB: Rolling back trx with id 0 127939
	InnoDB: Rolling back of trx id 0 127939 completed
	InnoDB: Rollback of uncommitted transactions completed
	020204 23:08:51  InnoDB: Starting an apply batch of log records to the database.
	..
	InnoDB: Progress in percents: 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 7
	3 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: Last MySQL binlog file offset 0 40418561, file name ./donna-bin.001
	020204 23:08:53  InnoDB: Flushing modified pages from the buffer pool...
	020204 23:09:03  InnoDB: Started
	mysqld: ready for connections
	

如果数据库遭到损坏或磁盘失败,则不得不从一个备份文件恢复。在损坏的情况下,首先可以恢复一个未损坏的备份文件。然后依照 MySQL 手册提示从一般的日志文件中恢复数据。

在某些数据库损坏的情况下,可能通过转储(dump)、撤销(drop)和重新建立一个或多个损坏的表就足够了。可怜通过 CHECK TABLE SQL 命令检查一个受损的表,虽然 CHECK TABLE 并不能发现所有的损坏类型。你可能使用 innodb_tablespace_monitor 来检查数据文件时的文件空间管理的完整性。

在某些情况下,数据库页面显示损坏,而实际上是由于操作系统的文件高速缓冲损坏,而磁盘上的数据文件还是好的。 这时最好先重起你的系统。这可能解决数据库页面错误。

6.1 强制(Forcing)恢复

如果出现数据库页面损坏,可以通过 SELECT INTO OUTFILE 从数据库中转储出表数据,通常大部分的数据并未受损坏。 但是这些损坏可能引起 SELECT * FROM table 或 InnoDB 后台操作崩溃或中断(assert),甚至是 InnoDB 的前滚(roll-forward)恢复崩溃。从 InnoDB version 3.23.44 开始,在 my.cnf 中有个设置选项可以强制 InnoDB 启动,以及防止后台操作的运行,因而你可以转储数据。例如,你可以 my.cnf 在中加入如下设置:

set-variable = innodb_force_recovery = 4

 

innodb_force_recovery 代替选择将在下面列出。 这个参数不能用于数据库的其它方面!当设置值大于 0 时,作为安全尺度,InnoDB 禁止用户使用 INSERT, UPDATE, 或 DELETE

从 3.23.53 和 4.0.4 开始,即使强制恢复被使用你也可以使用 DROP CREATE 一个表。 如果你确定表如引起回滚崩溃,你可以移除(drop)它。你也可以通过这个停止一个因导入大量数据或 ALTER TABLE 而引起的失控(runaway)回滚。你可以杀死 mysqld 进程,并使用 my.cnf 设置项 innodb_force_recovery=3 不使用回滚。然后就可以 DROP 那个引起失控(runaway)回滚的表。

下面较大的数意味着包含所有较低数所对就的安全防范。为了能够转储表设置至少为 4 ,这是相对安全的,仅仅只有一些损坏的页面数据掉失。Option 6 is more dramatic, because database pages are left in an obsolete state, which in turn may introduce more corruption into B-trees and other database structures.

 

6.2 检查点(Checkpoints)

InnoDB 通过调用一个模糊的检查点来实现检查点机制。InnoDB 以很小的批量从缓冲池中刷新修改了的数据库页面。这就不需要在一个批量中刷新整个缓冲池,因这个实话上将可能停止用户 SQL 语句运行进程一段时间。

In crash recovery InnoDB 在崩溃修复时会检查记录在日志文件中的检查点标签。它知道,在标签前所有对数据库的修改已被记录到数据库的磁盘镜像中。然后 InnoDB 扫描日志文件中检查点后面的日志并将修改记入数据库。

InnoDB 以一个环形方式记录日志文件。所有使缓冲池中的数据库页面与磁盘镜像不相同已提交了的修改必须记录在日志文件中,以防 InnoDB 需要恢复。 这就意味着 InnoDB 以环形方式重新启用一个日志文件,它必须确定将被重新使用的日志文件中的操作日志结果已被磁盘镜像文件包含。用另一句话来说就是,InnoDB 必须时常地建立检查点并将修改了的数据库页面更新到磁盘中。

上面所述要以解释为什么将日志文件设置和大一点可以减少因建立检查点所用的磁盘 I/O。 这就可以理解设置日志文件的总尺寸与缓冲池一样大或更大。大的日志文件的缺点就是当进行崩溃修复时将需要很长的时间,因为有更多的操作日志需要更新到数据库中。