BUG#46861 Auto-closing of temporary tables broken by replicate-rewrite-db
When a connection is dropped any remaining temporary table is also automatically dropped and the SQL statement of this operation is written to the binary log in order to drop such tables on the slave and keep the slave in sync. Specifically, the current code base creates the following type of statement: DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `db`.`table`; Unfortunately, appending the database to the table name in this manner circumvents the replicate-rewrite-db option (and any options that check the current database). To solve the issue, we started writing the statement to the binary as follows: use `db`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `table`;
This commit is contained in:
parent
3e625f987b
commit
ea06bbd2b0
@ -18,5 +18,5 @@ master-bin.000001 # Query 1 # create database `drop-temp+table-test`
|
||||
master-bin.000001 # Query 1 # use `drop-temp+table-test`; create temporary table shortn1 (a int)
|
||||
master-bin.000001 # Query 1 # use `drop-temp+table-test`; create temporary table `table:name` (a int)
|
||||
master-bin.000001 # Query 1 # use `drop-temp+table-test`; create temporary table shortn2 (a int)
|
||||
master-bin.000001 # Query 1 # use `drop-temp+table-test`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `drop-temp+table-test`.`shortn2`,`drop-temp+table-test`.`table:name`,`drop-temp+table-test`.`shortn1`
|
||||
master-bin.000001 # Query 1 # use `drop-temp+table-test`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `shortn2`,`table:name`,`shortn1`
|
||||
drop database `drop-temp+table-test`;
|
||||
|
@ -260,7 +260,7 @@ master-bin.000001 # Query # # use `test`; create table t0 (n int)
|
||||
master-bin.000001 # Query # # use `test`; insert t0 select * from t1
|
||||
master-bin.000001 # Query # # use `test`; insert into t0 select GET_LOCK("lock1",null)
|
||||
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 `test`.`t1`,`test`.`ti`
|
||||
master-bin.000001 # Query # # use `test`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `t1`,`ti`
|
||||
do release_lock("lock1");
|
||||
drop table t0,t2;
|
||||
reset master;
|
||||
|
@ -5,8 +5,15 @@ reset slave;
|
||||
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
|
||||
start slave;
|
||||
create database if not exists mysqltest;
|
||||
use mysqltest;
|
||||
create temporary table mysqltest.t1 (n int);
|
||||
create temporary table mysqltest.t2 (n int);
|
||||
select get_lock("con_temp",10);
|
||||
get_lock("con_temp",10)
|
||||
1
|
||||
select get_lock("con_temp",10);
|
||||
get_lock("con_temp",10)
|
||||
1
|
||||
show status like 'Slave_open_temp_tables';
|
||||
Variable_name Value
|
||||
Slave_open_temp_tables 0
|
||||
|
@ -90,5 +90,132 @@ a b
|
||||
2 row 2
|
||||
3 row 3
|
||||
0
|
||||
set sql_log_bin= 0;
|
||||
drop database rewrite;
|
||||
set sql_log_bin= 1;
|
||||
set sql_log_bin= 0;
|
||||
drop table t1;
|
||||
set sql_log_bin= 1;
|
||||
|
||||
****
|
||||
**** Bug #46861 Auto-closing of temporary tables broken by replicate-rewrite-db
|
||||
****
|
||||
|
||||
****
|
||||
**** Preparing the environment
|
||||
****
|
||||
SET sql_log_bin= 0;
|
||||
CREATE DATABASE database_master_temp_01;
|
||||
CREATE DATABASE database_master_temp_02;
|
||||
CREATE DATABASE database_master_temp_03;
|
||||
SET sql_log_bin= 1;
|
||||
SET sql_log_bin= 0;
|
||||
CREATE DATABASE database_slave_temp_01;
|
||||
CREATE DATABASE database_slave_temp_02;
|
||||
CREATE DATABASE database_slave_temp_03;
|
||||
SET sql_log_bin= 1;
|
||||
|
||||
****
|
||||
**** Creating temporary tables on different databases with different connections
|
||||
****
|
||||
**** con_temp_01 --> creates
|
||||
**** t_01_01_temp on database_master_temp_01
|
||||
****
|
||||
**** con_temp_02 --> creates
|
||||
**** t_01_01_temp on database_master_temp_01
|
||||
**** t_02_01_temp, t_02_02_temp on database_master_temp_02
|
||||
****
|
||||
**** con_temp_02 --> creates
|
||||
**** t_01_01_temp on database_master_temp_01
|
||||
**** t_02_01_temp, t_02_02_temp on database_master_temp_02
|
||||
**** t_03_01_temp, t_03_02_temp, t_03_03_temp on database_master_temp_03
|
||||
****
|
||||
|
||||
con_temp_01
|
||||
|
||||
USE database_master_temp_01;
|
||||
CREATE TEMPORARY TABLE t_01_01_temp(a int);
|
||||
INSERT INTO t_01_01_temp VALUES(1);
|
||||
|
||||
con_temp_02
|
||||
|
||||
USE database_master_temp_01;
|
||||
CREATE TEMPORARY TABLE t_01_01_temp(a int);
|
||||
INSERT INTO t_01_01_temp VALUES(1);
|
||||
USE database_master_temp_02;
|
||||
CREATE TEMPORARY TABLE t_02_01_temp(a int);
|
||||
INSERT INTO t_02_01_temp VALUES(1);
|
||||
CREATE TEMPORARY TABLE t_02_02_temp(a int);
|
||||
INSERT INTO t_02_02_temp VALUES(1);
|
||||
|
||||
con_temp_03
|
||||
|
||||
USE database_master_temp_01;
|
||||
CREATE TEMPORARY TABLE t_01_01_temp(a int);
|
||||
INSERT INTO t_01_01_temp VALUES(1);
|
||||
USE database_master_temp_02;
|
||||
CREATE TEMPORARY TABLE t_02_01_temp(a int);
|
||||
INSERT INTO t_02_01_temp VALUES(1);
|
||||
CREATE TEMPORARY TABLE t_02_02_temp(a int);
|
||||
INSERT INTO t_02_02_temp VALUES(1);
|
||||
USE database_master_temp_03;
|
||||
CREATE TEMPORARY TABLE t_03_01_temp(a int);
|
||||
INSERT INTO t_03_01_temp VALUES(1);
|
||||
CREATE TEMPORARY TABLE t_03_02_temp(a int);
|
||||
INSERT INTO t_03_02_temp VALUES(1);
|
||||
CREATE TEMPORARY TABLE t_03_03_temp(a int);
|
||||
INSERT INTO t_03_03_temp VALUES(1);
|
||||
|
||||
**** Dropping the connections
|
||||
**** We want to SHOW BINLOG EVENTS, to know what was logged. But there is no
|
||||
**** guarantee that logging of the terminated con1 has been done yet.a To be
|
||||
**** sure that logging has been done, we use a user lock.
|
||||
|
||||
show status like 'Slave_open_temp_tables';
|
||||
Variable_name Value
|
||||
Slave_open_temp_tables 10
|
||||
select get_lock("con_01",10);
|
||||
get_lock("con_01",10)
|
||||
1
|
||||
select get_lock("con_01",10);
|
||||
get_lock("con_01",10)
|
||||
1
|
||||
select get_lock("con_02",10);
|
||||
get_lock("con_02",10)
|
||||
1
|
||||
select get_lock("con_02",10);
|
||||
get_lock("con_02",10)
|
||||
1
|
||||
select get_lock("con_03",10);
|
||||
get_lock("con_03",10)
|
||||
1
|
||||
select get_lock("con_03",10);
|
||||
get_lock("con_03",10)
|
||||
1
|
||||
|
||||
**** Checking the binary log and temporary tables
|
||||
|
||||
show status like 'Slave_open_temp_tables';
|
||||
Variable_name Value
|
||||
Slave_open_temp_tables 0
|
||||
show binlog events from <binlog_start>;
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
master-bin.000001 # Query # # use `database_master_temp_01`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `t_01_01_temp`
|
||||
master-bin.000001 # Query # # use `database_master_temp_02`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `t_02_02_temp`,`t_02_01_temp`
|
||||
master-bin.000001 # Query # # use `database_master_temp_01`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `t_01_01_temp`
|
||||
master-bin.000001 # Query # # use `database_master_temp_03`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `t_03_03_temp`,`t_03_02_temp`,`t_03_01_temp`
|
||||
master-bin.000001 # Query # # use `database_master_temp_02`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `t_02_02_temp`,`t_02_01_temp`
|
||||
master-bin.000001 # Query # # use `database_master_temp_01`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `t_01_01_temp`
|
||||
****
|
||||
**** Cleaning up the test case
|
||||
****
|
||||
SET sql_log_bin= 0;
|
||||
DROP DATABASE database_master_temp_01;
|
||||
DROP DATABASE database_master_temp_02;
|
||||
DROP DATABASE database_master_temp_03;
|
||||
SET sql_log_bin= 1;
|
||||
SET sql_log_bin= 0;
|
||||
DROP DATABASE database_slave_temp_01;
|
||||
DROP DATABASE database_slave_temp_02;
|
||||
DROP DATABASE database_slave_temp_03;
|
||||
SET sql_log_bin= 1;
|
||||
|
@ -3,15 +3,22 @@ source include/master-slave.inc;
|
||||
create database if not exists mysqltest;
|
||||
--enable_warnings
|
||||
|
||||
connect (con_temp,127.0.0.1,root,,test,$MASTER_MYPORT,);
|
||||
|
||||
connection con_temp;
|
||||
use mysqltest;
|
||||
create temporary table mysqltest.t1 (n int);
|
||||
create temporary table mysqltest.t2 (n int);
|
||||
sync_slave_with_master;
|
||||
select get_lock("con_temp",10);
|
||||
|
||||
connection master;
|
||||
disconnect master;
|
||||
disconnect con_temp;
|
||||
select get_lock("con_temp",10);
|
||||
sync_slave_with_master;
|
||||
|
||||
connection slave;
|
||||
--real_sleep 3 # time for DROP to be written
|
||||
show status like 'Slave_open_temp_tables';
|
||||
connection default;
|
||||
connection master;
|
||||
drop database mysqltest;
|
||||
|
||||
# End of 4.1 tests
|
||||
|
@ -1 +1 @@
|
||||
"--replicate-rewrite-db=test->rewrite" "--replicate-rewrite-db=mysqltest1->test"
|
||||
"--replicate-rewrite-db=test->rewrite" "--replicate-rewrite-db=mysqltest1->test" "--replicate-rewrite-db=database_master_temp_01->database_slave_temp_01" "--replicate-rewrite-db=database_master_temp_02->database_slave_temp_02" "--replicate-rewrite-db=database_master_temp_03->database_slave_temp_03"
|
||||
|
@ -73,9 +73,164 @@ connection slave;
|
||||
# The empty line last comes from the end line field in the file
|
||||
select * from rewrite.t1;
|
||||
|
||||
set sql_log_bin= 0;
|
||||
drop database rewrite;
|
||||
set sql_log_bin= 1;
|
||||
|
||||
connection master;
|
||||
set sql_log_bin= 0;
|
||||
drop table t1;
|
||||
set sql_log_bin= 1;
|
||||
|
||||
# End of 4.1 tests
|
||||
|
||||
--echo
|
||||
--echo ****
|
||||
--echo **** Bug #46861 Auto-closing of temporary tables broken by replicate-rewrite-db
|
||||
--echo ****
|
||||
--echo
|
||||
|
||||
--echo ****
|
||||
--echo **** Preparing the environment
|
||||
--echo ****
|
||||
connection master;
|
||||
|
||||
connect (con_temp_03,127.0.0.1,root,,test,$MASTER_MYPORT,);
|
||||
connect (con_temp_02,127.0.0.1,root,,test,$MASTER_MYPORT,);
|
||||
connect (con_temp_01,127.0.0.1,root,,test,$MASTER_MYPORT,);
|
||||
|
||||
connection master;
|
||||
SET sql_log_bin= 0;
|
||||
CREATE DATABASE database_master_temp_01;
|
||||
CREATE DATABASE database_master_temp_02;
|
||||
CREATE DATABASE database_master_temp_03;
|
||||
SET sql_log_bin= 1;
|
||||
|
||||
connection slave;
|
||||
SET sql_log_bin= 0;
|
||||
CREATE DATABASE database_slave_temp_01;
|
||||
CREATE DATABASE database_slave_temp_02;
|
||||
CREATE DATABASE database_slave_temp_03;
|
||||
SET sql_log_bin= 1;
|
||||
|
||||
--echo
|
||||
--echo ****
|
||||
--echo **** Creating temporary tables on different databases with different connections
|
||||
--echo ****
|
||||
--echo **** con_temp_01 --> creates
|
||||
--echo **** t_01_01_temp on database_master_temp_01
|
||||
--echo ****
|
||||
--echo **** con_temp_02 --> creates
|
||||
--echo **** t_01_01_temp on database_master_temp_01
|
||||
--echo **** t_02_01_temp, t_02_02_temp on database_master_temp_02
|
||||
--echo ****
|
||||
--echo **** con_temp_02 --> creates
|
||||
--echo **** t_01_01_temp on database_master_temp_01
|
||||
--echo **** t_02_01_temp, t_02_02_temp on database_master_temp_02
|
||||
--echo **** t_03_01_temp, t_03_02_temp, t_03_03_temp on database_master_temp_03
|
||||
--echo ****
|
||||
|
||||
--echo
|
||||
--echo con_temp_01
|
||||
--echo
|
||||
connection con_temp_01;
|
||||
USE database_master_temp_01;
|
||||
CREATE TEMPORARY TABLE t_01_01_temp(a int);
|
||||
INSERT INTO t_01_01_temp VALUES(1);
|
||||
|
||||
--echo
|
||||
--echo con_temp_02
|
||||
--echo
|
||||
connection con_temp_02;
|
||||
USE database_master_temp_01;
|
||||
CREATE TEMPORARY TABLE t_01_01_temp(a int);
|
||||
INSERT INTO t_01_01_temp VALUES(1);
|
||||
USE database_master_temp_02;
|
||||
CREATE TEMPORARY TABLE t_02_01_temp(a int);
|
||||
INSERT INTO t_02_01_temp VALUES(1);
|
||||
CREATE TEMPORARY TABLE t_02_02_temp(a int);
|
||||
INSERT INTO t_02_02_temp VALUES(1);
|
||||
|
||||
--echo
|
||||
--echo con_temp_03
|
||||
--echo
|
||||
connection con_temp_03;
|
||||
USE database_master_temp_01;
|
||||
CREATE TEMPORARY TABLE t_01_01_temp(a int);
|
||||
INSERT INTO t_01_01_temp VALUES(1);
|
||||
USE database_master_temp_02;
|
||||
CREATE TEMPORARY TABLE t_02_01_temp(a int);
|
||||
INSERT INTO t_02_01_temp VALUES(1);
|
||||
CREATE TEMPORARY TABLE t_02_02_temp(a int);
|
||||
INSERT INTO t_02_02_temp VALUES(1);
|
||||
USE database_master_temp_03;
|
||||
CREATE TEMPORARY TABLE t_03_01_temp(a int);
|
||||
INSERT INTO t_03_01_temp VALUES(1);
|
||||
CREATE TEMPORARY TABLE t_03_02_temp(a int);
|
||||
INSERT INTO t_03_02_temp VALUES(1);
|
||||
CREATE TEMPORARY TABLE t_03_03_temp(a int);
|
||||
INSERT INTO t_03_03_temp VALUES(1);
|
||||
|
||||
--echo
|
||||
--echo **** Dropping the connections
|
||||
--echo **** We want to SHOW BINLOG EVENTS, to know what was logged. But there is no
|
||||
--echo **** guarantee that logging of the terminated con1 has been done yet.a To be
|
||||
--echo **** sure that logging has been done, we use a user lock.
|
||||
--echo
|
||||
connection master;
|
||||
sync_slave_with_master;
|
||||
connection slave;
|
||||
show status like 'Slave_open_temp_tables';
|
||||
|
||||
connection master;
|
||||
let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1);
|
||||
connection con_temp_01;
|
||||
select get_lock("con_01",10);
|
||||
connection master;
|
||||
disconnect con_temp_01;
|
||||
select get_lock("con_01",10);
|
||||
|
||||
connection con_temp_02;
|
||||
select get_lock("con_02",10);
|
||||
connection master;
|
||||
disconnect con_temp_02;
|
||||
select get_lock("con_02",10);
|
||||
|
||||
connection con_temp_03;
|
||||
select get_lock("con_03",10);
|
||||
connection master;
|
||||
disconnect con_temp_03;
|
||||
select get_lock("con_03",10);
|
||||
|
||||
--echo
|
||||
--echo **** Checking the binary log and temporary tables
|
||||
--echo
|
||||
connection master;
|
||||
sync_slave_with_master;
|
||||
connection slave;
|
||||
show status like 'Slave_open_temp_tables';
|
||||
|
||||
connection master;
|
||||
--source include/show_binlog_events.inc
|
||||
|
||||
--echo ****
|
||||
--echo **** Cleaning up the test case
|
||||
--echo ****
|
||||
connection master;
|
||||
SET sql_log_bin= 0;
|
||||
DROP DATABASE database_master_temp_01;
|
||||
DROP DATABASE database_master_temp_02;
|
||||
DROP DATABASE database_master_temp_03;
|
||||
SET sql_log_bin= 1;
|
||||
|
||||
connection slave;
|
||||
SET sql_log_bin= 0;
|
||||
DROP DATABASE database_slave_temp_01;
|
||||
DROP DATABASE database_slave_temp_02;
|
||||
DROP DATABASE database_slave_temp_03;
|
||||
SET sql_log_bin= 1;
|
||||
|
||||
connection master;
|
||||
sync_slave_with_master;
|
||||
|
||||
# end of 5.0 tests
|
||||
|
@ -769,19 +769,23 @@ void close_temporary_tables(THD *thd)
|
||||
{
|
||||
/* Set pseudo_thread_id to be that of the processed table */
|
||||
thd->variables.pseudo_thread_id= tmpkeyval(thd, table);
|
||||
/* Loop forward through all tables within the sublist of
|
||||
common pseudo_thread_id to create single DROP query */
|
||||
String db;
|
||||
db.append(table->s->db);
|
||||
/* Loop forward through all tables that belong to a common database
|
||||
within the sublist of common pseudo_thread_id to create single
|
||||
DROP query
|
||||
*/
|
||||
for (s_query.length(stub_len);
|
||||
table && is_user_table(table) &&
|
||||
tmpkeyval(thd, table) == thd->variables.pseudo_thread_id;
|
||||
tmpkeyval(thd, table) == thd->variables.pseudo_thread_id &&
|
||||
strlen(table->s->db) == db.length() &&
|
||||
strcmp(table->s->db, db.ptr()) == 0;
|
||||
table= next)
|
||||
{
|
||||
/*
|
||||
We are going to add 4 ` around the db/table names and possible more
|
||||
due to special characters in the names
|
||||
We are going to add ` around the table names and possible more
|
||||
due to special characters
|
||||
*/
|
||||
append_identifier(thd, &s_query, table->s->db, strlen(table->s->db));
|
||||
s_query.q_append('.');
|
||||
append_identifier(thd, &s_query, table->s->table_name,
|
||||
strlen(table->s->table_name));
|
||||
s_query.q_append(',');
|
||||
@ -794,6 +798,7 @@ void close_temporary_tables(THD *thd)
|
||||
Query_log_event qinfo(thd, s_query.ptr(),
|
||||
s_query.length() - 1 /* to remove trailing ',' */,
|
||||
0, FALSE);
|
||||
qinfo.db= db.ptr();
|
||||
thd->variables.character_set_client= cs_save;
|
||||
/*
|
||||
Imagine the thread had created a temp table, then was doing a SELECT, and
|
||||
|
Loading…
x
Reference in New Issue
Block a user