强制InnoDB恢复log sequence number is in the future

InnoDB I/O问题的故障排除步骤取决于问题发生的时间: 在MySQL服务器启动期间,或者在DML或DDL语句由于文件系统级别的问题而失败的正常操作期间。

初始化问题

如果InnoDB尝试初始化其表空间或日志文件时出错,请删除由InnoDB创建的所有文件:所有ibdata文件和所有重做日志文件(MySQL 8.0.30和更高版本中的ib_redoN文件或早期版本中的ib_logfile文件)。如果您创建了任何InnoDB表,也要删除任何表。MySQL数据库目录中的ibd文件。然后再次尝试初始化InnoDB。为了进行最简单的故障排除,从命令提示符启动MySQL服务器,这样您就可以看到发生了什么。

运行时问题

如果InnoDB在文件操作期间打印出操作系统错误,通常该问题有以下解决方案之一:
☑ 确保InnoDB数据文件目录和InnoDB日志目录存在
☑ 确保mysqld有权在这些目录中创建文件
☑ 确保mysqld可以读取正确的my.cnf或my.ini选项文件,以便它从您指定的选项开始
☑ 请确保磁盘未满,并且没有超出任何磁盘配额
☑ 确保您为子目录和数据文件指定的名称不冲突
☑ 请仔细检查innodb_data_home_dir和innodb_data_file_path值的语法。特别是innodb_data_file_path选项中的任何最大值都是一个硬限制,超过该限制会导致致命错误

故障排除恢复故障

从MySQL 8.0.26开始,在重做日志恢复完成并且数据字典动态元数据(srv_dict_metadata)传输到数据字典表(dict_table_t)对象之前,不允许检查点和推进检查点LSN。如果在恢复期间或恢复之后(但在将数据字典动态元数据传输到数据字典表对象之前),重做日志由于此更改而耗尽了空间,则可能需要重新启动innodb_force_recovery,至少从SRV_FORCE_NO_IBUF_MERGE设置开始,或者在失败的情况下,从SRV_FORCE_NO_LOG_REDO设置开始。如果在这种情况下innodb_force_recovery重启失败,则可能需要从备份中恢复。

这个问题通常发生在以下更改之后:

☑ 如果InnoDB日志文件被删除且这些事件其中之一或更多发生在删除之前(没有任何一个事件是自己发生的—它由以下事件之一以及删除日志文件两个条件而引起):
1.硬件服务器崩溃
2.Mysqld进程由于kill ‐9或其他原因终止。
3.数据从一个热备份中恢复。
4.在使用innodb_fast_shutdown = 2时,MySQL被关闭。
☑ MySQL从一个InnoDB不存在或来自其他备份的备份被恢复。
☑ MySQL从一个不一致的备份被恢复。
☑ 在innodb_force_recovery = 6时,MySQL被启动。

原因

根本原因是InnoDB日志文件(重做日志)与数据文件不同步
• 当InnoDB中发生更改,更改在被写入数据文件之前先被写入日志文件。在 innodb_fast_shutdown = 0或1 (默认) 的正常关闭期间,InnoDB会写一个比所有页中的位置更晚的检查点位置,因为它会将它们都刷掉,然后在服务器关闭之前写一个检查点。当innodb_fast_shutdown = 2时,它将它到达的位置写作检查点但不将任何页刷新到当前位置,所以会需要崩溃恢复。该崩溃恢复不会直接引起这个错误,但如果日志文件删除就会引起,就像在崩溃后能删除它们一样。
• 当InnoDB从磁盘读取页并发出该错误信息时,它将页中位置与日志文件位置比较。
• 日志位置大于当前位置的页不会使用崩溃恢复,直到当前日志位置大于记录的位置。这表示崩溃恢复不能正确运行直到该问题被解决。
• 如果原因与以innodb_force_recovery = 6启动MySQL有关,这会清楚地显示在MySQL错误日志中。

解决方案

选择以下方法之一:
1、如果你仍有它们,从备份或复制数据文件的位置恢复初始日志文件。在这个问题发生但没有任何更改的情况下,这会恢复所有数据
2、使用mysqldump来备份数据,删除所有InnoDB表的ib_logfile*,ibdata*, .ibd,和.frm;从转储中重建InnoDB表。一些数据丢失通常在这个情况下发生
3、将所有InnoDB表转换为MyISAM,删除所有ib_logfile*, ibdata*,重启MySQL并将表转回InnoDB。效果会与方案2相同,所以这个情况同样会发生数据丢失
4、使用InnoDB存储引擎创建一个”work table” ,其大小与日志文件的总大小相同,将数据插入。然后删除这个工作表。通常在这个情况下会发生一些数据丢失

