diff options
author | Monty <monty@mariadb.org> | 2021-04-06 16:37:11 +0300 |
---|---|---|
committer | Monty <monty@mariadb.org> | 2021-04-07 22:45:00 +0300 |
commit | 4e2ca42225311f73745c9eec309bc941183aba30 (patch) | |
tree | f2b3db03e4f2ee6a355a21ade963535d1a166e56 | |
parent | 58780b5afbd00a87899c524735ec11b3534e51ee (diff) | |
download | mariadb-git-4e2ca42225311f73745c9eec309bc941183aba30.tar.gz |
MDEV-25334 FTWRL/Backup blocks DDL on temporary tables with binlog enabled, assertion fails in Diagnostics_area::set_error_status
Fixed by adding a MDL_BACKUP_COMMIT lock before altering temporary tables
whose creation was logged to binary log (in which case the ALTER TABLE
must also be logged)
-rw-r--r-- | mysql-test/main/backup_lock_binlog.result | 40 | ||||
-rw-r--r-- | mysql-test/main/backup_lock_binlog.test | 49 | ||||
-rw-r--r-- | sql/sql_table.cc | 21 |
3 files changed, 107 insertions, 3 deletions
diff --git a/mysql-test/main/backup_lock_binlog.result b/mysql-test/main/backup_lock_binlog.result new file mode 100644 index 00000000000..adf960a9cb1 --- /dev/null +++ b/mysql-test/main/backup_lock_binlog.result @@ -0,0 +1,40 @@ +# +# MDEV-25334 FTWRL/Backup blocks DDL on temporary tables with binlog +# enabled assertion fails in Diagnostics_area::set_error_status +# +select @@binlog_format; +@@binlog_format +MIXED +connect con1,localhost,root,,; +connection default; +# +# Test 1 +# +CREATE TEMPORARY TABLE tmp (a INT); +connection con1; +FLUSH TABLES WITH READ LOCK; +connection default; +SET lock_wait_timeout= 1; +ALTER TABLE tmp; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +connection con1; +unlock tables; +connection default; +drop table tmp; +# +# Test 2 (In statement format to ensure temporary table gets logged) +# +set @@binlog_format=statement; +CREATE TEMPORARY TABLE tmp (a INT); +connection con1; +BACKUP STAGE START; +BACKUP STAGE BLOCK_COMMIT; +connection default; +SET lock_wait_timeout= 1; +ALTER TABLE tmp; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +connection con1; +BACKUP STAGE end; +connection default; +drop table tmp; +disconnect con1; diff --git a/mysql-test/main/backup_lock_binlog.test b/mysql-test/main/backup_lock_binlog.test new file mode 100644 index 00000000000..45b3f1cfbd9 --- /dev/null +++ b/mysql-test/main/backup_lock_binlog.test @@ -0,0 +1,49 @@ +--source include/have_binlog_format_mixed_or_statement.inc + +# +# Tests involving locks and binlog +# + +--echo # +--echo # MDEV-25334 FTWRL/Backup blocks DDL on temporary tables with binlog +--echo # enabled assertion fails in Diagnostics_area::set_error_status +--echo # + +select @@binlog_format; +--connect (con1,localhost,root,,) +connection default; + +--echo # +--echo # Test 1 +--echo # + +CREATE TEMPORARY TABLE tmp (a INT); +--connection con1 +FLUSH TABLES WITH READ LOCK; +--connection default +SET lock_wait_timeout= 1; +--error ER_LOCK_WAIT_TIMEOUT +ALTER TABLE tmp; +--connection con1 +unlock tables; +--connection default +drop table tmp; + +--echo # +--echo # Test 2 (In statement format to ensure temporary table gets logged) +--echo # + +set @@binlog_format=statement; +CREATE TEMPORARY TABLE tmp (a INT); +--connection con1 +BACKUP STAGE START; +BACKUP STAGE BLOCK_COMMIT; +--connection default +SET lock_wait_timeout= 1; +--error ER_LOCK_WAIT_TIMEOUT +ALTER TABLE tmp; +--connection con1 +BACKUP STAGE end; +--connection default +drop table tmp; +--disconnect con1 diff --git a/sql/sql_table.cc b/sql/sql_table.cc index ea1a35a9ddd..680258141f2 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -9574,7 +9574,8 @@ bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db, If such table exists, there must be a corresponding TABLE_SHARE in THD::all_temp_tables list. */ - if (thd->find_tmp_table_share(alter_ctx.new_db.str, alter_ctx.new_name.str)) + if (thd->find_tmp_table_share(alter_ctx.new_db.str, + alter_ctx.new_name.str)) { my_error(ER_TABLE_EXISTS_ERROR, MYF(0), alter_ctx.new_alias.str); DBUG_RETURN(true); @@ -9715,6 +9716,17 @@ bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db, if (table->s->tmp_table == NO_TMP_TABLE) mysql_audit_alter_table(thd, table_list); + else if (table->s->table_creation_was_logged && mysql_bin_log.is_open()) + { + /* Protect against MDL error in binary logging */ + MDL_request mdl_request; + DBUG_ASSERT(!mdl_ticket); + mdl_request.init(MDL_key::BACKUP, "", "", MDL_BACKUP_COMMIT, + MDL_TRANSACTION); + if (thd->mdl_context.acquire_lock(&mdl_request, + thd->variables.lock_wait_timeout)) + DBUG_RETURN(true); + } THD_STAGE_INFO(thd, stage_setup); @@ -9794,9 +9806,12 @@ do_continue:; thd->get_stmt_da()->current_statement_warn_count()); my_ok(thd, 0L, 0L, alter_ctx.tmp_buff); - /* We don't replicate alter table statement on temporary tables */ + /* + We don't replicate alter table statement on temporary tables + For which we did not log the CREATE TEMPORARY TABLE statement. + */ if (table->s->tmp_table == NO_TMP_TABLE || - !thd->is_current_stmt_binlog_format_row()) + table->s->table_creation_was_logged) { if (write_bin_log(thd, true, thd->query(), thd->query_length())) DBUG_RETURN(true); |