Skip to content

Commit

Permalink
Bug#28606948: BACKPORT OF BUG#24670909 TO 5.7.22
Browse files Browse the repository at this point in the history
Backported the changes from mysql-8.0 to mysql-5.7

BUG#24670909:

Problem:
Previously, a session disconnect causes DROP TEMPORARY TABLE IF EXISTS
to be binlogged for all the opened temp tables in that session. Even
though temporary table operation are not otherwise binlogged in row or
mixed mode, this was done regardless of binary log format in use, as
it was not tracked, whether a particular temp table was not created in
STATEMENT mode - in which case it does need the DROP.
For ROW/MIXED users, this behavior causes spurious binlog writes
and GTIDs generated on otherwise read only servers.

Fix:
Track the binlog format at temporary table create time
(open_table_uncached and after final decide_logging_format call for
CREATE ... SELECT), and that can be used to decide whether a DROP should be
logged or not in method close_temporary_tables.
  • Loading branch information
Neha Kumari committed Nov 1, 2018
1 parent 2348605 commit 9827f13
Show file tree
Hide file tree
Showing 18 changed files with 423 additions and 75 deletions.
79 changes: 58 additions & 21 deletions mysql-test/extra/binlog_tests/drop_temp_table.test
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,11 @@ connection con2;
SELECT GET_LOCK("a",10);
let $VERSION=`SELECT VERSION()`;

let $wait_binlog_event=DROP /*!40005 TEMPORARY */ TABLE IF EXISTS;
source include/wait_for_binlog_event.inc;
if (`SELECT @@GLOBAL.binlog_format != 'ROW'`)
{
let $wait_binlog_event=DROP /*!40005 TEMPORARY */ TABLE IF EXISTS;
source include/wait_for_binlog_event.inc;
}

source include/show_binlog_events.inc;
DROP DATABASE `drop-temp+table-test`;
Expand All @@ -86,27 +89,58 @@ DROP DATABASE `drop-temp+table-test`;

RESET MASTER;

CREATE TABLE t1 ( i text );
if (`SELECT @@GLOBAL.binlog_format != 'ROW'`)
{
CREATE TABLE t1 ( i text );

--connect(con1,localhost,root,,)
CREATE TEMPORARY TABLE ttmp1 ( i text );
SET @@session.binlog_format=ROW;
INSERT INTO t1 VALUES ('1');
SELECT @@session.binlog_format;
--disconnect con1

-- connection default
--let $wait_binlog_event= DROP
--source include/wait_for_binlog_event.inc
--let $mask_binlog_commit_events= 1
-- source include/show_binlog_events.inc
--let $mask_binlog_commit_events= 0
DROP TABLE t1;
RESET MASTER;
}

--connect(con1,localhost,root,,)
CREATE TEMPORARY TABLE ttmp1 ( i text );
SET @@session.binlog_format=ROW;
INSERT INTO t1 VALUES ('1');
SELECT @@session.binlog_format;
--disconnect con1
# End of 4.1 tests

-- connection default
--let $wait_binlog_event= DROP
--source include/wait_for_binlog_event.inc
--let $mask_binlog_commit_events= 1
-- source include/show_binlog_events.inc
--let $mask_binlog_commit_events= 0
RESET MASTER;
--echo #
--echo # Bug 83003: Using temporary tables on slaves increases GTID sequence number
--echo #

DROP TABLE t1;
--source include/count_sessions.inc
--connect (con1,localhost,root,,)

# End of 4.1 tests
SET @saved_binlog_format= @@SESSION.binlog_format;
SET SESSION binlog_format= STATEMENT;
CREATE TEMPORARY TABLE temp_needs_logging(a INT) ENGINE=InnoDB;
SET SESSION binlog_format= @saved_binlog_format;

# Check with both transactional and non-transactional tables as those are logged
# separately in close_temporary_tables.
CREATE TEMPORARY TABLE temp_trx(a INT) ENGINE=InnoDB;
CREATE TEMPORARY TABLE temp_non_trx(a INT) ENGINE=MyISAM;

CREATE TEMPORARY TABLE temp_needs_logging_in_stmt(a INT) ENGINE=InnoDB;
SET SESSION sql_log_bin= 0;
CREATE TEMPORARY TABLE temp_binlog_disabled(a INT) ENGINE=InnoDB;
SET SESSION sql_log_bin= 1;