方案2和3可以合并。重要的是确保没有剩余的InnoDB表。合并方案2和3可以,例如使你将InnoDB表转换为MyISAM,其中没有具体InnoDB信息会丢失且使用mysqldump剩余的表能被备份并在重启后被恢复。
要在方案2,3, 和4中选择,你通常应该选择能在最短时间完成的方案,但是使用方案4会有较高的未检测问题的可能性,所以使用其他两个方案更好。

1.恢复初始日志文件

这也会从任何在使用的日志文件丢失的提交或未提交的事务中得到时间,所以这比之后会导致数据丢失的选项好多了。该选项应当被首先使用,除非错误发生后数据被更改了。那样的话,它对于接受旧工作的丢失并保留新工作造成的损失可能最低。

2.重载数据

在重新初始化所有InnoDB文件之后重载数据来确保一切回到一致状态。
步骤是:
1.转储所有InnoDB数据。你能用mysqldump 或 SELECT … INTO OUTFILE完成。确保你也将schema信息如表定义和触发器包括在内。你不需要使用其他存储引擎来包括表。
2.停止MySQL。
3.删除所有InnoDB特定文件。文件的位置和名称将取决于你的MySQL 配置;默认是所有文件被datadir配置到MySQL数据目录下。你必须删除以下文件:

共享的表空间文件(每个文件默认称为ibdata*)。
InnoDB日志文件(重做日志) ib_logfile*。
InnoDB表的表定义文件,*.frm。
InnoDB表的触发器文件 (*.TRN 和 *.TRG)。
InnoDB数据文件,*.ibd。

4.启动MySQL并等待InnoDB重新初始化。当InnoDB完成创建新共享表空间和日志文件,你能在MySQL错误日志中看到。
5.重载InnoDB文件的数据和schema。

解决

【1】错误:”log sequence number is in the future”
数据库崩溃,还好里面数据的数据不太重要,尝试恢复

innodb_force_recovery = 3

按照提示访问官方文档
https://dev.mysql.com/doc/refman/8.0/en/forcing-innodb-recovery.html
按照文中所述编辑数据库的配置文件my.cnf,添加innodb_force_recovery属性
设置 innodb_force_recovery = 1,然后保存修改并重启MariaDB服务器
innodb_force_recovery = 1不行就改成2,2不行改成3,以此类推,最大值为6,

注意:当该值设置为4或者更大时有可能彻底损坏数据,所以做之前最好备份硬盘
启动后把数据导出,重装数剧库或者删除重建数据库就OK了,记得吧innodb_force_recovery改回来

附加问题
在修改innodb_force_recovery并重启数据服务时,重启命令一直在等待,查看日志发现出现很多如下日志条目
InnoDB: Waiting for the background threads to start
InnoDB: Waiting for the background threads to start
InnoDB: 等待后台线程启动
...
修改配置文件my.cnf,添加innodb_purge_threads = 0

官网简绍

要调查数据库页面损坏,可以使用 SELECT … INTO OUTFILE。通常,通过这种方式获得的大部分数据是完整的。严重的损坏可能导致SELECT * FROM tbl_name语句或InnoDB后台操作意外退出或断言,甚至导致InnoDB前滚恢复崩溃。在这种情况下,您可以使用innodb_force_recovery选项强制启动innodb存储引擎,同时阻止后台操作运行,以便转储您的表。例如,在重新启动服务器之前,可以将以下行添加到选项文件的[mysqld]部分:

[mysqld]
innodb_force_recovery = 1          #建议直接3

Warning
仅在紧急情况下将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会阻止插入、更新或删除操作。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,则可以删除或创建表。innodb_force_recovery值大于3时,也支持删除表。innodb_force_recovery值不允许大于4的DROP TABLE。

如果您知道给定的表在回滚时导致意外退出,那么您可以删除它。如果遇到由失败的批量导入或ALTER TABLE导致的失控回滚,可以终止mysqld进程,并将innodb_force_recovery设置为3,以便在不回滚的情况下启动数据库,然后删除导致失控回滚的表。

如果表数据中的损坏使您无法转储整个表的内容,则使用ORDER BY primary_key DESC子句的查询可能会转储损坏部分之后的那部分表。

如果启动innodb需要较高的innodb_force_recovery值,则可能会出现损坏的数据结构,从而导致复杂的查询(包含WHERE、ORDER BY或其他子句的查询)失败。在这种情况下,您可能只能运行基本SELECT * FROM t查询。

