summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMonty <monty@mariadb.org>2021-04-06 16:37:11 +0300
committerMonty <monty@mariadb.org>2021-04-07 22:45:00 +0300
commit4e2ca42225311f73745c9eec309bc941183aba30 (patch)
treef2b3db03e4f2ee6a355a21ade963535d1a166e56
parent58780b5afbd00a87899c524735ec11b3534e51ee (diff)
downloadmariadb-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.result40
-rw-r--r--mysql-test/main/backup_lock_binlog.test49
-rw-r--r--sql/sql_table.cc21
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);