--disconnect con1
--connection default
--source include/wait_until_count_sessions.inc

--source include/show_binlog_events.inc

# End of 5.6 tests
--echo #
--echo # BUG#21638823: ASSERTION FAILED:
--echo # THD->GET_TRANSACTION()->IS_EMPTY(TRANSACTION_CTX::STMT) || THD
Expand All @@ -133,8 +167,11 @@ XA END 'idle_at_disconnect';
--disconnect con3
--source include/wait_until_disconnected.inc
--connection default
--let $wait_binlog_event= DROP
--source include/wait_for_binlog_event.inc
if (`SELECT @@GLOBAL.binlog_format != 'ROW'`)
{
--let $wait_binlog_event= DROP
--source include/wait_for_binlog_event.inc
}
--echo # Dump binlog to show that, either the generated DROP comes after tx
--echo # commit (stmt or mixed), or there is no trace of the XA txn and
--echo # the temp table (row)
Expand All @@ -151,4 +188,4 @@ XA ROLLBACK 'idle_when_drop_temp';

# clean up the binary log at in the end of the test
# case as well.
RESET MASTER;
RESET MASTER;
17 changes: 10 additions & 7 deletions mysql-test/extra/binlog_tests/mix_innodb_myisam_binlog.test
Original file line number Diff line number Diff line change
Expand Up @@ -241,13 +241,16 @@ disconnect con2;
# Wait until con2 disconnects
--source include/wait_until_disconnected.inc
connection con3;
# Bug #22084462 - MYSQL TEST BINLOG.BINLOG_ROW_MIX_INNODB_MYISAM FAILS
# Wait to ensure that drop temporary tables events
# are present in binary log.
--let $event_sequence= (Anonymous_)?Gtid # !Q(DROP.*TEMPORARY.*) # (Anonymous_)?Gtid # !Q(DROP.*TEMPORARY.*)
--let $limit= 0,4
--let $wait_for_binlog_events= 1
--source include/assert_binlog_events.inc
if (`SELECT @@GLOBAL.binlog_format = 'STATEMENT'`)
{
# Bug #22084462 - MYSQL TEST BINLOG.BINLOG_ROW_MIX_INNODB_MYISAM FAILS
# Wait to ensure that drop temporary tables events
# are present in binary log.
--let $event_sequence= (Anonymous_)?Gtid # !Q(DROP.*TEMPORARY.*) # (Anonymous_)?Gtid # !Q(DROP.*TEMPORARY.*)
--let $limit= 0,4
--let $wait_for_binlog_events= 1
--source include/assert_binlog_events.inc
}
select get_lock("lock1",60);
source include/show_binlog_events.inc;
do release_lock("lock1");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,13 @@ while ($i <= 4)
--echo # Disconnecting.
--disconnect con1

# Verify that the binlog contains the expected events.
--let $event_sequence= (Anonymous_)?Gtid # !Q(DROP.*TEMPORARY.*)
--let $wait_for_binlog_events= 1
--source include/assert_binlog_events.inc
if (`SELECT @@GLOBAL.binlog_format != 'ROW'`)
{
# Verify that the binlog contains the expected events.
--let $event_sequence= (Anonymous_)?Gtid # !Q(DROP.*TEMPORARY.*)
--let $wait_for_binlog_events= 1
--source include/assert_binlog_events.inc
}

# Sync with slave and assert slave has dropped the temp table.
--source include/sync_slave_sql_with_master.inc
Expand All @@ -106,6 +109,11 @@ while ($i <= 4)
# Verify that one gtid was added if gtid_mode=on
--connection master
--let $gtid_step_gtid_mode_agnostic= 1
--let $gtid_step_count= 0
if (`SELECT @@GLOBAL.binlog_format != 'ROW'`)
{
--let $gtid_step_count= 1
}
--source include/gtid_step_assert.inc

