Do allow writes for innodb_force_recovery=2 or 3
While the primary purpose of innodb_force_recovery is to allow data to be rescued from an InnoDB instance that would crash due to some data corruption, the settings 1, 2, or 3 are relatively safe to use and there is no need to prevent write transactions in these modes. The setting innodb_force_recovery=4 and above can cause database corruption. For those modes, we already set the flag high_level_read_only to disable modifications, except DROP TABLE. MODIFICATIONS_NOT_ALLOWED_MSG_FORCE_RECOVERY: Remove. There is no need to spam the error log for each refused DML operation. It suffices to return an error to the client. There will be messages at startup if innodb_read_only or innodb_force_recovery are preventing writes.
This commit is contained in:
parent
9f3622191d
commit
0288fa619f
@ -1,5 +1,5 @@
|
||||
create table t1(f1 int not null, f2 int not null, index idx(f2))engine=innodb;
|
||||
create table t2(f1 int not null, f2 int not null, index idx(f2))engine=innodb;
|
||||
create table t2(f1 int primary key, f2 int, index idx(f2))engine=innodb;
|
||||
insert into t1 values(1, 2);
|
||||
insert into t2 values(1, 2);
|
||||
SET GLOBAL innodb_fast_shutdown = 0;
|
||||
@ -85,6 +85,37 @@ ERROR HY000: Table 't2' is read only
|
||||
show tables;
|
||||
Tables_in_test
|
||||
t2
|
||||
# Restart the server with innodb_force_recovery=2
|
||||
select * from t2;
|
||||
f1 f2
|
||||
1 2
|
||||
begin;
|
||||
update t2 set f2=3;
|
||||
connect con1,localhost,root,,;
|
||||
create table t3(a int)engine=innodb;
|
||||
# Force a redo log flush of the above uncommitted UPDATE
|
||||
SET GLOBAL innodb_flush_log_at_trx_commit=1;
|
||||
drop table t3;
|
||||
disconnect con1;
|
||||
connection default;
|
||||
# Kill the server
|
||||
# Restart the server with innodb_force_recovery=3
|
||||
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
|
||||
select * from t2;
|
||||
f1 f2
|
||||
1 3
|
||||
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
|
||||
select * from t2;
|
||||
f1 f2
|
||||
1 2
|
||||
SET GLOBAL innodb_lock_wait_timeout=1;
|
||||
insert into t2 values(1,2);
|
||||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
||||
insert into t2 values(9,10);
|
||||
select * from t2;
|
||||
f1 f2
|
||||
1 2
|
||||
9 10
|
||||
drop table t2;
|
||||
show tables;
|
||||
Tables_in_test
|
||||
|
@ -10,7 +10,7 @@ call mtr.add_suppression("InnoDB: Allocated tablespace ID \\d+ for test.t[12], o
|
||||
--enable_query_log
|
||||
|
||||
create table t1(f1 int not null, f2 int not null, index idx(f2))engine=innodb;
|
||||
create table t2(f1 int not null, f2 int not null, index idx(f2))engine=innodb;
|
||||
create table t2(f1 int primary key, f2 int, index idx(f2))engine=innodb;
|
||||
insert into t1 values(1, 2);
|
||||
insert into t2 values(1, 2);
|
||||
|
||||
@ -132,8 +132,40 @@ truncate table t2;
|
||||
drop table t2;
|
||||
show tables;
|
||||
|
||||
--echo # Restart the server with innodb_force_recovery=2
|
||||
--let $restart_parameters= --innodb-force-recovery=2
|
||||
--source include/restart_mysqld.inc
|
||||
|
||||
select * from t2;
|
||||
begin;
|
||||
update t2 set f2=3;
|
||||
|
||||
connect (con1,localhost,root,,);
|
||||
create table t3(a int)engine=innodb;
|
||||
--echo # Force a redo log flush of the above uncommitted UPDATE
|
||||
SET GLOBAL innodb_flush_log_at_trx_commit=1;
|
||||
drop table t3;
|
||||
disconnect con1;
|
||||
|
||||
connection default;
|
||||
--source include/kill_mysqld.inc
|
||||
|
||||
--echo # Restart the server with innodb_force_recovery=3
|
||||
--let $restart_parameters= --innodb-force-recovery=3
|
||||
--source include/start_mysqld.inc
|
||||
|
||||
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
|
||||
select * from t2;
|
||||
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
|
||||
select * from t2;
|
||||
SET GLOBAL innodb_lock_wait_timeout=1;
|
||||
--error ER_LOCK_WAIT_TIMEOUT
|
||||
insert into t2 values(1,2);
|
||||
insert into t2 values(9,10);
|
||||
|
||||
--let $restart_parameters=
|
||||
--source include/restart_mysqld.inc
|
||||
|
||||
select * from t2;
|
||||
drop table t2;
|
||||
show tables;
|
||||
|
@ -70,11 +70,6 @@ Created 9/17/2000 Heikki Tuuri
|
||||
#include <deque>
|
||||
#include <vector>
|
||||
|
||||
static const char* MODIFICATIONS_NOT_ALLOWED_MSG_FORCE_RECOVERY =
|
||||
"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";
|
||||
|
||||
/** Provide optional 4.x backwards compatibility for 5.0 and above */
|
||||
ibool row_rollback_on_timeout = FALSE;
|
||||
|
||||
@ -1432,9 +1427,7 @@ row_insert_for_mysql(
|
||||
|
||||
} else if (!prebuilt->table->is_readable()) {
|
||||
return(row_mysql_get_table_status(prebuilt->table, trx, true));
|
||||
} else if (srv_force_recovery) {
|
||||
|
||||
ib::error() << MODIFICATIONS_NOT_ALLOWED_MSG_FORCE_RECOVERY;
|
||||
} else if (high_level_read_only) {
|
||||
return(DB_READ_ONLY);
|
||||
}
|
||||
DBUG_EXECUTE_IF("mark_table_corrupted", {
|
||||
@ -1850,9 +1843,8 @@ row_update_for_mysql_using_upd_graph(
|
||||
return(row_mysql_get_table_status(table, trx, true));
|
||||
}
|
||||
|
||||
if(srv_force_recovery) {
|
||||
ib::error() << MODIFICATIONS_NOT_ALLOWED_MSG_FORCE_RECOVERY;
|
||||
DBUG_RETURN(DB_READ_ONLY);
|
||||
if (high_level_read_only) {
|
||||
return(DB_READ_ONLY);
|
||||
}
|
||||
|
||||
DEBUG_SYNC_C("innodb_row_update_for_mysql_begin");
|
||||
@ -4472,10 +4464,8 @@ row_rename_table_for_mysql(
|
||||
ut_a(new_name != NULL);
|
||||
ut_ad(trx->state == TRX_STATE_ACTIVE);
|
||||
|
||||
if (srv_force_recovery) {
|
||||
ib::info() << MODIFICATIONS_NOT_ALLOWED_MSG_FORCE_RECOVERY;
|
||||
err = DB_READ_ONLY;
|
||||
goto funct_exit;
|
||||
if (high_level_read_only) {
|
||||
return(DB_READ_ONLY);
|
||||
|
||||
} else if (row_mysql_is_system_table(new_name)) {
|
||||
|
||||
|
@ -1471,10 +1471,6 @@ innobase_start_or_create_for_mysql()
|
||||
srv_read_only_mode = true;
|
||||
}
|
||||
|
||||
if (srv_force_recovery == SRV_FORCE_NO_LOG_REDO) {
|
||||
srv_read_only_mode = 1;
|
||||
}
|
||||
|
||||
high_level_read_only = srv_read_only_mode
|
||||
|| srv_force_recovery > SRV_FORCE_NO_TRX_UNDO;
|
||||
|
||||
|
@ -285,8 +285,12 @@ trx_purge_add_update_undo_to_history(
|
||||
purge have been started, recv_recovery_rollback_active() can
|
||||
start transactions in row_merge_drop_temp_indexes() and
|
||||
fts_drop_orphaned_tables(), and roll back recovered transactions.
|
||||
Also, DROP TABLE may be executed while innodb_force_recovery=2
|
||||
prevents the purge from running.
|
||||
|
||||
Arbitrary user transactions may be executed when all the undo log
|
||||
related background processes (including purge) are disabled due to
|
||||
innodb_force_recovery=2 or innodb_force_recovery=3.
|
||||
DROP TABLE may be executed at any innodb_force_recovery level.
|
||||
|
||||
After the purge thread has been given permission to exit,
|
||||
in fast shutdown, we may roll back transactions (trx->undo_no==0)
|
||||
in THD::cleanup() invoked from unlink_thd(). */
|
||||
|
Loading…
x
Reference in New Issue
Block a user