mirror of
https://github.com/MariaDB/server.git
synced 2025-05-10 15:59:53 +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.
158 lines
7.3 KiB
Text
158 lines
7.3 KiB
Text
include/master-slave.inc
|
|
[connection master]
|
|
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;
|
|
#
|
|
# MDEV-35207 ignored error at binlogging by CREATE-TABLE-SELECT leads to assert
|
|
#
|
|
connect conn_err,localhost,root,,;
|
|
call mtr.add_suppression("Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage");
|
|
create table t engine=myisam select repeat ('a',4096*3) AS a;
|
|
ERROR HY000: Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage; increase this mariadbd variable and try again
|
|
create table t engine=innodb select repeat ('a',4096*3) AS a;
|
|
ERROR HY000: Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage; increase this mariadbd variable and try again
|
|
create table t (a int unique, b char) select 1 AS a, 'b' as b union select 1 as a, 'c' as b;
|
|
ERROR 23000: Duplicate entry '1' for key 'a'
|
|
select * from t;
|
|
ERROR 42S02: Table 'test.t' doesn't exist
|
|
disconnect conn_err;
|
|
connection master;
|
|
|
|
#
|
|
# MDEV-35499 errored CREATE-OR-REPLACE-SELECT does not DROP table in binlog
|
|
#
|
|
#
|
|
# Engine = innodb
|
|
#
|
|
set statement binlog_format=statement for create table t (a int) select 1 as a;
|
|
set statement binlog_format=row for create or replace table t (a int primary key, b char) engine=innodb select 1 AS a, 'b' as b union select 1 as a, 'c' as b;
|
|
ERROR 23000: Duplicate entry '1' for key 'PRIMARY'
|
|
select * from t;
|
|
ERROR 42S02: Table 'test.t' doesn't exist
|
|
#
|
|
# Prove an expected lonely `DROP table t'
|
|
include/show_binlog_events.inc
|
|
Log_name Pos Event_type Server_id End_log_pos Info
|
|
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
|
|
master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS `test`.`t`/* Generated to handle failed CREATE OR REPLACE */
|
|
master-bin.000001 # Query # # ROLLBACK
|
|
set statement binlog_format=statement for create table t (a int) select 1 as a;
|
|
set statement binlog_format=row for create or replace table t (a text) engine=innodb select repeat ('a',1024) AS a union select repeat ('a',3*4096) AS a union select repeat ('a',3*4096) AS a;
|
|
ERROR HY000: Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage; increase this mariadbd variable and try again
|
|
select * from t;
|
|
ERROR 42S02: Table 'test.t' doesn't exist
|
|
#
|
|
# Prove an expected lonely `DROP table t'
|
|
include/show_binlog_events.inc
|
|
Log_name Pos Event_type Server_id End_log_pos Info
|
|
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
|
|
master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS `test`.`t`/* Generated to handle failed CREATE OR REPLACE */
|
|
master-bin.000001 # Query # # ROLLBACK
|
|
set statement binlog_format=statement for create table t (a int) select 1 as a;
|
|
set statement binlog_format=row for create or replace table t (a text) engine=innodb select repeat ('a',4096*3) AS a;;
|
|
ERROR HY000: Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage; increase this mariadbd variable and try again
|
|
select * from t;
|
|
ERROR 42S02: Table 'test.t' doesn't exist
|
|
#
|
|
# Prove an expected lonely `DROP table t'
|
|
include/show_binlog_events.inc
|
|
Log_name Pos Event_type Server_id End_log_pos Info
|
|
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
|
|
master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS `test`.`t`/* Generated to handle failed CREATE OR REPLACE */
|
|
master-bin.000001 # Query # # ROLLBACK
|
|
#
|
|
# Engine = myisam
|
|
#
|
|
set statement binlog_format=statement for create table t (a int) select 1 as a;
|
|
set statement binlog_format=row for create or replace table t (a int primary key, b char) engine=myisam select 1 AS a, 'b' as b union select 1 as a, 'c' as b;
|
|
ERROR 23000: Duplicate entry '1' for key 'PRIMARY'
|
|
select * from t;
|
|
ERROR 42S02: Table 'test.t' doesn't exist
|
|
#
|
|
# Prove an expected lonely `DROP table t'
|
|
include/show_binlog_events.inc
|
|
Log_name Pos Event_type Server_id End_log_pos Info
|
|
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
|
|
master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS `test`.`t`/* Generated to handle failed CREATE OR REPLACE */
|
|
master-bin.000001 # Query # # ROLLBACK
|
|
set statement binlog_format=statement for create table t (a int) select 1 as a;
|
|
set statement binlog_format=row for create or replace table t (a text) engine=myisam select repeat ('a',1024) AS a union select repeat ('a',3*4096) AS a union select repeat ('a',3*4096) AS a;
|
|
ERROR HY000: Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage; increase this mariadbd variable and try again
|
|
select * from t;
|
|
ERROR 42S02: Table 'test.t' doesn't exist
|
|
#
|
|
# Prove an expected lonely `DROP table t'
|
|
include/show_binlog_events.inc
|
|
Log_name Pos Event_type Server_id End_log_pos Info
|
|
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
|
|
master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS `test`.`t`/* Generated to handle failed CREATE OR REPLACE */
|
|
master-bin.000001 # Query # # ROLLBACK
|
|
set statement binlog_format=statement for create table t (a int) select 1 as a;
|
|
set statement binlog_format=row for create or replace table t (a text) engine=myisam select repeat ('a',4096*3) AS a;;
|
|
ERROR HY000: Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage; increase this mariadbd variable and try again
|
|
select * from t;
|
|
ERROR 42S02: Table 'test.t' doesn't exist
|
|
#
|
|
# Prove an expected lonely `DROP table t'
|
|
include/show_binlog_events.inc
|
|
Log_name Pos Event_type Server_id End_log_pos Info
|
|
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
|
|
master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS `test`.`t`/* Generated to handle failed CREATE OR REPLACE */
|
|
master-bin.000001 # Query # # ROLLBACK
|
|
create table ti_pk (a int primary key) engine=innodb;
|
|
create table ta (a int) engine=aria;
|
|
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 |
|
|
set statement binlog_format = ROW for create table t_y (a int) engine=aria select f_ia(1 /* err */) as a;
|
|
ERROR 23000: Duplicate entry '1' for key 'PRIMARY'
|
|
select * from t_y;
|
|
ERROR 42S02: Table 'test.t_y' doesn't exist
|
|
# correct execution: `ta` is modified and its new record is binlogged
|
|
include/show_binlog_events.inc
|
|
Log_name Pos Event_type Server_id End_log_pos Info
|
|
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
|
|
master-bin.000001 # Table_map # # table_id: # (test.ta)
|
|
master-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F
|
|
master-bin.000001 # Query # # COMMIT
|
|
select * from ta;
|
|
a
|
|
1
|
|
select * from ti_pk;
|
|
a
|
|
connection slave;
|
|
include/diff_tables.inc [master:ta,slave:ta]
|
|
connection master;
|
|
delete from ta;
|
|
connection slave;
|
|
connection master;
|
|
set statement binlog_format = STATEMENT for create table t_y (a int) engine=aria select f_ia(1 /* err */) as a;
|
|
ERROR 23000: Duplicate entry '1' for key 'PRIMARY'
|
|
select * from t_y;
|
|
ERROR 42S02: Table 'test.t_y' doesn't exist
|
|
# ***TODO: fix MDEV-36027***. As of now `ta` is modified but that's not binlogged
|
|
include/show_binlog_events.inc
|
|
select *,'on_master' from ta;
|
|
a on_master
|
|
1 on_master
|
|
select * from ti_pk;
|
|
a
|
|
connection slave;
|
|
select *,'on_slave' from ta;
|
|
a on_slave
|
|
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;
|
|
connection slave;
|
|
End of the tests
|
|
include/rpl_end.inc
|