Commit 913d1f19 authored by Michael Widenius's avatar Michael Widenius

MDEV-5854 Interrupted CREATE OR REPLACE is written into binlog, and in a wrong format


mysql-test/r/create_or_replace2.result:
  Added test case
mysql-test/t/create_or_replace.test:
  Fixed comment
mysql-test/t/create_or_replace2.test:
  Added test case
sql/sql_base.cc:
  Safety fix:
  Don't let threads with query_id=0 free temporary tables as this may free temporary tables not in use.
  This is mostly the case for the slave io threads, as most other threads has thd->query_id != 0.
sql/sql_table.cc:
  Added comment.
  Ignore kill when opening temporary table for CREATE ... LIKE.
  This fixed the original isue
parent e7704bfd
include/master-slave.inc
[connection master]
drop table if exists t1;
SET @old_debug= @@session.debug;
CREATE TABLE t1 (i INT, KEY(i)) ENGINE=InnoDB;
CREATE OR REPLACE TEMPORARY TABLE tmp (a int, b int, key(a)) engine=myisam;
set debug_dbug='+d,send_kill_after_delete';
CREATE OR REPLACE TABLE t1 LIKE tmp;
set debug_dbug=@old_debug;
SHOW TABLES;
Tables_in_test
t1
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) DEFAULT NULL,
`b` int(11) DEFAULT NULL,
KEY `a` (`a`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SHOW TABLES;
Tables_in_test
t1
drop temporary table if exists tmp;
drop table t1;
include/rpl_end.inc
# #
# Check CREATE OR REPLACE ALTER TABLE # Check CREATE OR REPLACE TABLE
# #
--source include/have_innodb.inc --source include/have_innodb.inc
......
#
# Check CREATE OR REPLACE TABLE for test that requires DEBUG
#
--source include/have_debug.inc
--source include/master-slave.inc
--source include/have_binlog_format_row.inc
--source include/have_xtradb.inc
--disable_warnings
drop table if exists t1;
--enable_warnings
SET @old_debug= @@session.debug;
#
# MDEV-5854
# Interrupted CREATE OR REPLACE is written into binlog, and in a wrong format
#
CREATE TABLE t1 (i INT, KEY(i)) ENGINE=InnoDB;
CREATE OR REPLACE TEMPORARY TABLE tmp (a int, b int, key(a)) engine=myisam;
set debug_dbug='+d,send_kill_after_delete';
CREATE OR REPLACE TABLE t1 LIKE tmp;
set debug_dbug=@old_debug;
SHOW TABLES;
show create table t1;
--sync_slave_with_master
SHOW TABLES;
--connection master
--disable_warnings
drop temporary table if exists tmp;
--enable_warnings
drop table t1;
--source include/rpl_end.inc
...@@ -656,6 +656,12 @@ static void mark_temp_tables_as_free_for_reuse(THD *thd) ...@@ -656,6 +656,12 @@ static void mark_temp_tables_as_free_for_reuse(THD *thd)
{ {
DBUG_ENTER("mark_temp_tables_as_free_for_reuse"); DBUG_ENTER("mark_temp_tables_as_free_for_reuse");
if (thd->query_id == 0)
{
/* Thread has not executed any statement and has not used any tmp tables */
DBUG_VOID_RETURN;
}
thd->lock_temporary_tables(); thd->lock_temporary_tables();
for (TABLE *table= thd->temporary_tables ; table ; table= table->next) for (TABLE *table= thd->temporary_tables ; table ; table= table->next)
{ {
......
...@@ -2560,6 +2560,18 @@ err: ...@@ -2560,6 +2560,18 @@ err:
error= 1; error= 1;
} }
/*
We are always logging drop of temporary tables.
The reason is to handle the following case:
- Use statement based replication
- CREATE TEMPORARY TABLE foo (logged)
- set row based replication
- DROP TEMPORAY TABLE foo (needs to be logged)
This should be fixed so that we remember if creation of the
temporary table was logged and only log it if the creation was
logged.
*/
if (non_trans_tmp_table_deleted || if (non_trans_tmp_table_deleted ||
trans_tmp_table_deleted || non_tmp_table_deleted) trans_tmp_table_deleted || non_tmp_table_deleted)
{ {
...@@ -4628,6 +4640,7 @@ int create_table_impl(THD *thd, ...@@ -4628,6 +4640,7 @@ int create_table_impl(THD *thd,
thd->variables.option_bits|= OPTION_KEEP_LOG; thd->variables.option_bits|= OPTION_KEEP_LOG;
thd->log_current_statement= 1; thd->log_current_statement= 1;
create_info->table_was_deleted= 1; create_info->table_was_deleted= 1;
DBUG_EXECUTE_IF("send_kill_after_delete", thd->killed= KILL_QUERY; );
/* /*
The test of query_tables is to ensure we have any tables in the The test of query_tables is to ensure we have any tables in the
...@@ -4769,6 +4782,7 @@ int create_table_impl(THD *thd, ...@@ -4769,6 +4782,7 @@ int create_table_impl(THD *thd,
err: err:
THD_STAGE_INFO(thd, stage_after_create); THD_STAGE_INFO(thd, stage_after_create);
delete file; delete file;
DBUG_PRINT("exit", ("return: %d", error));
DBUG_RETURN(error); DBUG_RETURN(error);
warn: warn:
...@@ -5262,7 +5276,8 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, ...@@ -5262,7 +5276,8 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
char buf[2048]; char buf[2048];
String query(buf, sizeof(buf), system_charset_info); String query(buf, sizeof(buf), system_charset_info);
query.length(0); // Have to zero it since constructor doesn't query.length(0); // Have to zero it since constructor doesn't
Open_table_context ot_ctx(thd, MYSQL_OPEN_REOPEN); Open_table_context ot_ctx(thd, MYSQL_OPEN_REOPEN |
MYSQL_OPEN_IGNORE_KILLED);
bool new_table= FALSE; // Whether newly created table is open. bool new_table= FALSE; // Whether newly created table is open.
if (create_res != 0) if (create_res != 0)
...@@ -5271,6 +5286,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, ...@@ -5271,6 +5286,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
Table or view with same name already existed and we where using Table or view with same name already existed and we where using
IF EXISTS. Continue without logging anything. IF EXISTS. Continue without logging anything.
*/ */
do_logging= 0;
goto err; goto err;
} }
if (!table->table) if (!table->table)
...@@ -5316,6 +5332,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, ...@@ -5316,6 +5332,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
if (write_bin_log(thd, TRUE, query.ptr(), query.length())) if (write_bin_log(thd, TRUE, query.ptr(), query.length()))
{ {
res= 1; res= 1;
do_logging= 0;
goto err; goto err;
} }
......
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