1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-30 16:24:05 +03:00

MDEV-32126 Assertion fails upon online ALTER and binary log enabled

Assertion `!writer.checksum_len || writer.remains == 0' fails upon
concurrent online ALTER and transactions with failing statements and binary
log enabled.
Also another assertion, `pos != (~(my_off_t) 0)', fails in my_seek, upon
reinit_io_cache, on a simplified test. This means that IO_CACHE wasn't
properly initialized, or had an error before.

The overall problem is a deep interference with the effect of an installed
binlog_hton: the assumption about that thd->binlog_get_cache_mngr() is,
sufficiently, NULL, when we shouldn't run the binlog part of
binlog_commit/binlog_rollback, is wrong: as turns out, sometimes the binlog
handlerton can be not installed in current thd, but binlog_commit can be
called on behalf of binlog, as in the bug reported.

One separate condition found is XA recovery of the orphaned transaction,
when binlog_commit is also called, but it has nothing to do with
online alter.

Solution:
Extract online alter operations into a separate handlerton.
This commit is contained in:
Nikita Malyavin
2023-09-19 18:19:10 +04:00
parent a1019e93d6
commit 830bdfccbd
6 changed files with 172 additions and 17 deletions

View File

@ -1736,6 +1736,60 @@ set debug_sync= reset;
drop table iso_levels;
--echo # MDEV-32126 Assertion fails upon online ALTER and binary log enabled
create temporary table tmp (id int, primary key(id)) engine=innodb;
create table t1 (a int, b text) engine=innodb;
create table t2 (a int, b int, c char(8), d text, unique(a)) engine=innodb;
insert into t2 values (1,1,'f','e'),(1000,1000,'c','b');
--connection default
set debug_sync= 'alter_table_online_before_lock signal go_trx wait_for go_alter';
send alter table t2 force, algorithm=copy, lock=none;
--connection con2
set debug_sync= 'now wait_for go_trx';
start transaction;
insert into t1 values (3,'a');
--error ER_DUP_ENTRY
insert into t2 values (3,3,'a','x'), (3,3,'a','x');
insert into t2 values (3,3,'a','x');
commit;
set debug_sync= 'now signal go_alter';
--connection default
--reap
truncate t2;
set @@binlog_format=mixed;
--connection con2
start transaction;
create temporary table tmp (id int, primary key(id)) engine=innodb;
insert into t1 values (1, repeat('x',8000)),(2, repeat('x',8000));
update t2 set b = null order by b limit 2;
insert into t1 values (3, repeat('x',8000));
delete from t1;
insert into t2 values (1,1,'f','e'),(1000,1000,'c','b');
commit;
--connection default
set debug_sync= 'alter_table_online_before_lock signal go_trx wait_for go_alter';
send alter table t2 force, algorithm=copy, lock=none;
--connection con2
set debug_sync= 'now wait_for go_trx';
start transaction;
drop temporary table if exists tmp;
--error ER_DUP_ENTRY
insert into t2 values (3,3,'a','x'), (3,3,'a','x');
insert into t2 values (3,3,'a','x');
commit;
set debug_sync= 'now signal go_alter';
--connection default
--reap
drop table t1, t2;
set @@binlog_format=default;
set debug_sync= reset;
--disconnect con1
--disconnect con2