备份与恢复灾难恢复
29.7 MySQL灾难恢复
在MySQL运行的过程中难免会遇到各种各样的问题。例如,数据库机房断网、网络抖动、断电、内存溢出、服务器磁盘老化等,这都会对MySQL的正常运行造成一定的影响。其中,断电、内存溢出和服务器磁盘老化等问题可能会给MySQL造成灾难性的后果。
一个常见的场景是会损坏数据库的表数据文件而导致MySQL数据库无法正常启动。本节简单介绍如何解决由于数据库的表数据文件损坏而无法正常启动MySQL数据库的问题。
29.7.1 问题重现
如果是由于数据库的表数据文件被损坏而无法正常启动MySQL数据库,往往会在MySQL的错误日志文件中输出如下错误信息:
2020-01-22 14:18:05 4122 [Note] InnoDB: Database was not shutdown normally!
2020-01-22 14:18:05 4122 [Note] InnoDB: Starting crash recovery.
2020-01-22 14:18:05 4122 [Note] InnoDB: Reading tablespace information from the .ibd files...
2020-01-22 14:18:05 4122 [ERROR] InnoDB: Attempted to open a previously opened tablespace. Previous
tablespace dev/tb_test uses spac
e ID: 1 at filepath: ./dev/tb_test.ibd. Cannot open tablespace mysql/innodb_table_stats which uses space
ID: 1 at filepath: ./mysql/
innodb_table_stats.ibd
2020-01-22 14:18:05 2ad861898590 InnoDB: Operating system error number 2 in a file operation.
InnoDB: The error means the system cannot find the path specified.
InnoDB: If you are installing InnoDB, remember that you must create
InnoDB: directories yourself, InnoDB does not create them.
InnoDB: Error: could not open single-table tablespace file ./mysql/innodb_table_stats.ibd
InnoDB: We do not continue the crash recovery, because the table may becomeInnoDB: corrupt if we cannot
apply the log records in the InnoDB log to it.
InnoDB: To fix the problem and start mysqld:
InnoDB: 1) If there is a permission problem in the file and mysqld cannot
InnoDB: open the file, you should modify the permissions.
InnoDB: 2) If the table is not needed, or you can restore it from a backup,
InnoDB: then you can remove the .ibd file, and InnoDB will do a normal
InnoDB: crash recovery and ignore that table.
InnoDB: 3) If the file system or the disk is broken, and you cannot remove
InnoDB: the .ibd file, you can set innodb_force_recovery > 0 in my.cnf
InnoDB: and force InnoDB to continue crash recovery here.
150126 14:18:06 mysqld_safe mysqld from pid file /home/mysql/mysql_app/dbdata/binghe.pid ended
29.7.2 问题分析
通过对错误日志的分析可以得知具体的错误信息如下:
InnoDB: Error: could not open single-table tablespace file ./mysql/innodb_table_stats.ibd
InnoDB: We do not continue the crash recovery, because the table may becomeInnoDB: corrupt if we cannot
apply the log records in the InnoDB log to it.
实际上是InnoDB存储引擎出了问题。并且,MySQL的错误日志中给出了解决此问题的方案。
InnoDB: To fix the problem and start mysqld:
InnoDB: 1) If there is a permission problem in the file and mysqld cannot
InnoDB: open the file, you should modify the permissions.
InnoDB: 2) If the table is not needed, or you can restore it from a backup,
InnoDB: then you can remove the .ibd file, and InnoDB will do a normal
InnoDB: crash recovery and ignore that table.
InnoDB: 3) If the file system or the disk is broken, and you cannot remove
InnoDB: the .ibd file, you can set innodb_force_recovery > 0 in my.cnf
InnoDB: and force InnoDB to continue crash recovery here.
150126 14:18:06 mysqld_safe mysqld from pid file /home/mysql/mysql_app/dbdata/binghe.pid ended
而且在MySQL的官方文档中也可以找到强制恢复的方法。网址为https://dev.mysql.com/doc/refman/8.0/en/forcing-innodb-recovery.html。
可以在MySQL的配置文件my.cnf的[mysqld]下添加一行代码:
[mysqld]
innodb_force_recovery = 1
如果innodb_force_recovery=1不生效,则可尝试2~6几个数字中的一个。
innodb_force_recovery决定着InnoDB存储引擎的数据恢复情况,其默认值为0,表示当需要恢复时执行所有的恢复操作;当不能进行有效的恢复操作时,MySQL可能会无法启动,并在错误日志文件中记录下错误日志。
innodb_force_recovery的值可以设置为1~6,大的数字包含前面所有数字的影响。当设置参数值大于0后,可以对表进行SELECT(查询)、CREATE(创建)和DROP(删除数据库和数据表)操作,但是不能进行INSERT(插入)、UPDATE(更新数据)和DELETE(删除数据)等操作。
innodb_force_recovery每个取值的含义如下:
·1(SRV_FORCE_IGNORE_CORRUPT):忽略损坏的数据页,继续运行MySQL服务。
·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设置为只读。
29.7.3 问题解决
通过上一节对问题的分析,基本上可以明确如何解决问题。本节简单介绍解决问题的步骤。
(1)在my.cnf配置文件的[mysqld]下配置innodb_force_recovery的值。
[mysqld]
innodb_force_recovery=1
注意:如果innodb_force_recovery=1不生效,则可尝试2~6几个数字中的一个。
(2)重启MySQL服务。
[root@binghe150 ~]# service mysqld restart
Shutting down MySQL..... SUCCESS!
Starting MySQL......... SUCCESS!
(3)导出数据库中的数据,这里以mysqldump导出goods数据库为例。
[root@binghe150 ~]# mysqldump -uroot -p --databases goods --routines --events > /home/mysql/backups/
mysqldump_databases_goods.sql
Enter password:
注意:这里一定要确保goods数据库备份成功。
(4)删除goods数据库中的数据。如果MySQL提示无法删除数据库中的数据,可以在服务器命令行中直接删除goods数据库的目录。
rm -rf /data/mysql/data/goods/
注意:执行此步骤的前提是第(3)步中的数据备份操作一定要成功。
(5)备份MySQL数据目录下的ib_logfile0、ib_logfile1、ib_logfile2、ib_logfile3和ibdata1文件,然后将这些文件删除。
cp /data/mysql/data/ib_logfile0 /data/mysql/backup/
cp /data/mysql/data/ib_logfile1 /data/mysql/backup/
cp /data/mysql/data/ib_logfile2 /data/mysql/backup/
cp /data/mysql/data/ib_logfile3 /data/mysql/backup/
cp /data/mysql/data/ibdata1 /data/mysql/backup/
rm -rf /data/mysql/data/ib_logfile0
rm -rf /data/mysql/data/ib_logfile1
rm -rf /data/mysql/data/ib_logfile2
rm -rf /data/mysql/data/ib_logfile3
rm -rf /data/mysql/data/ibdata1
注意:有些MySQL数据库中可能只存在ib_logfile0、ib_logfile1和ibdata1文件,那么只需要备份这些文件后,删除MySQL数据目录下的这些文件即可。
(6)将my.cnf文件中的innodb_force_recovery选项的值设置为0。
[mysqld]
innodb_force_recovery=0
将innodb_force_recovery选项的值设置为0后,需要重新启动MySQL让服务生效。
(7)将备份的数据文件导入MySQL中。
[root@binghe150 ~]# mysql -uroot -p goods < /home/mysql/backups/mysqldump_databases_goods.sql
Enter password:
至此,由于数据库的表数据文件被损坏而无法正常启动MySQL数据库的问题就已经成功解决了。
注意:备份与恢复数据时,笔者只是简单使用了mysqldump命令和mysql命令,读者也可以使用本章介绍的其他工具实现数据的备份与恢复。
- 点赞
- 收藏
- 关注作者
评论(0)