Skip to content

Commit c051eab

Browse files
committed
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.
1 parent b0a9233 commit c051eab

File tree

8 files changed

+133
-8
lines changed

8 files changed

+133
-8
lines changed
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
CREATE TABLE t(a INT PRIMARY KEY) ENGINE=InnoDB;
2+
INSERT INTO t VALUES(1);
3+
BEGIN;
4+
INSERT INTO t VALUES(2);
5+
DELETE FROM t WHERE a=2;
6+
# Normal MariaDB shutdown would roll back the above transaction.
7+
# We want the transaction to remain open, so we will kill the server
8+
# after ensuring that any non-transactional files are clean.
9+
FLUSH TABLES;
10+
# Create another transaction that will be recovered as COMMITTED.
11+
BEGIN;
12+
SET DEBUG_SYNC='after_trx_committed_in_memory SIGNAL committed WAIT_FOR ever';
13+
COMMIT;
14+
SET DEBUG_SYNC='now WAIT_FOR committed';
15+
# Ensure that the above incomplete transactions become durable.
16+
SET GLOBAL innodb_flush_log_at_trx_commit=1;
17+
BEGIN;
18+
INSERT INTO t VALUES(-10000);
19+
ROLLBACK;
20+
SELECT * FROM t;
21+
a
22+
1
23+
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
24+
SELECT * FROM t;
25+
a
26+
1
27+
UPDATE t SET a=3 WHERE a=1;
28+
ERROR HY000: Table 't' is read only
29+
# Starting with MariaDB 10.2, innodb_read_only implies READ UNCOMMITTED.
30+
# In earlier versions, this would return the last committed version
31+
# (empty table)!
32+
SELECT * FROM t;
33+
a
34+
1
35+
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
36+
SELECT * FROM t;
37+
a
38+
1
39+
SELECT * FROM t;
40+
a
41+
1
42+
DROP TABLE t;
43+
NOT FOUND /Rolled back recovered transaction [^0]/ in mysqld.1.err
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
--source include/have_innodb.inc
2+
--source include/have_debug.inc
3+
--source include/have_debug_sync.inc
4+
# need to restart server
5+
--source include/not_embedded.inc
6+
7+
--connect(con1, localhost, root)
8+
CREATE TABLE t(a INT PRIMARY KEY) ENGINE=InnoDB;
9+
INSERT INTO t VALUES(1);
10+
BEGIN;
11+
# Generate insert_undo log.
12+
INSERT INTO t VALUES(2);
13+
# Generate update_undo log.
14+
DELETE FROM t WHERE a=2;
15+
--connect(con2, localhost, root)
16+
--echo # Normal MariaDB shutdown would roll back the above transaction.
17+
--echo # We want the transaction to remain open, so we will kill the server
18+
--echo # after ensuring that any non-transactional files are clean.
19+
FLUSH TABLES;
20+
--echo # Create another transaction that will be recovered as COMMITTED.
21+
BEGIN;
22+
# Generate multiple pages of both insert_undo and update_undo, so that
23+
# the state TRX_UNDO_CACHE will not be chosen.
24+
--disable_query_log
25+
let $n= 10000;
26+
while ($n) {
27+
dec $n;
28+
eval INSERT INTO t VALUES(-$n);
29+
eval DELETE FROM t WHERE a=-$n;
30+
}
31+
--enable_query_log
32+
SET DEBUG_SYNC='after_trx_committed_in_memory SIGNAL committed WAIT_FOR ever';
33+
send COMMIT;
34+
35+
connection default;
36+
SET DEBUG_SYNC='now WAIT_FOR committed';
37+
--echo # Ensure that the above incomplete transactions become durable.
38+
SET GLOBAL innodb_flush_log_at_trx_commit=1;
39+
BEGIN;
40+
INSERT INTO t VALUES(-10000);
41+
ROLLBACK;
42+
--let $restart_parameters= --innodb-force-recovery=3
43+
--let $shutdown_timeout= 0
44+
--source include/restart_mysqld.inc
45+
--let $shutdown_timeout= 30
46+
--disconnect con1
47+
--disconnect con2
48+
SELECT * FROM t;
49+
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
50+
SELECT * FROM t;
51+
# refused on MySQL 5.6, MariaDB 10.0, 10.1, but not MariaDB 10.2+
52+
--error ER_OPEN_AS_READONLY
53+
UPDATE t SET a=3 WHERE a=1;
54+
--let $restart_parameters= --innodb-read-only
55+
--source include/restart_mysqld.inc
56+
--echo # Starting with MariaDB 10.2, innodb_read_only implies READ UNCOMMITTED.
57+
--echo # In earlier versions, this would return the last committed version
58+
--echo # (empty table)!
59+
SELECT * FROM t;
60+
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
61+
SELECT * FROM t;
62+
--let $restart_parameters=
63+
--source include/restart_mysqld.inc
64+
SELECT * FROM t;
65+
DROP TABLE t;
66+
let SEARCH_FILE= $MYSQLTEST_VARDIR/log/mysqld.1.err;
67+
--let SEARCH_PATTERN= Rolled back recovered transaction [^0]
68+
--source include/search_pattern_in_file.inc

storage/innobase/lock/lock0lock.cc

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7000,7 +7000,10 @@ lock_trx_release_locks(
70007000
}
70017001
mutex_exit(&trx_sys->mutex);
70027002
} else {
7003-
ut_ad(trx_state_eq(trx, TRX_STATE_ACTIVE));
7003+
ut_ad(trx_state_eq(trx, TRX_STATE_ACTIVE)
7004+
|| (trx_state_eq(trx, TRX_STATE_COMMITTED_IN_MEMORY)
7005+
&& trx->is_recovered
7006+
&& !UT_LIST_GET_LEN(trx->lock.trx_locks)));
70047007
}
70057008

70067009
/* The transition of trx->state to TRX_STATE_COMMITTED_IN_MEMORY

storage/innobase/trx/trx0trx.cc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*****************************************************************************
22
33
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
4-
Copyright (c) 2017, MariaDB Corporation.
4+
Copyright (c) 2017, 2018, MariaDB Corporation.
55
66
This program is free software; you can redistribute it and/or modify it under
77
the terms of the GNU General Public License as published by the Free Software
@@ -1227,6 +1227,8 @@ trx_commit_in_memory(
12271227
trx->read_view = NULL;
12281228

12291229
if (lsn) {
1230+
DEBUG_SYNC_C("after_trx_committed_in_memory");
1231+
12301232
if (trx->insert_undo != NULL) {
12311233

12321234
trx_undo_insert_cleanup(trx);

storage/innobase/trx/trx0undo.cc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*****************************************************************************
22
33
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
4-
Copyright (c) 2014, 2017, MariaDB Corporation.
4+
Copyright (c) 2014, 2018, MariaDB Corporation.
55
66
This program is free software; you can redistribute it and/or modify it under
77
the terms of the GNU General Public License as published by the Free Software
@@ -1989,7 +1989,9 @@ trx_undo_insert_cleanup(
19891989

19901990
mutex_exit(&(rseg->mutex));
19911991

1992-
trx_undo_seg_free(undo);
1992+
if (!srv_read_only_mode) {
1993+
trx_undo_seg_free(undo);
1994+
}
19931995

19941996
mutex_enter(&(rseg->mutex));
19951997

storage/xtradb/lock/lock0lock.cc

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7099,7 +7099,10 @@ lock_trx_release_locks(
70997099
}
71007100
mutex_exit(&trx_sys->mutex);
71017101
} else {
7102-
ut_ad(trx_state_eq(trx, TRX_STATE_ACTIVE));
7102+
ut_ad(trx_state_eq(trx, TRX_STATE_ACTIVE)
7103+
|| (trx_state_eq(trx, TRX_STATE_COMMITTED_IN_MEMORY)
7104+
&& trx->is_recovered
7105+
&& !UT_LIST_GET_LEN(trx->lock.trx_locks)));
71037106
}
71047107

71057108
/* The transition of trx->state to TRX_STATE_COMMITTED_IN_MEMORY

storage/xtradb/trx/trx0trx.cc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*****************************************************************************
22
33
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
4-
Copyright (c) 2017, MariaDB Corporation.
4+
Copyright (c) 2017, 2018, MariaDB Corporation.
55
66
This program is free software; you can redistribute it and/or modify it under
77
the terms of the GNU General Public License as published by the Free Software
@@ -1442,6 +1442,8 @@ trx_commit_in_memory(
14421442
if (lsn) {
14431443
ulint flush_log_at_trx_commit;
14441444

1445+
DEBUG_SYNC_C("after_trx_committed_in_memory");
1446+
14451447
if (trx->insert_undo != NULL) {
14461448

14471449
trx_undo_insert_cleanup(trx);

storage/xtradb/trx/trx0undo.cc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*****************************************************************************
22
33
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
4-
Copyright (c) 2014, 2017, MariaDB Corporation.
4+
Copyright (c) 2014, 2018, MariaDB Corporation.
55
66
This program is free software; you can redistribute it and/or modify it under
77
the terms of the GNU General Public License as published by the Free Software
@@ -1989,7 +1989,9 @@ trx_undo_insert_cleanup(
19891989

19901990
mutex_exit(&(rseg->mutex));
19911991

1992-
trx_undo_seg_free(undo);
1992+
if (!srv_read_only_mode) {
1993+
trx_undo_seg_free(undo);
1994+
}
19931995

19941996
mutex_enter(&(rseg->mutex));
19951997

0 commit comments

Comments
 (0)