无法打开数据文件

关于表定义的信息存储在InnoDB数据字典中。如果移动数据文件,字典数据可能会变得不一致。 如果数据字典损坏或一致性问题使您无法启动InnoDB。

启用 innodb_file_per_table (默认设置)后,如果每个表的文件表空间文件(.ibd文件)丢失,启动时可能会出现以下消息:

[ERROR] InnoDB: Operating system error number 2 in a file operation.
[ERROR] InnoDB: The error means the system cannot find the path specified.
[ERROR] InnoDB: Cannot open datafile for read-only: './test/t1.ibd' OS error: 71
[Warning] InnoDB: Ignoring tablespace `test/t1` because it could not be opened.

若要处理这些消息,请发出DROP TABLE语句,从数据字典中删除有关缺失表的数据。

恢复每个表的孤立文件ibd文件

此过程描述了如何将孤立的 file-per-table .ibd 文件恢复到另一个 MySQL 实例。如果系统表空间丢失或不可恢复,并且您希望.ibd 在新的 MySQL 实例上恢复文件备份,则可以使用此过程。
一般表空间 .ibd文件 不支持该过程 。
该过程假设您只有.ibd文件备份,您正在恢复到最初创建孤立 .ibd文件的相同版本的 MySQL,还有那个.ibd文件备份是干净的。

1、在新的 MySQL 实例上,在同名数据库中重新创建表

mysql> CREATE DATABASE sakila;
mysql> USE sakila;
mysql> CREATE TABLE actor (
         actor_id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
         first_name VARCHAR(45) NOT NULL,
         last_name VARCHAR(45) NOT NULL,
         last_update TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
         PRIMARY KEY  (actor_id),
         KEY idx_actor_last_name (last_name)
       )ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

2、丢弃新创建的表的表空间

mysql> ALTER TABLE sakila.actor DISCARD TABLESPACE;

3、将孤立.ibd文件从备份目录复制到新的数据库目录

cp /backup_directory/actor.ibd path/to/mysql-5.7/data/sakila/

4、确保该.ibd文件具有必要的文件权限
5、导入孤立.ibd文件发出警告,指示InnoDB正在尝试导入文件而不进行模式验证

mysql> ALTER TABLE sakila.actor IMPORT TABLESPACE; SHOW WARNINGS;
Query OK, 0 rows affected, 1 warning (0.15 sec)

Warning | 1810 | InnoDB: IO Read error: (2, No such file or directory)
Error opening './sakila/actor.cfg', will attempt to import
without schema verification

6、查询表以验证.ibd 文件是否已成功恢复。

mysql> SELECT COUNT(*) FROM sakila.actor;
+----------+
| count(*) |
+----------+
|      200 |
+----------+

InnoDB错误处理

以下项目描述了InnoDB如何执行错误处理。InnoDB有时只回滚失败的语句,有时回滚整个事务。
☑ 如果表空间中的文件空间不足,就会出现MySQL表已满错误,InnoDB会回滚SQL语句
☑ 事务死锁会导致InnoDB回滚整个事务。发生这种情况时,请重试整个事务
锁等待超时导致InnoDB回滚当前语句(等待锁并遇到超时的语句)。要回滚整个事务,请启动服务器并启用 --innodb-rollback-on-timeout。如果使用默认行为,请重试该语句;如果启用了 --innodb-rollback-on-timeout,请重试整个事务
在繁忙的服务器上,死锁和锁等待超时都是正常的,应用程序有必要意识到它们可能会发生,并通过重试来处理它们。通过在事务期间对数据的第一次更改和提交之间做尽可能少的工作,可以降低发生这种情况的可能性,这样锁就可以保持尽可能短的时间和尽可能少的行数。有时在不同的事务之间划分工作可能是实用且有帮助的
☑ 如果您没有在语句中指定IGNORE选项,则重复键错误会回滚SQL语句
☑ A row too long error错误回滚SQL语句
☑ 其他错误主要是由MySQL代码层(在InnoDB存储引擎层之上)检测到的,它们回滚相应的SQL语句。单个SQL语句的回滚不会释放锁。
在隐式回滚期间,以及在执行显式ROLLBACK SQL语句期间,SHOW PROCESSLIST 显示Rolling back在 State相关连接的列中。
You use one hundred percent of effort and success to do exchange, there is no deal.

猜你喜欢

转载自blog.csdn.net/qq_50573146/article/details/127016488
今日推荐