--inc $i
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
RESET MASTER;
CREATE TABLE t1(a INT) ENGINE=InnoDB;
CREATE TABLE t2(a INT) ENGINE=MyISAM;
SET @saved_binlog_format= @@SESSION.binlog_format;
SET SESSION binlog_format= 'STATEMENT';
CREATE TEMPORARY TABLE tmp10 (a INT);
SET SESSION binlog_format= @saved_binlog_format;
CREATE TEMPORARY TABLE tmp1 ENGINE=InnoDB SELECT * FROM t1;
CREATE TEMPORARY TABLE tmp2 ENGINE=MyISAM SELECT * FROM t2;
CREATE TEMPORARY TABLE tmp3 ENGINE=MyISAM SELECT * FROM t1;
CREATE TEMPORARY TABLE tmp4 ENGINE=InnoDB SELECT * FROM t2;
CREATE TEMPORARY TABLE tmp5 (a INT) ENGINE=InnoDB;
CREATE TEMPORARY TABLE tmp6 (a INT) ENGINE=MyISAM;
CREATE TEMPORARY TABLE tmp7 LIKE t1;
CREATE TEMPORARY TABLE tmp8 LIKE t2;
include/show_binlog_events.inc
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Query # # use `test`; CREATE TABLE t1(a INT) ENGINE=InnoDB
master-bin.000001 # Query # # use `test`; CREATE TABLE t2(a INT) ENGINE=MyISAM
master-bin.000001 # Query # # use `test`; CREATE TEMPORARY TABLE tmp10 (a INT)
master-bin.000001 # Query # # use `test`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `tmp10`
DROP TABLE t1, t2;
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
RESET MASTER;
CREATE TABLE t1(a INT) ENGINE=InnoDB;
CREATE TABLE t2(a INT) ENGINE=MyISAM;
CREATE TEMPORARY TABLE tmp1 ENGINE=InnoDB SELECT * FROM t1;
CREATE TEMPORARY TABLE tmp2 ENGINE=MyISAM SELECT * FROM t2;
CREATE TEMPORARY TABLE tmp3 ENGINE=MyISAM SELECT * FROM t1;
CREATE TEMPORARY TABLE tmp4 ENGINE=InnoDB SELECT * FROM t2;
CREATE TEMPORARY TABLE tmp5 (a INT) ENGINE=InnoDB;
CREATE TEMPORARY TABLE tmp6 (a INT) ENGINE=MyISAM;
CREATE TEMPORARY TABLE tmp7 LIKE t1;
CREATE TEMPORARY TABLE tmp8 LIKE t2;
SET SESSION binlog_format= 'ROW';
CREATE TEMPORARY TABLE tmp10 (a INT);
include/show_binlog_events.inc
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Query # # use `test`; CREATE TABLE t1(a INT) ENGINE=InnoDB
master-bin.000001 # Query # # use `test`; CREATE TABLE t2(a INT) ENGINE=MyISAM
master-bin.000001 # Query # # use `test`; CREATE TEMPORARY TABLE tmp1 ENGINE=InnoDB SELECT * FROM t1
master-bin.000001 # Query # # use `test`; CREATE TEMPORARY TABLE tmp2 ENGINE=MyISAM SELECT * FROM t2
master-bin.000001 # Query # # use `test`; CREATE TEMPORARY TABLE tmp3 ENGINE=MyISAM SELECT * FROM t1
master-bin.000001 # Query # # use `test`; CREATE TEMPORARY TABLE tmp4 ENGINE=InnoDB SELECT * FROM t2
master-bin.000001 # Query # # use `test`; CREATE TEMPORARY TABLE tmp5 (a INT) ENGINE=InnoDB
master-bin.000001 # Query # # use `test`; CREATE TEMPORARY TABLE tmp6 (a INT) ENGINE=MyISAM
master-bin.000001 # Query # # use `test`; CREATE TEMPORARY TABLE tmp7 LIKE t1
master-bin.000001 # Query # # use `test`; CREATE TEMPORARY TABLE tmp8 LIKE t2
master-bin.000001 # Query # # use `test`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `tmp7`,`tmp5`,`tmp4`,`tmp1`
master-bin.000001 # Query # # use `test`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `tmp8`,`tmp6`,`tmp3`,`tmp2`
DROP TABLE t1, t2;
32 changes: 15 additions & 17 deletions mysql-test/suite/binlog/r/binlog_row_drop_tmp_tbl.result
Original file line number Diff line number Diff line change
Expand Up @@ -34,26 +34,25 @@ master-bin.000001 # Query # # use `drop-temp+table-test`; DROP TEMPORARY TABLE I
master-bin.000001 # Query # # use `drop-temp+table-test`; DROP TEMPORARY TABLE IF EXISTS `tmp2` /* generated by server */
master-bin.000001 # Query # # use `drop-temp+table-test`; DROP TABLE IF EXISTS `t` /* generated by server */
master-bin.000001 # Query # # use `drop-temp+table-test`; DROP TABLE IF EXISTS `tmp2`,`t` /* generated by server */
master-bin.000001 # Query # # use `drop-temp+table-test`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `shortn2`,`table:name`,`shortn1`
DROP DATABASE `drop-temp+table-test`;
RESET MASTER;
CREATE TABLE t1 ( i text );
CREATE TEMPORARY TABLE ttmp1 ( i text );
SET @@session.binlog_format=ROW;
INSERT INTO t1 VALUES ('1');
SELECT @@session.binlog_format;
@@session.binlog_format
ROW
#
# Bug 83003: Using temporary tables on slaves increases GTID sequence number
#
SET @saved_binlog_format= @@SESSION.binlog_format;
SET SESSION binlog_format= STATEMENT;
CREATE TEMPORARY TABLE temp_needs_logging(a INT) ENGINE=InnoDB;
SET SESSION binlog_format= @saved_binlog_format;
CREATE TEMPORARY TABLE temp_trx(a INT) ENGINE=InnoDB;
CREATE TEMPORARY TABLE temp_non_trx(a INT) ENGINE=MyISAM;
CREATE TEMPORARY TABLE temp_needs_logging_in_stmt(a INT) ENGINE=InnoDB;
SET SESSION sql_log_bin= 0;
CREATE TEMPORARY TABLE temp_binlog_disabled(a INT) ENGINE=InnoDB;
SET SESSION sql_log_bin= 1;
include/show_binlog_events.inc
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Query # # use `test`; CREATE TABLE t1 ( i text )
master-bin.000001 # Query # # BEGIN
master-bin.000001 # Table_map # # table_id: # (test.t1)
master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
master-bin.000001 # Query # # COMMIT
master-bin.000001 # Query # # use `test`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `ttmp1`
RESET MASTER;
DROP TABLE t1;
master-bin.000001 # Query # # use `test`; CREATE TEMPORARY TABLE temp_needs_logging(a INT) ENGINE=InnoDB
master-bin.000001 # Query # # use `test`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `temp_needs_logging`
#
# BUG#21638823: ASSERTION FAILED:
# THD->GET_TRANSACTION()->IS_EMPTY(TRANSACTION_CTX::STMT) || THD
Expand All @@ -80,7 +79,6 @@ XA END 'idle_at_disconnect';
# the temp table (row)
include/show_binlog_events.inc
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Query # # use `test`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `temp`
#
# Start XA txn and leave in XA_idle
XA START 'idle_when_drop_temp';
Expand Down
3 changes: 0 additions & 3 deletions mysql-test/suite/binlog/r/binlog_row_mix_innodb_myisam.result
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,6 @@ set autocommit=0;
create table t2 (n int) engine=innodb;
insert into t2 values (3);
include/save_binlog_position.inc
include/assert_binlog_events.inc [(Anonymous_)?Gtid # !Q(DROP.*TEMPORARY.*) # (Anonymous_)?Gtid # !Q(DROP.*TEMPORARY.*)]
select get_lock("lock1",60);
get_lock("lock1",60)
1
Expand Down Expand Up @@ -298,8 +297,6 @@ master-bin.000001 # Table_map # # table_id: # (test.t0)
master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
master-bin.000001 # Query # # COMMIT
master-bin.000001 # Query # # use `test`; create table t2 (n int) engine=innodb
master-bin.000001 # Query # # use `test`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `ti`
master-bin.000001 # Query # # use `test`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `t1`
do release_lock("lock1");
drop table t0,t2;
set autocommit=0;
Expand Down
23 changes: 22 additions & 1 deletion mysql-test/suite/binlog/r/binlog_stm_drop_tmp_tbl.result
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,29 @@ master-bin.000001 # Table_map # # table_id: # (test.t1)
master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
master-bin.000001 # Query # # COMMIT
master-bin.000001 # Query # # use `test`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `ttmp1`
RESET MASTER;
DROP TABLE t1;
RESET MASTER;
#
# Bug 83003: Using temporary tables on slaves increases GTID sequence number
#
SET @saved_binlog_format= @@SESSION.binlog_format;
SET SESSION binlog_format= STATEMENT;
CREATE TEMPORARY TABLE temp_needs_logging(a INT) ENGINE=InnoDB;
SET SESSION binlog_format= @saved_binlog_format;
CREATE TEMPORARY TABLE temp_trx(a INT) ENGINE=InnoDB;
CREATE TEMPORARY TABLE temp_non_trx(a INT) ENGINE=MyISAM;
CREATE TEMPORARY TABLE temp_needs_logging_in_stmt(a INT) ENGINE=InnoDB;
SET SESSION sql_log_bin= 0;
CREATE TEMPORARY TABLE temp_binlog_disabled(a INT) ENGINE=InnoDB;
SET SESSION sql_log_bin= 1;
include/show_binlog_events.inc
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Query # # use `test`; CREATE TEMPORARY TABLE temp_needs_logging(a INT) ENGINE=InnoDB
master-bin.000001 # Query # # use `test`; CREATE TEMPORARY TABLE temp_trx(a INT) ENGINE=InnoDB
master-bin.000001 # Query # # use `test`; CREATE TEMPORARY TABLE temp_non_trx(a INT) ENGINE=MyISAM
master-bin.000001 # Query # # use `test`; CREATE TEMPORARY TABLE temp_needs_logging_in_stmt(a INT) ENGINE=InnoDB
master-bin.000001 # Query # # use `test`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `temp_needs_logging_in_stmt`,`temp_trx`,`temp_needs_logging`
master-bin.000001 # Query # # use `test`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `temp_non_trx`
#
# BUG#21638823: ASSERTION FAILED:
# THD->GET_TRANSACTION()->IS_EMPTY(TRANSACTION_CTX::STMT) || THD
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# ====== Purpose =======
#
# This test verifies that DROP for a temporary table created
# in Row mode is not logged in binlog at session disconnect.
#
# ====== Implementation ======
#
# Create temporary tables in Row mode using different engines,
# also create a temporary table in Statement mode, now when you connect to the session
# after a disconnect print the output of show binlog events.
# This will verify that the DROP for temporary table created in statement
# mode is written to binary log at session disconnect, but for the temporary table
# created in Row mode no DROP statement for temporary table is logged at session
# disconnect.
#
# ====== References =======
#
# Bug#28606948:BACKPORT OF BUG #24670909 TO 5.7.22
#
# The name of this file has row_mix even though we are just testing in row
# format because we want the name of tests to be consistent in 5.7 and 8.0

--source include/have_log_bin.inc
--source include/have_myisam.inc
--source include/have_binlog_format_row.inc

RESET MASTER;

CREATE TABLE t1(a INT) ENGINE=InnoDB;
CREATE TABLE t2(a INT) ENGINE=MyISAM;

--source include/count_sessions.inc

--connect(con1,localhost,root)

SET @saved_binlog_format= @@SESSION.binlog_format;
# A DROP for tmp10 should be binlogged because CREATE TABLE is
# created in Statement mode

SET SESSION binlog_format= 'STATEMENT';
CREATE TEMPORARY TABLE tmp10 (a INT);
SET SESSION binlog_format= @saved_binlog_format;

# No DROP should be logged for any of the statements below
CREATE TEMPORARY TABLE tmp1 ENGINE=InnoDB SELECT * FROM t1;
CREATE TEMPORARY TABLE tmp2 ENGINE=MyISAM SELECT * FROM t2;
CREATE TEMPORARY TABLE tmp3 ENGINE=MyISAM SELECT * FROM t1;
CREATE TEMPORARY TABLE tmp4 ENGINE=InnoDB SELECT * FROM t2;
CREATE TEMPORARY TABLE tmp5 (a INT) ENGINE=InnoDB;
CREATE TEMPORARY TABLE tmp6 (a INT) ENGINE=MyISAM;
CREATE TEMPORARY TABLE tmp7 LIKE t1;
CREATE TEMPORARY TABLE tmp8 LIKE t2;

--disconnect con1
--connection default
--source include/wait_until_count_sessions.inc

--source include/show_binlog_events.inc

DROP TABLE t1, t2;
Loading

0 comments on commit 9827f13

Please sign in to comment.