Skip to content

Commit 4eff7de

Browse files
MDEV-37229: Set proper trx isolation level before every applied event
Every applier thread in Galera should run with READ_COMMITTED transaction isolation level to prevent applying issues caused by InnoDB gap locks. The exception is statement-based replication, where REPEATABLE_READ is required by the server code. Apparently, there was a separate issue with applier thread variables: wsrep_plugins_post_init() would overwrite thd->variables for every applier thread and forget to restore proper default isolation level. Then, upon every server transaction termination, trans_reset_one_shot_statistics() would set thread's isolation level to the one stored in thd->variables, thus spoiling the isolation level value for appliers.
1 parent 68432a0 commit 4eff7de

File tree

5 files changed

+52
-1
lines changed

5 files changed

+52
-1
lines changed

mysql-test/suite/galera/r/galera_binlog_stmt_autoinc.result

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,28 @@ i c
3333
3 dummy_text
3434
5 dummy_text
3535
7 dummy_text
36+
insert into t1(i) values(null);
37+
Warnings:
38+
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system variable that may have a different value on the slave
39+
insert into t1(i) values(null);
40+
Warnings:
41+
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system variable that may have a different value on the slave
42+
insert into t1(i) values(null);
43+
Warnings:
44+
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system variable that may have a different value on the slave
45+
insert into t1(i) values(null);
46+
Warnings:
47+
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system variable that may have a different value on the slave
48+
select * from t1 order by i;
49+
i c
50+
1 dummy_text
51+
3 dummy_text
52+
5 dummy_text
53+
7 dummy_text
54+
9 dummy_text
55+
11 dummy_text
56+
13 dummy_text
57+
15 dummy_text
3658
connection node_2;
3759
show variables like 'auto_increment%';
3860
Variable_name Value
@@ -44,6 +66,10 @@ i c
4466
3 dummy_text
4567
5 dummy_text
4668
7 dummy_text
69+
9 dummy_text
70+
11 dummy_text
71+
13 dummy_text
72+
15 dummy_text
4773
SET GLOBAL wsrep_forced_binlog_format='none';
4874
connection node_1;
4975
SET GLOBAL wsrep_forced_binlog_format='none';

mysql-test/suite/galera/t/galera_binlog_stmt_autoinc.cnf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@ auto_increment_offset=1
55
auto_increment_increment=2
66

77
[mysqld.2]
8+
wsrep_slave_threads=2
89
auto_increment_offset=2
910
auto_increment_increment=2

mysql-test/suite/galera/t/galera_binlog_stmt_autoinc.test

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,17 @@ insert into t1(i) values(null), (null), (null);
4848

4949
select * from t1 order by i;
5050

51+
# Ensure both appliers have some work to perform in parallel.
52+
# This way we can see they both have proper isolation level set.
53+
insert into t1(i) values(null);
54+
insert into t1(i) values(null);
55+
insert into t1(i) values(null);
56+
insert into t1(i) values(null);
57+
58+
select * from t1 order by i;
59+
5160
--connection node_2
52-
--let $wait_condition = SELECT COUNT(*) = 4 FROM t1;
61+
--let $wait_condition = SELECT COUNT(*) = 8 FROM t1;
5362
--source include/wait_condition.inc
5463
show variables like 'auto_increment%';
5564
select * from t1 order by i;

sql/sql_plugin.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4545,6 +4545,8 @@ my_bool post_init_callback(THD *thd, void *)
45454545

45464546
// Restore option_bits
45474547
thd->variables.option_bits= option_bits_saved;
4548+
// Restore proper default isolation level for appliers.
4549+
thd->variables.tx_isolation= ISO_READ_COMMITTED;
45484550
}
45494551
set_current_thd(0);
45504552
return 0;

sql/wsrep_applier.cc

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,19 @@ int wsrep_apply_events(THD* thd,
253253
}
254254
}
255255

256+
/* Statement-based replication requires InnoDB repeatable read
257+
transaction isolation level or higher. */
258+
if (LOG_EVENT_IS_QUERY(typ))
259+
{
260+
thd->variables.tx_isolation= ISO_REPEATABLE_READ;
261+
thd->tx_isolation = ISO_REPEATABLE_READ;
262+
}
263+
else
264+
{
265+
thd->variables.tx_isolation= ISO_READ_COMMITTED;
266+
thd->tx_isolation = ISO_READ_COMMITTED;
267+
}
268+
256269
if (LOG_EVENT_IS_WRITE_ROW(typ) ||
257270
LOG_EVENT_IS_UPDATE_ROW(typ) ||
258271
LOG_EVENT_IS_DELETE_ROW(typ))

0 commit comments

Comments
 (0)