Commit 228479a2 authored by Kristian Nielsen's avatar Kristian Nielsen Committed by Monty

MDEV-8075: DROP TEMPORARY TABLE not marked as ddl, causing optimistic parallel replication to fail

CREATE/DROP TEMPORARY TABLE are not safe to optimistically replicate in
parallel with other transactions, so they need to be marked as "ddl" in the
binlog.

This was already done for stand-alone CREATE/DROP TEMPORARY. But temporary
tables can also be created and dropped inside a BEGIN...END transaction, and
such transactions were not marked as ddl. Nor was the DROP TEMPORARY TABLE
statement emitted implicitly when a client connection is closed.

So this patch adds such ddl mark for the missing cases.

The difference to Kristian's original patch is mainly a fix in
mysql_trans_commit_alter_copy_data() to remember the unsafe_rollback_flags
over the temporary commit.
parent da7604a2
# Test the markings on GTID events (ddl, waited, trans,
# @@skip_parallel_replication) that are used to control parallel
# replication on the slave.
--source include/have_innodb.inc
RESET MASTER;
--source include/wait_for_binlog_checkpoint.inc
set time_zone="+02:00";
--let $stable_stamp= `SELECT UNIX_TIMESTAMP("2020-01-21 15:32:22")`
eval set timestamp=$stable_stamp;
CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
--let $binlog_pos1=query_get_value(SHOW MASTER STATUS, Position, 1)
/* GTID */ INSERT INTO t1 VALUES (1,0);
/* GTID */ BEGIN;
/* GTID */ INSERT INTO t1 VALUES (2,0);
/* GTID */ ALTER TABLE t1 ADD c INT;
/* GTID */ INSERT INTO t1 VALUES (3,0,0);
/* GTID */ COMMIT;
/* GTID */ BEGIN;
/* GTID */ UPDATE t1 SET b=1, c=1 WHERE a=2;
/* GTID */ CREATE TEMPORARY TABLE t2 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
/* GTID */ INSERT INTO t2 VALUES (4,10), (5,20);
/* GTID */ INSERT INTO t1 SELECT a, 2, b FROM t2;
/* GTID */ DROP TEMPORARY TABLE t2;
/* GTID */ INSERT INTO t1 VALUES (6, 3, 0);
/* GTID */ COMMIT;
/* GTID */ CREATE TEMPORARY TABLE t3 (a INT PRIMARY KEY) ENGINE=InnoDB;
/* GTID */ BEGIN;
/* GTID */ DELETE FROM t1 WHERE a=5;
/* GTID */ INSERT INTO t3 VALUES (7);
/* GTID */ INSERT INTO t1 SELECT a, 4, 0 FROM t3;
/* GTID */ UPDATE t1 SET c=1 WHERE a=7;
/* GTID */ DROP TEMPORARY TABLE t3;
/* GTID */ COMMIT;
/* GTID */ CREATE TEMPORARY TABLE t4 (a INT PRIMARY KEY) ENGINE=InnoDB;
/* GTID */ BEGIN;
/* GTID */ INSERT INTO t1 VALUES (8, 5, 0);
/* GTID */ ALTER TABLE t4 ADD b INT;
/* GTID */ INSERT INTO t1 VALUES (9, 5, 1);
/* GTID */ COMMIT;
connect (tmp_con,localhost,root,,);
eval set timestamp=$stable_stamp;
/* GTID */ INSERT INTO t1 VALUES (10, 6, 0);
/* GTID */ BEGIN;
/* GTID */ CREATE TEMPORARY TABLE t5 (a INT PRIMARY KEY) ENGINE=InnoDB;
/* GTID */ INSERT INTO t1 VALUES (11, 7, 0);
/* GTID */ COMMIT;
--let $before_drop_pos=query_get_value(SHOW MASTER STATUS, Position, 1)
disconnect tmp_con;
connection default;
# We need to wait for the implicit DROP TEMPORARY TABLE to be logged after
# tmp_con disconnect, otherwise we get sporadic test failures.
--let $wait_condition= SELECT variable_value > $before_drop_pos FROM information_schema.global_status WHERE variable_name = 'binlog_snapshot_position'
--source include/wait_condition.inc
--let $binlog_pos2=query_get_value(SHOW MASTER STATUS, Position, 1)
--let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1)
FLUSH LOGS;
--let $MYSQLD_DATADIR= `select @@datadir`
--let $file= $MYSQLTEST_VARDIR/tmp/binlog_parallel_replication_marks.out
--let OUTPUT_FILE=$file
exec $MYSQL_BINLOG --start_position=$binlog_pos1 --stop_position=$binlog_pos2 $MYSQLD_DATADIR/$binlog_file > $file;
perl;
my $file= $ENV{'OUTPUT_FILE'};
open F, "<", $file
or die "Unable to open file '$file': $!\n";
while (<F>) {
s/^#\d+ \d+:\d+:\d+ /# /;
s/GTID \d+-\d+-\d+/GTID #-#-#/;
s/end_log_pos \d+/end_log_pos #/;
s/table id \d+/table id #/;
s/mapped to number \d+/mapped to number #/;
print if /GTID|BEGIN|COMMIT|Table_map|Write_rows|Update_rows|Delete_rows|generated by server|40005 TEMPORARY/;
}
close F;
EOF
DROP TABLE t1;
RESET MASTER;
set time_zone="+02:00";
set timestamp=1579613542;
CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
/* GTID */ INSERT INTO t1 VALUES (1,0);
/* GTID */ BEGIN;
/* GTID */ INSERT INTO t1 VALUES (2,0);
/* GTID */ ALTER TABLE t1 ADD c INT;
/* GTID */ INSERT INTO t1 VALUES (3,0,0);
/* GTID */ COMMIT;
/* GTID */ BEGIN;
/* GTID */ UPDATE t1 SET b=1, c=1 WHERE a=2;
/* GTID */ CREATE TEMPORARY TABLE t2 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
/* GTID */ INSERT INTO t2 VALUES (4,10), (5,20);
/* GTID */ INSERT INTO t1 SELECT a, 2, b FROM t2;
/* GTID */ DROP TEMPORARY TABLE t2;
/* GTID */ INSERT INTO t1 VALUES (6, 3, 0);
/* GTID */ COMMIT;
/* GTID */ CREATE TEMPORARY TABLE t3 (a INT PRIMARY KEY) ENGINE=InnoDB;
/* GTID */ BEGIN;
/* GTID */ DELETE FROM t1 WHERE a=5;
/* GTID */ INSERT INTO t3 VALUES (7);
/* GTID */ INSERT INTO t1 SELECT a, 4, 0 FROM t3;
/* GTID */ UPDATE t1 SET c=1 WHERE a=7;
/* GTID */ DROP TEMPORARY TABLE t3;
/* GTID */ COMMIT;
/* GTID */ CREATE TEMPORARY TABLE t4 (a INT PRIMARY KEY) ENGINE=InnoDB;
/* GTID */ BEGIN;
/* GTID */ INSERT INTO t1 VALUES (8, 5, 0);
/* GTID */ ALTER TABLE t4 ADD b INT;
/* GTID */ INSERT INTO t1 VALUES (9, 5, 1);
/* GTID */ COMMIT;
set timestamp=1579613542;
/* GTID */ INSERT INTO t1 VALUES (10, 6, 0);
/* GTID */ BEGIN;
/* GTID */ CREATE TEMPORARY TABLE t5 (a INT PRIMARY KEY) ENGINE=InnoDB;
/* GTID */ INSERT INTO t1 VALUES (11, 7, 0);
/* GTID */ COMMIT;
FLUSH LOGS;
# server id 1 end_log_pos # GTID #-#-# trans
BEGIN
# server id 1 end_log_pos # Table_map: `test`.`t1` mapped to number #
# server id 1 end_log_pos # Write_rows: table id # flags: STMT_END_F
COMMIT/*!*/;
# server id 1 end_log_pos # GTID #-#-# trans
BEGIN
# server id 1 end_log_pos # Table_map: `test`.`t1` mapped to number #
# server id 1 end_log_pos # Write_rows: table id # flags: STMT_END_F
COMMIT/*!*/;
# server id 1 end_log_pos # GTID #-#-# ddl
/* GTID */ ALTER TABLE t1 ADD c INT
# server id 1 end_log_pos # GTID #-#-# trans
BEGIN
# server id 1 end_log_pos # Table_map: `test`.`t1` mapped to number #
# server id 1 end_log_pos # Write_rows: table id # flags: STMT_END_F
COMMIT/*!*/;
# server id 1 end_log_pos # GTID #-#-# trans
BEGIN
# server id 1 end_log_pos # Table_map: `test`.`t1` mapped to number #
# server id 1 end_log_pos # Update_rows: table id # flags: STMT_END_F
# server id 1 end_log_pos # Table_map: `test`.`t1` mapped to number #
# server id 1 end_log_pos # Write_rows: table id # flags: STMT_END_F
# server id 1 end_log_pos # Table_map: `test`.`t1` mapped to number #
# server id 1 end_log_pos # Write_rows: table id # flags: STMT_END_F
COMMIT/*!*/;
# server id 1 end_log_pos # GTID #-#-# trans
BEGIN
# server id 1 end_log_pos # Table_map: `test`.`t1` mapped to number #
# server id 1 end_log_pos # Delete_rows: table id # flags: STMT_END_F
# server id 1 end_log_pos # Table_map: `test`.`t1` mapped to number #
# server id 1 end_log_pos # Write_rows: table id # flags: STMT_END_F
# server id 1 end_log_pos # Table_map: `test`.`t1` mapped to number #
# server id 1 end_log_pos # Update_rows: table id # flags: STMT_END_F
COMMIT/*!*/;
# server id 1 end_log_pos # GTID #-#-# trans
BEGIN
# server id 1 end_log_pos # Table_map: `test`.`t1` mapped to number #
# server id 1 end_log_pos # Write_rows: table id # flags: STMT_END_F
COMMIT/*!*/;
# server id 1 end_log_pos # GTID #-#-# trans
BEGIN
# server id 1 end_log_pos # Table_map: `test`.`t1` mapped to number #
# server id 1 end_log_pos # Write_rows: table id # flags: STMT_END_F
COMMIT/*!*/;
# server id 1 end_log_pos # GTID #-#-# trans
BEGIN
# server id 1 end_log_pos # Table_map: `test`.`t1` mapped to number #
# server id 1 end_log_pos # Write_rows: table id # flags: STMT_END_F
COMMIT/*!*/;
# server id 1 end_log_pos # GTID #-#-# trans
BEGIN
# server id 1 end_log_pos # Table_map: `test`.`t1` mapped to number #
# server id 1 end_log_pos # Write_rows: table id # flags: STMT_END_F
COMMIT/*!*/;
# server id 1 end_log_pos # GTID #-#-# ddl
DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `t5`
DROP TABLE t1;
RESET MASTER;
set time_zone="+02:00";
set timestamp=1579613542;
CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
/* GTID */ INSERT INTO t1 VALUES (1,0);
/* GTID */ BEGIN;
/* GTID */ INSERT INTO t1 VALUES (2,0);
/* GTID */ ALTER TABLE t1 ADD c INT;
/* GTID */ INSERT INTO t1 VALUES (3,0,0);
/* GTID */ COMMIT;
/* GTID */ BEGIN;
/* GTID */ UPDATE t1 SET b=1, c=1 WHERE a=2;
/* GTID */ CREATE TEMPORARY TABLE t2 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
/* GTID */ INSERT INTO t2 VALUES (4,10), (5,20);
/* GTID */ INSERT INTO t1 SELECT a, 2, b FROM t2;
/* GTID */ DROP TEMPORARY TABLE t2;
/* GTID */ INSERT INTO t1 VALUES (6, 3, 0);
/* GTID */ COMMIT;
/* GTID */ CREATE TEMPORARY TABLE t3 (a INT PRIMARY KEY) ENGINE=InnoDB;
/* GTID */ BEGIN;
/* GTID */ DELETE FROM t1 WHERE a=5;
/* GTID */ INSERT INTO t3 VALUES (7);
/* GTID */ INSERT INTO t1 SELECT a, 4, 0 FROM t3;
/* GTID */ UPDATE t1 SET c=1 WHERE a=7;
/* GTID */ DROP TEMPORARY TABLE t3;
/* GTID */ COMMIT;
/* GTID */ CREATE TEMPORARY TABLE t4 (a INT PRIMARY KEY) ENGINE=InnoDB;
/* GTID */ BEGIN;
/* GTID */ INSERT INTO t1 VALUES (8, 5, 0);
/* GTID */ ALTER TABLE t4 ADD b INT;
/* GTID */ INSERT INTO t1 VALUES (9, 5, 1);
/* GTID */ COMMIT;
set timestamp=1579613542;
/* GTID */ INSERT INTO t1 VALUES (10, 6, 0);
/* GTID */ BEGIN;
/* GTID */ CREATE TEMPORARY TABLE t5 (a INT PRIMARY KEY) ENGINE=InnoDB;
/* GTID */ INSERT INTO t1 VALUES (11, 7, 0);
/* GTID */ COMMIT;
FLUSH LOGS;
# server id 1 end_log_pos # GTID #-#-# trans
BEGIN
/* GTID */ INSERT INTO t1 VALUES (1,0)
COMMIT/*!*/;
# server id 1 end_log_pos # GTID #-#-# trans
BEGIN
/* GTID */ INSERT INTO t1 VALUES (2,0)
COMMIT/*!*/;
# server id 1 end_log_pos # GTID #-#-# ddl
/* GTID */ ALTER TABLE t1 ADD c INT
# server id 1 end_log_pos # GTID #-#-# trans
BEGIN
/* GTID */ INSERT INTO t1 VALUES (3,0,0)
COMMIT/*!*/;
# server id 1 end_log_pos # GTID #-#-# ddl
BEGIN
/* GTID */ UPDATE t1 SET b=1, c=1 WHERE a=2
/* GTID */ CREATE TEMPORARY TABLE t2 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB
/* GTID */ INSERT INTO t2 VALUES (4,10), (5,20)
/* GTID */ INSERT INTO t1 SELECT a, 2, b FROM t2
DROP TEMPORARY TABLE `t2` /* generated by server */
/* GTID */ INSERT INTO t1 VALUES (6, 3, 0)
COMMIT/*!*/;
# server id 1 end_log_pos # GTID #-#-# ddl
/* GTID */ CREATE TEMPORARY TABLE t3 (a INT PRIMARY KEY) ENGINE=InnoDB
# server id 1 end_log_pos # GTID #-#-# ddl
BEGIN
/* GTID */ DELETE FROM t1 WHERE a=5
/* GTID */ INSERT INTO t3 VALUES (7)
/* GTID */ INSERT INTO t1 SELECT a, 4, 0 FROM t3
/* GTID */ UPDATE t1 SET c=1 WHERE a=7
DROP TEMPORARY TABLE `t3` /* generated by server */
COMMIT/*!*/;
# server id 1 end_log_pos # GTID #-#-# ddl
/* GTID */ CREATE TEMPORARY TABLE t4 (a INT PRIMARY KEY) ENGINE=InnoDB
# server id 1 end_log_pos # GTID #-#-# trans
BEGIN
/* GTID */ INSERT INTO t1 VALUES (8, 5, 0)
COMMIT/*!*/;
# server id 1 end_log_pos # GTID #-#-# ddl
/* GTID */ ALTER TABLE t4 ADD b INT
# server id 1 end_log_pos # GTID #-#-# trans
BEGIN
/* GTID */ INSERT INTO t1 VALUES (9, 5, 1)
COMMIT/*!*/;
# server id 1 end_log_pos # GTID #-#-# trans
BEGIN
/* GTID */ INSERT INTO t1 VALUES (10, 6, 0)
COMMIT/*!*/;
# server id 1 end_log_pos # GTID #-#-# ddl
BEGIN
/* GTID */ CREATE TEMPORARY TABLE t5 (a INT PRIMARY KEY) ENGINE=InnoDB
/* GTID */ INSERT INTO t1 VALUES (11, 7, 0)
COMMIT/*!*/;
# server id 1 end_log_pos # GTID #-#-# ddl
DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `t5`
DROP TABLE t1;
--source include/have_log_bin.inc
--source include/have_binlog_format_row.inc
--source include/binlog_parallel_replication_marks.test
--source include/have_log_bin.inc
--source include/have_binlog_format_mixed_or_statement.inc
--source include/binlog_parallel_replication_marks.test
......@@ -496,6 +496,53 @@ a b
57 7
58 8
59 9
*** MDEV-8075: DROP TEMPORARY TABLE not marked as ddl, causing optimistic parallel replication to fail ***
include/stop_slave.inc
INSERT INTO t1 VALUES (40, 10);
CREATE TEMPORARY TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES (41);
BEGIN;
INSERT INTO t2 SELECT a, 20 FROM t1;
DROP TEMPORARY TABLE t1;
COMMIT;
INSERT INTO t1 VALUES (42, 10);
include/save_master_gtid.inc
SELECT * FROM t1 WHERE a >= 40 ORDER BY a;
a b
40 10
42 10
SELECT * FROM t2 WHERE a >= 40 ORDER BY a;
a b
41 20
50 0
51 1
52 2
53 3
54 4
55 5
56 6
57 7
58 8
59 9
include/start_slave.inc
include/sync_with_master_gtid.inc
SELECT * FROM t1 WHERE a >= 40 ORDER BY a;
a b
40 10
42 10
SELECT * FROM t2 WHERE a >= 40 ORDER BY a;
a b
41 20
50 0
51 1
52 2
53 3
54 4
55 5
56 6
57 7
58 8
59 9
include/stop_slave.inc
SET GLOBAL slave_parallel_mode=@old_parallel_mode;
SET GLOBAL slave_parallel_threads=@old_parallel_threads;
......
......@@ -456,6 +456,30 @@ SELECT * FROM t2 WHERE a >= 50 ORDER BY a;
SELECT * FROM t2 WHERE a >= 50 ORDER BY a;
--echo *** MDEV-8075: DROP TEMPORARY TABLE not marked as ddl, causing optimistic parallel replication to fail ***
--connection server_2
--source include/stop_slave.inc
--connection server_1
INSERT INTO t1 VALUES (40, 10);
CREATE TEMPORARY TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES (41);
BEGIN;
INSERT INTO t2 SELECT a, 20 FROM t1;
DROP TEMPORARY TABLE t1;
COMMIT;
INSERT INTO t1 VALUES (42, 10);
--source include/save_master_gtid.inc
SELECT * FROM t1 WHERE a >= 40 ORDER BY a;
SELECT * FROM t2 WHERE a >= 40 ORDER BY a;
--connection server_2
--source include/start_slave.inc
--source include/sync_with_master_gtid.inc
SELECT * FROM t1 WHERE a >= 40 ORDER BY a;
SELECT * FROM t2 WHERE a >= 40 ORDER BY a;
# Clean up.
--connection server_2
......
......@@ -1470,16 +1470,30 @@ struct THD_TRANS
static unsigned int const CREATED_TEMP_TABLE= 0x02;
static unsigned int const DROPPED_TEMP_TABLE= 0x04;
static unsigned int const DID_WAIT= 0x08;
static unsigned int const DID_DDL= 0x10;
void mark_created_temp_table()
{
DBUG_PRINT("debug", ("mark_created_temp_table"));
m_unsafe_rollback_flags|= CREATED_TEMP_TABLE;
}
void mark_dropped_temp_table()
{
DBUG_PRINT("debug", ("mark_dropped_temp_table"));
m_unsafe_rollback_flags|= DROPPED_TEMP_TABLE;
}
bool has_created_dropped_temp_table() const {
return
(m_unsafe_rollback_flags & (CREATED_TEMP_TABLE|DROPPED_TEMP_TABLE)) != 0;
}
void mark_trans_did_wait() { m_unsafe_rollback_flags|= DID_WAIT; }
bool trans_did_wait() const {
return (m_unsafe_rollback_flags & DID_WAIT) != 0;
}
void mark_trans_did_ddl() { m_unsafe_rollback_flags|= DID_DDL; }
bool trans_did_ddl() const {
return (m_unsafe_rollback_flags & DID_DDL) != 0;
}
};
......
......@@ -6635,8 +6635,10 @@ Gtid_log_event::Gtid_log_event(THD *thd_arg, uint64 seq_no_arg,
if (thd_arg->transaction.stmt.trans_did_wait() ||
thd_arg->transaction.all.trans_did_wait())
flags2|= FL_WAITED;
if (sql_command_flags[thd->lex->sql_command] &
(CF_DISALLOW_IN_RO_TRANS | CF_AUTO_COMMIT_TRANS))
if (thd_arg->transaction.stmt.trans_did_ddl() ||
thd_arg->transaction.stmt.has_created_dropped_temp_table() ||
thd_arg->transaction.all.trans_did_ddl() ||
thd_arg->transaction.all.has_created_dropped_temp_table())
flags2|= FL_DDL;
else if (is_transactional)
flags2|= FL_TRANSACTIONAL;
......
......@@ -1245,6 +1245,7 @@ bool close_temporary_tables(THD *thd)
thd->variables.character_set_client= cs_save;
thd->get_stmt_da()->set_overwrite_status(true);
thd->transaction.stmt.mark_dropped_temp_table();
if ((error= (mysql_bin_log.write(&qinfo) || error)))
{
/*
......
......@@ -4048,6 +4048,16 @@ class THD :public Statement,
{
main_lex.restore_set_statement_var();
}
/* Copy relevant `stmt` transaction flags to `all` transaction. */
void merge_unsafe_rollback_flags()
{
if (transaction.stmt.modified_non_trans_table)
transaction.all.modified_non_trans_table= TRUE;
transaction.all.m_unsafe_rollback_flags|=
(transaction.stmt.m_unsafe_rollback_flags &
(THD_TRANS::DID_WAIT | THD_TRANS::CREATED_TEMP_TABLE |
THD_TRANS::DROPPED_TEMP_TABLE | THD_TRANS::DID_DDL));
}
};
......
......@@ -4360,6 +4360,15 @@ void select_create::store_values(List<Item> &values)
bool select_create::send_eof()
{
DBUG_ENTER("select_create::send_eof");
/*
The routine that writes the statement in the binary log
is in select_insert::prepare_eof(). For that reason, we
mark the flag at this point.
*/
if (table->s->tmp_table)
thd->transaction.stmt.mark_created_temp_table();
if (prepare_eof())
{
abort_result_set();
......
......@@ -2847,6 +2847,7 @@ mysql_execute_command(THD *thd)
goto error;
}
}
thd->transaction.stmt.mark_trans_did_ddl();
}
#ifndef DBUG_OFF
......@@ -6936,8 +6937,7 @@ void THD::reset_for_next_command()
if (!thd->in_multi_stmt_transaction_mode())
{
thd->variables.option_bits&= ~OPTION_KEEP_LOG;
thd->transaction.all.modified_non_trans_table= FALSE;
thd->transaction.all.m_unsafe_rollback_flags&= ~THD_TRANS::DID_WAIT;
thd->transaction.all.reset();
}
DBUG_ASSERT(thd->security_ctx== &thd->main_security_ctx);
thd->thread_specific_used= FALSE;
......
......@@ -2560,6 +2560,9 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
if (non_trans_tmp_table_deleted ||
trans_tmp_table_deleted || non_tmp_table_deleted)
{
if (non_trans_tmp_table_deleted || trans_tmp_table_deleted)
thd->transaction.stmt.mark_dropped_temp_table();
query_cache_invalidate3(thd, tables, 0);
if (!dont_log_query && mysql_bin_log.is_open())
{
......@@ -5073,6 +5076,9 @@ bool mysql_create_table(THD *thd, TABLE_LIST *create_table,
if (thd->is_current_stmt_binlog_format_row() && create_info->tmp_table())
DBUG_RETURN(result);
if (create_info->tmp_table())
thd->transaction.stmt.mark_created_temp_table();
/* Write log if no error or if we already deleted a table */
if (!result || thd->log_current_statement)
{
......@@ -5567,13 +5573,17 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
DBUG_PRINT("info",
("res: %d tmp_table: %d create_info->table: %p",
res, create_info->tmp_table(), local_create_info.table));
if (!res && create_info->tmp_table() && local_create_info.table)
if (create_info->tmp_table())
{
/*
Remember that tmp table creation was logged so that we know if
we should log a delete of it.
*/
local_create_info.table->s->table_creation_was_logged= 1;
thd->transaction.stmt.mark_created_temp_table();
if (!res && local_create_info.table)
{
/*
Remember that tmp table creation was logged so that we know if
we should log a delete of it.
*/
local_create_info.table->s->table_creation_was_logged= 1;
}
}
do_logging= TRUE;
}
......@@ -9366,8 +9376,12 @@ bool mysql_trans_prepare_alter_copy_data(THD *thd)
bool mysql_trans_commit_alter_copy_data(THD *thd)
{
bool error= FALSE;
uint save_unsafe_rollback_flags;
DBUG_ENTER("mysql_trans_commit_alter_copy_data");
/* Save flags as transcommit_implicit_are_deleting_them */
save_unsafe_rollback_flags= thd->transaction.stmt.m_unsafe_rollback_flags;
if (ha_enable_transaction(thd, TRUE))
DBUG_RETURN(TRUE);
......@@ -9382,6 +9396,7 @@ bool mysql_trans_commit_alter_copy_data(THD *thd)
if (trans_commit_implicit(thd))
error= TRUE;
thd->transaction.stmt.m_unsafe_rollback_flags= save_unsafe_rollback_flags;
DBUG_RETURN(error);
}
......
......@@ -151,11 +151,10 @@ bool trans_begin(THD *thd, uint flags)
thd->variables.option_bits&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
/*
The following set should not be needed as the flag should always be 0
when we come here. We should at some point change this to an assert.
The following set should not be needed as transaction state should
already be reset. We should at some point change this to an assert.
*/
thd->transaction.all.modified_non_trans_table= FALSE;
thd->transaction.all.m_unsafe_rollback_flags&= ~THD_TRANS::DID_WAIT;
thd->transaction.all.reset();
thd->has_waiter= false;
thd->waiting_on_group_commit= false;
......@@ -251,8 +250,7 @@ bool trans_commit(THD *thd)
else
(void) RUN_HOOK(transaction, after_commit, (thd, FALSE));
thd->variables.option_bits&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
thd->transaction.all.modified_non_trans_table= FALSE;
thd->transaction.all.m_unsafe_rollback_flags&= ~THD_TRANS::DID_WAIT;
thd->transaction.all.reset();
thd->lex->start_transaction_opt= 0;
DBUG_RETURN(MY_TEST(res));
......@@ -299,8 +297,7 @@ bool trans_commit_implicit(THD *thd)
}
thd->variables.option_bits&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
thd->transaction.all.modified_non_trans_table= FALSE;
thd->transaction.all.m_unsafe_rollback_flags&= ~THD_TRANS::DID_WAIT;
thd->transaction.all.reset();
/*
Upon implicit commit, reset the current transaction
......@@ -345,8 +342,7 @@ bool trans_rollback(THD *thd)
thd->variables.option_bits&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
/* Reset the binlog transaction marker */
thd->variables.option_bits&= ~OPTION_GTID_BEGIN;
thd->transaction.all.modified_non_trans_table= FALSE;
thd->transaction.all.m_unsafe_rollback_flags&= ~THD_TRANS::DID_WAIT;
thd->transaction.all.reset();
thd->lex->start_transaction_opt= 0;
DBUG_RETURN(MY_TEST(res));
......@@ -390,8 +386,7 @@ bool trans_rollback_implicit(THD *thd)
preserve backward compatibility.
*/
thd->variables.option_bits&= ~(OPTION_KEEP_LOG);
thd->transaction.all.modified_non_trans_table= false;
thd->transaction.all.m_unsafe_rollback_flags&= ~THD_TRANS::DID_WAIT;
thd->transaction.all.reset();
/* Rollback should clear transaction_rollback_request flag. */
DBUG_ASSERT(! thd->transaction_rollback_request);
......@@ -427,6 +422,8 @@ bool trans_commit_stmt(THD *thd)
*/
DBUG_ASSERT(! thd->in_sub_stmt);
thd->merge_unsafe_rollback_flags();
if (thd->transaction.stmt.ha_list)
{
if (WSREP_ON)
......@@ -481,6 +478,8 @@ bool trans_rollback_stmt(THD *thd)
*/
DBUG_ASSERT(! thd->in_sub_stmt);
thd->merge_unsafe_rollback_flags();
if (thd->transaction.stmt.ha_list)
{
if (WSREP_ON)
......@@ -904,8 +903,7 @@ bool trans_xa_commit(THD *thd)
}
thd->variables.option_bits&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
thd->transaction.all.modified_non_trans_table= FALSE;
thd->transaction.all.m_unsafe_rollback_flags&= ~THD_TRANS::DID_WAIT;
thd->transaction.all.reset();
thd->server_status&=
~(SERVER_STATUS_IN_TRANS | SERVER_STATUS_IN_TRANS_READONLY);
DBUG_PRINT("info", ("clearing SERVER_STATUS_IN_TRANS"));
......@@ -960,8 +958,7 @@ bool trans_xa_rollback(THD *thd)
res= xa_trans_force_rollback(thd);
thd->variables.option_bits&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
thd->transaction.all.modified_non_trans_table= FALSE;
thd->transaction.all.m_unsafe_rollback_flags&= ~THD_TRANS::DID_WAIT;
thd->transaction.all.reset();
thd->server_status&=
~(SERVER_STATUS_IN_TRANS | SERVER_STATUS_IN_TRANS_READONLY);
DBUG_PRINT("info", ("clearing SERVER_STATUS_IN_TRANS"));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment