一、参数介绍
参数innodb_force_recovery影响了整个Innodb存储引擎的恢复状况。该值默认为0,表示当需要恢复时执行所有的恢复操作。当不能进行有效恢复时,如数据页发生了corruption,Mysql数据库可能会宕机,并把错误写入错误日志中。
但在某些情况下,可能不需要执行完整的恢复操作。例如在进行alter table操作时,这时发生意外,数据库重启时会对Innodb表执行回滚操作。对于一个大表,这需要很长时间,甚至可能是几个小时。这时可以自行恢复,例如将表删除,从备份中重新将数据导入表中,这些操作可能要快于回滚操作。
Innodb_force_recovery可以设置6个非零值:
-
1(SRV_FORCE_IGNORE_CORRUPT):忽略检查到的corrupt页。
-
2(SRV_FORCE_NO_BACKGROUND):阻止主线程的运行,如主线程需要执行full purge操作,会导致crash。
-
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后,可以对标进行select、create、drop操作,但insert、update或者delete这类操作是不允许的。
二、故障模拟
2.1.创建大数据量表
2.1.1.创建测试表
mysql> CREATE TABLE usertb (
-> id serial,
-> uname varchar(20) ,
-> ucreatetime datetime ,
-> age int(11)
2.1.2.创建插入表存储过程
mysql> delimiter $$
mysql> create procedure test1()
-> begin
-> declare v_cnt decimal (10) default 0 ;
-> dd:loop
-> insert into usertb values
-> (null,'1','2010-01-01 00:00:00',20),
-> (null,'2','2010-01-01 00:00:00',20),
-> (null,'3','2010-01-01 00:00:00',20),
-> (null,'4','2010-01-01 00:00:00',20),
-> (null,'5','2011-01-01 00:00:00',20),
-> (null,'6','2011-01-01 00:00:00',20),
-> (null,'7','2011-01-01 00:00:00',20),
-> (null,'8','2012-01-01 00:00:00',20),
-> (null,'9','2012-01-01 00:00:00',20),
-> (null,'0','2012-01-01 00:00:00',20)
-> ;
-> commit;
-> set v_cnt = v_cnt+10 ;
-> if v_cnt = 10000000 then leave dd;
-> end if;
-> end loop dd ;
-> end;$$
Query OK, 0 rows affected (0.09 sec)
2.1.3.执行存储过程
2.1.4.确认数据量
mysql> select count(*) from usertb;
+----------+
| count(*) |
+----------+
| 10000000 |
+----------+
2.2.故障模拟
2.2.1 更新表
update usertb set age=70;
2.2.2 查看参数
mysql> show variables like '%recovery%';
+-----------------------------+-------+
| Variable_name | Value |
+-----------------------------+-------+ |
| innodb_force_recovery | 0 |
+-----------------------------+-------+
2.2.3 杀死mysql进程(模拟突然宕机)
root 98943 1 0 07:45 pts/4 00:00:00 /bin/sh /u01/3306/bin/mysqld_safe --datadir=/u01/3306/data --pid-file=/u01/3306/tmp/mysqld.pid
mysql 99554 98943 24 07:45 pts/4 00:01:39 /u01/3306/bin/mysqld --basedir=/u01/3306 --datadir=/u01/3306/data --plugin-dir=/u01/3306/lib/plugin --user=mysql --log-error=/u01/3306/log/mysqld_error.log --pid-file=/u01/3306/tmp/mysqld.pid --socket=/u01/3306/mysql.sock --port=3306
[root@mysql ~]# kill -9 98943
[root@mysql ~]# kill -9 99554
2.2.4.启动mysql
观察error日志发现,在进行恢复
2018-07-12T14:53:54.060470Z 0 [Note] InnoDB: Completed initialization of buffer pool
2018-07-12T14:53:54.061908Z 0 [Note] InnoDB: If the mysqld execution user is authorized, page cleaner thread priority can be changed. See the man page of setpriority().
2018-07-12T14:53:54.097022Z 0 [Note] InnoDB: Highest supported file format is Barracuda.
2018-07-12T14:53:54.111544Z 0 [Note] InnoDB: Log scan progressed past the checkpoint lsn 4251709539
2018-07-12T14:53:54.229291Z 0 [Note] InnoDB: Doing recovery: scanned up to log sequence number 4256952320
2018-07-12T14:53:54.389743Z 0 [Note] InnoDB: Doing recovery: scanned up to log sequence number 4262195200
2018-07-12T14:53:54.518164Z 0 [Note] InnoDB: Doing recovery: scanned up to log sequence number 4267438080
2.2.5更改参数|innodb_force_recovery = 3 ,再次模拟发现日志如下:
2018-07-12T15:01:34.910567Z 2 [ERROR] InnoDB: innodb_force_recovery is on. We do not allow database modifications by the user. Shut down mysqld and edit my.cnf to set innodb_force_recovery=0