mirror of
https://github.com/MariaDB/server.git
synced 2025-07-06 03:18:17 +02:00

MDEV-35499 Errored-out CREATE-or-REPLACE-SELECT does not log DROP table into binlog MDEV-35502 Failed at ROW-format binlogging CREATE-TABLE-SELECT should not generate Incident event When a CREATE TABLE .. SELECT errors while inserting data, a user would expect that all changes are rolled back and the table would not exist after executing the query. However CREATE-TABLE-SELECT can face an error near the end of its execution select_create::send_eof() so that the error was never checked which led to various assert inside binlogging path that should not be attended at all. Specifically when binlog_commit() of ha_commit_one_phase() that CREATE-TABLE-SELECT employs errored out because of a limited cache size (binlog_commit may try writing to a transactional cache) the cache was not flushed to binlog. The missed error check allowed further execution down to trans_commit_implicit() in whose stack DBUG_ASSERT(!(entry->using_trx_cache && !mngr->trx_cache.empty() && mngr->get_binlog_cache_log(TRUE)->error)); fired. In a non-debug build that table remains created/populated inconsistently with binlog. The fixes need and install the error checking in select_create::send_eof(). That prevents from any further execution when ha_commit_one_phase() fails for any reason (typically due to binlog_commit()). This commit also covers CREATE-or-REPLACE-SELECT that additionally had a specific issue in that DROP TABLE was not logged the binary log, MDEV-35499. See changes select_create::abort_result_set(). The current commit also corrects an unnecessary Incident event logging when CREATE-TABLE-SELECT encounters a binloging issue, MDEV-35502. The Incident was actually only harmful in this case as the table was never going to be created, therefore replicated, in such a case. In "normal" cases when the SELECT phase errors due to binlogging, an internal incident flag gets reset inside select_create::abort_result_set(). A hunk in select_insert::prepare_eof() addresses a specific kind of this issue that deals with incorrect computation of the binlog cache type. Because of that in the OLD version execution was allowed to proceed along ha_commit_trans()..binlog_commit() while a Pending event was not flushed to the transactional cache. That might lead to the unnecessary binlogged Incident despite the select_create::abort_result_set() measures. However now with the corrected cache type any binlogging error to flush the Pending event is covered according to the normal case. non-transaction table, updates to the non-transactional table NOTE the commit contains few tests overlapping with unfixed yet MDEV-36027. Thanks to Brandon Nesterenko and Kristian Nielsen for thorough review, and Kristian additionally for ideas to simplify the patch and some code contribution.
161 lines
5.5 KiB
Text
161 lines
5.5 KiB
Text
--source include/have_binlog_format_row.inc
|
|
--source include/have_innodb.inc
|
|
--source include/master-slave.inc
|
|
|
|
--connection master
|
|
set @max_binlog_cache_size = @@global.max_binlog_cache_size;
|
|
set @binlog_cache_size = @@global.binlog_cache_size;
|
|
set @@global.max_binlog_cache_size = 4096;
|
|
set @@global. binlog_cache_size = 4096;
|
|
|
|
--echo #
|
|
--echo # MDEV-35207 ignored error at binlogging by CREATE-TABLE-SELECT leads to assert
|
|
--echo #
|
|
# fix the current (write) binlog position
|
|
--let $binlog_file_0= query_get_value(SHOW MASTER STATUS, File, 1)
|
|
--let $binlog_start_0 = query_get_value(SHOW MASTER STATUS, Position, 1)
|
|
|
|
# use a separate connection also to validate its close will be clean
|
|
connect (conn_err,localhost,root,,);
|
|
|
|
call mtr.add_suppression("Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage");
|
|
--error ER_TRANS_CACHE_FULL
|
|
create table t engine=myisam select repeat ('a',4096*3) AS a;
|
|
|
|
--error ER_TRANS_CACHE_FULL
|
|
create table t engine=innodb select repeat ('a',4096*3) AS a;
|
|
|
|
--error ER_DUP_ENTRY
|
|
create table t (a int unique, b char) select 1 AS a, 'b' as b union select 1 as a, 'c' as b;
|
|
--error ER_NO_SUCH_TABLE
|
|
select * from t;
|
|
|
|
--disconnect conn_err
|
|
|
|
--connection master
|
|
--let $binlog_file_1= query_get_value(SHOW MASTER STATUS, File, 1)
|
|
--let $binlog_start_1= query_get_value(SHOW MASTER STATUS, Position, 1)
|
|
|
|
--let $cmp = `select strcmp('$binlog_file_1', '$binlog_file_0') <> 0 OR $binlog_start_1 <> $binlog_start_0`
|
|
if (!$cmp)
|
|
{
|
|
--echo *** Error: unexpected advance of binlog position
|
|
--die
|
|
}
|
|
|
|
--echo
|
|
--echo #
|
|
--echo # MDEV-35499 errored CREATE-OR-REPLACE-SELECT does not DROP table in binlog
|
|
--echo #
|
|
--let $i = 2
|
|
while ($i)
|
|
{
|
|
--let $engine=`select if($i % 2, "myisam", "innodb")`
|
|
--echo #
|
|
--echo # Engine = $engine
|
|
--echo #
|
|
set statement binlog_format=statement for create table t (a int) select 1 as a;
|
|
--let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1)
|
|
--let $binlog_start = query_get_value(SHOW MASTER STATUS, Position, 1)
|
|
--error ER_DUP_ENTRY
|
|
--eval set statement binlog_format=row for create or replace table t (a int primary key, b char) engine=$engine select 1 AS a, 'b' as b union select 1 as a, 'c' as b
|
|
--error ER_NO_SUCH_TABLE
|
|
select * from t;
|
|
--echo #
|
|
--echo # Prove an expected lonely `DROP table t'
|
|
--source include/show_binlog_events.inc
|
|
|
|
# error before stmt commit
|
|
set statement binlog_format=statement for create table t (a int) select 1 as a;
|
|
--let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1)
|
|
--let $binlog_start = query_get_value(SHOW MASTER STATUS, Position, 1)
|
|
--error ER_TRANS_CACHE_FULL
|
|
--eval set statement binlog_format=row for create or replace table t (a text) engine=$engine select repeat ('a',1024) AS a union select repeat ('a',3*4096) AS a union select repeat ('a',3*4096) AS a
|
|
--error ER_NO_SUCH_TABLE
|
|
select * from t;
|
|
--echo #
|
|
--echo # Prove an expected lonely `DROP table t'
|
|
--source include/show_binlog_events.inc
|
|
|
|
# error at stmt commit
|
|
set statement binlog_format=statement for create table t (a int) select 1 as a;
|
|
--let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1)
|
|
--let $binlog_start = query_get_value(SHOW MASTER STATUS, Position, 1)
|
|
--error ER_TRANS_CACHE_FULL
|
|
--eval set statement binlog_format=row for create or replace table t (a text) engine=$engine select repeat ('a',4096*3) AS a;
|
|
--error ER_NO_SUCH_TABLE
|
|
select * from t;
|
|
--echo #
|
|
--echo # Prove an expected lonely `DROP table t'
|
|
--source include/show_binlog_events.inc
|
|
|
|
--dec $i
|
|
}
|
|
|
|
# Tests of mixed engines to demonstrate non-transaction table updates
|
|
# are binlogged or otherwise MDEV-36027.
|
|
create table ti_pk (a int primary key) engine=innodb;
|
|
create table ta (a int) engine=aria;
|
|
delimiter |;
|
|
create function f_ia(arg int)
|
|
returns integer
|
|
begin
|
|
insert into ti_pk set a=1;
|
|
insert into ta set a=1;
|
|
insert into ti_pk set a=arg;
|
|
return 1;
|
|
end |
|
|
delimiter ;|
|
|
|
|
--let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1)
|
|
--let $binlog_start = query_get_value(SHOW MASTER STATUS, Position, 1)
|
|
|
|
--error ER_DUP_ENTRY
|
|
set statement binlog_format = ROW for create table t_y (a int) engine=aria select f_ia(1 /* err */) as a;
|
|
--error ER_NO_SUCH_TABLE
|
|
select * from t_y;
|
|
|
|
--echo # correct execution: `ta` is modified and its new record is binlogged
|
|
--source include/show_binlog_events.inc
|
|
select * from ta;
|
|
select * from ti_pk;
|
|
|
|
--sync_slave_with_master
|
|
--let $diff_tables=master:ta,slave:ta
|
|
--source include/diff_tables.inc
|
|
|
|
--connection master
|
|
delete from ta;
|
|
--sync_slave_with_master
|
|
|
|
--connection master
|
|
# MDEV-36027 Errored-out CREATE-SELECT does not binlog results of any function modifying non-transactional table
|
|
--let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1)
|
|
--let $binlog_start = query_get_value(SHOW MASTER STATUS, Position, 1)
|
|
--error ER_DUP_ENTRY
|
|
set statement binlog_format = STATEMENT for create table t_y (a int) engine=aria select f_ia(1 /* err */) as a;
|
|
--error ER_NO_SUCH_TABLE
|
|
select * from t_y;
|
|
|
|
--echo # ***TODO: fix MDEV-36027***. As of now `ta` is modified but that's not binlogged
|
|
--source include/show_binlog_events.inc
|
|
select *,'on_master' from ta;
|
|
select * from ti_pk;
|
|
|
|
--sync_slave_with_master
|
|
select *,'on_slave' from ta;
|
|
|
|
# Cleanup
|
|
--connection master
|
|
drop function f_ia;
|
|
drop table ti_pk, ta;
|
|
|
|
SET @@global.max_binlog_cache_size = @max_binlog_cache_size;
|
|
SET @@global. binlog_cache_size = @binlog_cache_size;
|
|
|
|
# test that binlog replicates correctly to slave
|
|
# --connection slave
|
|
--sync_slave_with_master
|
|
|
|
--echo End of the tests
|
|
--source include/rpl_end.inc
|