为了调查数据库页面损坏,您可以使用 SELECT ... INTO OUTFILE
从数据库中导出表。通常,以这种方式获得的大多数数据都是完整的。严重的损坏可能会导致 SELECT * FROM
语句或 tbl_name
InnoDB
后台操作意外退出或断言,甚至导致 InnoDB
前滚恢复崩溃。在这种情况下,可以使用 innodb_force_recovery
选项强制 InnoDB
存储引擎启动,同时阻止后台操作运行,以便您可以转储表。例如,可以在重新启动服务器之前将以下行添加到选项文件的 [mysqld]
部分:
[mysqld]
innodb_force_recovery = 1
有关使用选项文件的信息,请参阅 第 6.2.2.2 节“使用选项文件”。
仅在紧急情况下才将 innodb_force_recovery
设置为大于 0 的值,以便您可以启动 InnoDB
并转储表。在这样做之前,请确保您有数据库的备份副本,以防您需要重新创建它。值 4 或更大可能会永久损坏数据文件。仅在您已在数据库的单独物理副本上成功测试过该设置后,才在生产服务器实例上使用 innodb_force_recovery
设置 4 或更大。当强制 InnoDB
恢复时,您应该始终从 innodb_force_recovery=1
开始,并仅在必要时逐步增加该值。
innodb_force_recovery
默认值为 0(正常启动,不强制恢复)。innodb_force_recovery
允许的非零值为 1 到 6。较大的值包括较小值的功能。例如,值 3 包含值 1 和 2 的所有功能。
如果能够以 innodb_force_recovery
值 3 或更小转储表,则相对安全,因为只有损坏的单个页面上的某些数据会丢失。值 4 或更大被认为是危险的,因为数据文件可能会永久损坏。值 6 被认为是极端的,因为数据库页面处于过时状态,这反过来可能会将更多损坏引入 B 树 和其他数据库结构。
作为一项安全措施,当 innodb_force_recovery
大于 0 时,InnoDB
会阻止 INSERT
、UPDATE
或 DELETE
操作。innodb_force_recovery
设置为 4 或更大时,InnoDB
将处于只读模式。
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
)阻止 插入缓冲区 合并操作。如果它们会导致崩溃,则不执行合并操作。不计算表 统计数据。此值可能会永久损坏数据文件。使用此值后,请准备好删除并重新创建所有辅助索引。将
InnoDB
设置为只读。5
(SRV_FORCE_NO_UNDO_LOG_SCAN
)启动数据库时不查看 撤销日志:
InnoDB
会将未完成的事务也视为已提交。此值可能会永久损坏数据文件。将InnoDB
设置为只读。6
(SRV_FORCE_NO_LOG_REDO
)在恢复过程中不进行 重做日志 前滚。此值可能会永久损坏数据文件。使数据库页面处于过时状态,这反过来可能会将更多损坏引入 B 树和其他数据库结构。将
InnoDB
设置为只读。
您可以从表中 SELECT
以转储它们。如果 innodb_force_recovery
值为 3 或更小,则可以 DROP
或 CREATE
表。如果 innodb_force_recovery
值大于 3,也支持 DROP TABLE
。如果 innodb_force_recovery
值大于 4,则不允许使用 DROP TABLE
。
如果您知道某个给定表在回滚时导致意外退出,则可以将其删除。如果您遇到由失败的批量导入或 ALTER TABLE
导致的失控回滚,则可以终止 mysqld 进程并将 innodb_force_recovery
设置为 3
以在没有回滚的情况下启动数据库,然后 DROP
导致失控回滚的表。
如果表数据中的损坏导致您无法转储整个表内容,则包含 ORDER BY
子句的查询可能能够转储损坏部分之后的表部分。primary_key
DESC
如果需要较高的 innodb_force_recovery
值才能启动 InnoDB
,则可能存在损坏的数据结构,这可能会导致复杂查询(包含 WHERE
、ORDER BY
或其他子句的查询)失败。在这种情况下,您可能只能运行基本的 SELECT * FROM t
查询。