Bug #72666 DROP TEMPORARY TABLE with myisam causes implicit commit with unsafe sql
Submitted: 16 May 2014 8:43 Modified: 20 May 2014 12:39
Reporter: Peiran Song Email Updates:
Status: Verified Impact on me:
None 
Category:MySQL Server: DDL Severity:S3 (Non-critical)
Version:5.5.37, 5.5.38 OS:Linux
Assigned to: CPU Architecture:Any
Tags: drop temporary table, mixed binlog format

[16 May 2014 8:43] Peiran Song
Description:
Per documentation, DROP TEMPORARY TABLE should not result in commit.

http://dev.mysql.com/doc/refman/5.5/en/drop-table.html

"DROP TABLE automatically commits the current active transaction, unless you use the TEMPORARY keyword."

With MIXED binlog format, we found that when the temporary table is created as a MyISAM table, and when the transaction has some non-deterministic statement, the DROP TEMPORARY TABLE statement would sometimes cause a commit. 

This is not a problem with SBR. Not a problem with InnoDB. 

This is not reproduced on the latest 5.6.17.

How to repeat:
This unexpected behavior caught attention when it resulted in replication failure. The master starts a transaction, which runs several loops on "drop temporary table...; create temporary table...; DML...". The early commit caused the "drop temporary table" statements to be logged into binlog first, leaving some "create table" statements logged together and caused replication failure.  

my.cnf
----------
binlog-format=MIXED

Create a SQL file:
-----------------

use test;

create table company (id int AUTO_INCREMENT, name varchar(20), PRIMARY KEY (id)) ENGINE=InnoDB

insert into company(name) values ("a"), ("b");

set autocommit = 0;

drop temporary table if exists tmp_test;
create temporary table tmp_test (id int, name varchar(20)) engine = myisam;
insert into tmp_test (name) select name from company where id = 2;

drop temporary table if exists tmp_test;
create temporary table tmp_test (id int, name varchar(20)) engine = myisam;
insert into tmp_test (name) select name from company limit 1;

drop temporary table if exists tmp_test;
create temporary table tmp_test (id int, name varchar(20)) engine = myisam;
insert into tmp_test (name) select name from company limit 1;

set autocommit = 1;

Run the SQL and examine binlog output:
-------------------------------------
BEGIN
DROP TEMPORARY TABLE IF EXISTS `test`.`tmp_test` /* generated by server */
COMMIT
BEGIN
DROP TEMPORARY TABLE IF EXISTS `test`.`tmp_test` /* generated by server */
create temporary table tmp_test (id int, name varchar(20)) engine = myisam
insert into tmp_test (name) select name from company where id = 2
DROP TEMPORARY TABLE IF EXISTS `test`.`tmp_test` /* generated by server */
create temporary table tmp_test (id int, name varchar(20)) engine = myisam
create temporary table tmp_test (id int, name varchar(20)) engine = myisam
COMMIT

Suggested fix:
As stated in the documentation, DROP TEMPORARY TABLE should not cause a commit.
[19 May 2014 4:25] Peiran Song
Also reproduced with MEMORY storage engine, the same setup, just replace mysiam to memory.
[20 May 2014 12:39] MySQL Verification Team
Hello Peiran,

Thank you for the bug report and test case.
Verified as described.

Thanks,
Umesh
[22 May 2014 7:39] MySQL Verification Team
I didn't see this issue with 5.6.17/19..
Interestingly, with 5.5.38 - able to reproduce just 1-2 times in 10+ attempts.