Commit c051eaba authored by Marko Mäkelä's avatar Marko Mäkelä

MDEV-14988 innodb_read_only tries to modify files if transactions were recovered in COMMITTED state

lock_trx_release_locks(): Relax a debug assertion to allow
recovered TRX_STATE_COMMITTED_IN_MEMORY transactions.

trx_commit_in_memory(): Add DEBUG_SYNC instrumentation.

trx_undo_insert_cleanup(): Skip persistent changes if innodb_read_only
is set. This should only happen when a recovered committed transaction
would be cleaned up at shutdown.
parent b0a92333
CREATE TABLE t(a INT PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t VALUES(1);
BEGIN;
INSERT INTO t VALUES(2);
DELETE FROM t WHERE a=2;
# Normal MariaDB shutdown would roll back the above transaction.
# We want the transaction to remain open, so we will kill the server
# after ensuring that any non-transactional files are clean.
FLUSH TABLES;
# Create another transaction that will be recovered as COMMITTED.
BEGIN;
SET DEBUG_SYNC='after_trx_committed_in_memory SIGNAL committed WAIT_FOR ever';
COMMIT;
SET DEBUG_SYNC='now WAIT_FOR committed';
# Ensure that the above incomplete transactions become durable.
SET GLOBAL innodb_flush_log_at_trx_commit=1;
BEGIN;
INSERT INTO t VALUES(-10000);
ROLLBACK;
SELECT * FROM t;
a
1
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
SELECT * FROM t;
a
1
UPDATE t SET a=3 WHERE a=1;
ERROR HY000: Table 't' is read only
# Starting with MariaDB 10.2, innodb_read_only implies READ UNCOMMITTED.
# In earlier versions, this would return the last committed version
# (empty table)!
SELECT * FROM t;
a
1
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
SELECT * FROM t;
a
1
SELECT * FROM t;
a
1
DROP TABLE t;
NOT FOUND /Rolled back recovered transaction [^0]/ in mysqld.1.err
--source include/have_innodb.inc
--source include/have_debug.inc
--source include/have_debug_sync.inc
# need to restart server
--source include/not_embedded.inc
--connect(con1, localhost, root)
CREATE TABLE t(a INT PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t VALUES(1);
BEGIN;
# Generate insert_undo log.
INSERT INTO t VALUES(2);
# Generate update_undo log.
DELETE FROM t WHERE a=2;
--connect(con2, localhost, root)
--echo # Normal MariaDB shutdown would roll back the above transaction.
--echo # We want the transaction to remain open, so we will kill the server
--echo # after ensuring that any non-transactional files are clean.
FLUSH TABLES;
--echo # Create another transaction that will be recovered as COMMITTED.
BEGIN;
# Generate multiple pages of both insert_undo and update_undo, so that
# the state TRX_UNDO_CACHE will not be chosen.
--disable_query_log
let $n= 10000;
while ($n) {
dec $n;
eval INSERT INTO t VALUES(-$n);
eval DELETE FROM t WHERE a=-$n;
}
--enable_query_log
SET DEBUG_SYNC='after_trx_committed_in_memory SIGNAL committed WAIT_FOR ever';
send COMMIT;
connection default;
SET DEBUG_SYNC='now WAIT_FOR committed';
--echo # Ensure that the above incomplete transactions become durable.
SET GLOBAL innodb_flush_log_at_trx_commit=1;
BEGIN;
INSERT INTO t VALUES(-10000);
ROLLBACK;
--let $restart_parameters= --innodb-force-recovery=3
--let $shutdown_timeout= 0
--source include/restart_mysqld.inc
--let $shutdown_timeout= 30
--disconnect con1
--disconnect con2
SELECT * FROM t;
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
SELECT * FROM t;
# refused on MySQL 5.6, MariaDB 10.0, 10.1, but not MariaDB 10.2+
--error ER_OPEN_AS_READONLY
UPDATE t SET a=3 WHERE a=1;
--let $restart_parameters= --innodb-read-only
--source include/restart_mysqld.inc
--echo # Starting with MariaDB 10.2, innodb_read_only implies READ UNCOMMITTED.
--echo # In earlier versions, this would return the last committed version
--echo # (empty table)!
SELECT * FROM t;
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
SELECT * FROM t;
--let $restart_parameters=
--source include/restart_mysqld.inc
SELECT * FROM t;
DROP TABLE t;
let SEARCH_FILE= $MYSQLTEST_VARDIR/log/mysqld.1.err;
--let SEARCH_PATTERN= Rolled back recovered transaction [^0]
--source include/search_pattern_in_file.inc
...@@ -7000,7 +7000,10 @@ lock_trx_release_locks( ...@@ -7000,7 +7000,10 @@ lock_trx_release_locks(
} }
mutex_exit(&trx_sys->mutex); mutex_exit(&trx_sys->mutex);
} else { } else {
ut_ad(trx_state_eq(trx, TRX_STATE_ACTIVE)); ut_ad(trx_state_eq(trx, TRX_STATE_ACTIVE)
|| (trx_state_eq(trx, TRX_STATE_COMMITTED_IN_MEMORY)
&& trx->is_recovered
&& !UT_LIST_GET_LEN(trx->lock.trx_locks)));
} }
/* The transition of trx->state to TRX_STATE_COMMITTED_IN_MEMORY /* The transition of trx->state to TRX_STATE_COMMITTED_IN_MEMORY
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, MariaDB Corporation. Copyright (c) 2017, 2018, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
...@@ -1227,6 +1227,8 @@ trx_commit_in_memory( ...@@ -1227,6 +1227,8 @@ trx_commit_in_memory(
trx->read_view = NULL; trx->read_view = NULL;
if (lsn) { if (lsn) {
DEBUG_SYNC_C("after_trx_committed_in_memory");
if (trx->insert_undo != NULL) { if (trx->insert_undo != NULL) {
trx_undo_insert_cleanup(trx); trx_undo_insert_cleanup(trx);
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2014, 2017, MariaDB Corporation. Copyright (c) 2014, 2018, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
...@@ -1989,7 +1989,9 @@ trx_undo_insert_cleanup( ...@@ -1989,7 +1989,9 @@ trx_undo_insert_cleanup(
mutex_exit(&(rseg->mutex)); mutex_exit(&(rseg->mutex));
trx_undo_seg_free(undo); if (!srv_read_only_mode) {
trx_undo_seg_free(undo);
}
mutex_enter(&(rseg->mutex)); mutex_enter(&(rseg->mutex));
......
...@@ -7099,7 +7099,10 @@ lock_trx_release_locks( ...@@ -7099,7 +7099,10 @@ lock_trx_release_locks(
} }
mutex_exit(&trx_sys->mutex); mutex_exit(&trx_sys->mutex);
} else { } else {
ut_ad(trx_state_eq(trx, TRX_STATE_ACTIVE)); ut_ad(trx_state_eq(trx, TRX_STATE_ACTIVE)
|| (trx_state_eq(trx, TRX_STATE_COMMITTED_IN_MEMORY)
&& trx->is_recovered
&& !UT_LIST_GET_LEN(trx->lock.trx_locks)));
} }
/* The transition of trx->state to TRX_STATE_COMMITTED_IN_MEMORY /* The transition of trx->state to TRX_STATE_COMMITTED_IN_MEMORY
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, MariaDB Corporation. Copyright (c) 2017, 2018, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
...@@ -1442,6 +1442,8 @@ trx_commit_in_memory( ...@@ -1442,6 +1442,8 @@ trx_commit_in_memory(
if (lsn) { if (lsn) {
ulint flush_log_at_trx_commit; ulint flush_log_at_trx_commit;
DEBUG_SYNC_C("after_trx_committed_in_memory");
if (trx->insert_undo != NULL) { if (trx->insert_undo != NULL) {
trx_undo_insert_cleanup(trx); trx_undo_insert_cleanup(trx);
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2014, 2017, MariaDB Corporation. Copyright (c) 2014, 2018, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
...@@ -1989,7 +1989,9 @@ trx_undo_insert_cleanup( ...@@ -1989,7 +1989,9 @@ trx_undo_insert_cleanup(
mutex_exit(&(rseg->mutex)); mutex_exit(&(rseg->mutex));
trx_undo_seg_free(undo); if (!srv_read_only_mode) {
trx_undo_seg_free(undo);
}
mutex_enter(&(rseg->mutex)); mutex_enter(&(rseg->mutex));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment