kill掉持续很长时间的ddl sql后,由于回滚会给表带来一个长时间的写锁,有着急操作的同学就想重启数据库,但是在数据库开启后锁依然存在,因为这是mysql为了保证数据的事务特性的功能(其实应该庆幸这个功能存在,虽然有时候我们不希望它发挥功能)。
于是有人想到是否可以通过修改mysql参数 使数据库重启后不回滚呢?
所以我测试了一下:修改参数innodb_force_recovery=3
该参数默认为0 代表当发生需要恢复时,进行所有的恢复操作。
还可以设置6个非0值,1~6 大数字的影响包含小数字
这里只讨论3 3代表的意义是:不进行事务的回滚操作

所以我打开了一个事务:

MariaDB [db]> begin;
 Query OK, 0 rows affected (0.00 sec)MariaDB [db]> update table set id1=0;
 Query OK, 10248227 rows affected (1 min 31.18 sec)
 Rows matched: 11426551 Changed: 10248227 Warnings: 0MariaDB [db]> show variables like ‘%force%’;
 ±-----------------------------------------±------+
 | Variable_name | Value |
 ±-----------------------------------------±------+
 | aria_force_start_after_recovery_failures | 0 |
 | enforce_storage_engine | |
 | innodb_force_load_corrupted | OFF |
 | innodb_force_primary_key | OFF |
| innodb_force_recovery | 0 |
 | wsrep_forced_binlog_format | NONE |
 ±-----------------------------------------±------+
 6 rows in set (0.00 sec)

然后杀死进程;

[root@bogon mariadb]# ps -ef | grep mysql
 mysql 15242 1 99 22:03 ? 00:00:24 /usr/sbin/mysqld --defaults-file=/data2/my.cnf --basedir=/usr --datadir=/data2/mariadb/5003 --plugin-dir=/usr/lib64/mysql/plugin --user=mysql --log-error=/data2/log/mariadb/5003.err --pid-file=/data2/mariadb/5003/5003.pid --socket=/data2/mariadb/5003/5003.sock --port=5003[root@bogon mariadb]# kill -9 15242

如果此时再打开mysql服务,可以看到错误日志:

mysql现场Killed mysql killed状态_mysql现场Killed


说明数据库开始了回滚,因为默认情况下innodb_force_recovery=0

于是我们把innodb_force_recovery改为3 再启动数据库

可以看到错误日志:

mysql现场Killed mysql killed状态_mysql现场Killed_02


没错,没有进行回滚,并且数据库成功启动了

但是锁依然存在,除了root账号,普通账号对这个表只能删除,不能增删改

此时我们看到了这个事务,但是这个事务的trx_mysql_thread_id是0 无法杀死

mysql现场Killed mysql killed状态_回滚_03


但是如果我们把参数改回0时,再启动数据库:

mysql现场Killed mysql killed状态_mysql现场Killed_04


mysql现场Killed mysql killed状态_回滚_05


可以发现回滚在继续 (但是如果你在innodb_force_recovery=3时drop 了锁住的表,那么回滚将消失)

结论这个方法禁止使用,这个参数是用来抢救数据库的,不能在平时维护过程中使用。

警告!
仅允许innodb_force_recovery 在紧急情况下设置为大于0的值,以便您可以启动InnoDB和转储表。在此之前,请确保您拥有数据库的备份副本,以备需要重新创建时使用。值为4或更高可能会永久损坏数据文件。