summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <guilhem@mysql.com>2003-08-22 15:42:22 +0200
committerunknown <guilhem@mysql.com>2003-08-22 15:42:22 +0200
commite3563c7911580a34d423a154aaa0f9c99d01f45b (patch)
tree57dc420cb6593f87be0556b23e070c7008ccf987
parente3ceec7136aeac433a074dd923cc790af13b9546 (diff)
parentfdfb10f2fb9855d92be2ad9133a950a94606030f (diff)
downloadmariadb-git-e3563c7911580a34d423a154aaa0f9c99d01f45b.tar.gz
Merge gbichot@bk-internal.mysql.com:/home/bk/mysql-4.0
into mysql.com:/home/mysql_src/mysql-4.0
-rw-r--r--client/mysqldump.c5
-rw-r--r--mysql-test/r/mix_innodb_myisam_binlog.result180
-rw-r--r--mysql-test/r/rpl_loaddata.result6
-rw-r--r--mysql-test/t/mix_innodb_myisam_binlog.test175
-rw-r--r--mysql-test/t/rpl_loaddata.test14
-rw-r--r--sql/handler.cc69
-rw-r--r--sql/log.cc31
-rw-r--r--sql/log_event.cc2
-rw-r--r--sql/sql_class.h2
-rw-r--r--sql/sql_insert.cc4
-rw-r--r--sql/sql_parse.cc13
11 files changed, 471 insertions, 30 deletions
diff --git a/client/mysqldump.c b/client/mysqldump.c
index 459cb9fda31..f1425faf0ed 100644
--- a/client/mysqldump.c
+++ b/client/mysqldump.c
@@ -1459,9 +1459,8 @@ int main(int argc, char **argv)
fprintf(md_result_file,
"\n--\n-- Position to start replication from\n--\n\n");
fprintf(md_result_file,
- "CHANGE MASTER TO MASTER_LOG_FILE='%s' ;\n", row[0]);
- fprintf(md_result_file, "CHANGE MASTER TO MASTER_LOG_POS=%s ;\n",
- row[1]);
+ "CHANGE MASTER TO MASTER_LOG_FILE='%s', \
+MASTER_LOG_POS=%s ;\n",row[0],row[1]);
}
mysql_free_result(master);
}
diff --git a/mysql-test/r/mix_innodb_myisam_binlog.result b/mysql-test/r/mix_innodb_myisam_binlog.result
new file mode 100644
index 00000000000..8a3415a81d0
--- /dev/null
+++ b/mysql-test/r/mix_innodb_myisam_binlog.result
@@ -0,0 +1,180 @@
+drop table if exists ti, tm;
+create table ti (a int) type=innodb;
+create table tm (a int) type=myisam;
+reset master;
+begin;
+insert into ti values(1);
+insert into tm select * from ti;
+commit;
+show binlog events from 79;
+Log_name Pos Event_type Server_id Orig_log_pos Info
+master-bin.001 79 Query 1 79 use test; BEGIN
+master-bin.001 119 Query 1 79 use test; insert into ti values(1)
+master-bin.001 178 Query 1 79 use test; insert into tm select * from ti
+master-bin.001 244 Query 1 244 use test; COMMIT
+delete from ti;
+delete from tm;
+reset master;
+begin;
+insert into ti values(2);
+insert into tm select * from ti;
+rollback;
+Warning: Some non-transactional changed tables couldn't be rolled back
+show binlog events from 79;
+Log_name Pos Event_type Server_id Orig_log_pos Info
+master-bin.001 79 Query 1 79 use test; BEGIN
+master-bin.001 119 Query 1 79 use test; insert into ti values(2)
+master-bin.001 178 Query 1 79 use test; insert into tm select * from ti
+master-bin.001 244 Query 1 244 use test; ROLLBACK
+delete from ti;
+delete from tm;
+reset master;
+begin;
+insert into ti values(3);
+savepoint my_savepoint;
+insert into ti values(4);
+insert into tm select * from ti;
+rollback to savepoint my_savepoint;
+Warning: Some non-transactional changed tables couldn't be rolled back
+commit;
+show binlog events from 79;
+Log_name Pos Event_type Server_id Orig_log_pos Info
+master-bin.001 79 Query 1 79 use test; BEGIN
+master-bin.001 119 Query 1 79 use test; insert into ti values(3)
+master-bin.001 178 Query 1 79 use test; savepoint my_savepoint
+master-bin.001 235 Query 1 79 use test; insert into ti values(4)
+master-bin.001 294 Query 1 79 use test; insert into tm select * from ti
+master-bin.001 360 Query 1 79 use test; rollback to savepoint my_savepoint
+master-bin.001 429 Query 1 429 use test; COMMIT
+delete from ti;
+delete from tm;
+reset master;
+begin;
+insert into ti values(5);
+savepoint my_savepoint;
+insert into ti values(6);
+insert into tm select * from ti;
+rollback to savepoint my_savepoint;
+Warning: Some non-transactional changed tables couldn't be rolled back
+insert into ti values(7);
+commit;
+select a from ti order by a;
+a
+5
+7
+show binlog events from 79;
+Log_name Pos Event_type Server_id Orig_log_pos Info
+master-bin.001 79 Query 1 79 use test; BEGIN
+master-bin.001 119 Query 1 79 use test; insert into ti values(5)
+master-bin.001 178 Query 1 79 use test; savepoint my_savepoint
+master-bin.001 235 Query 1 79 use test; insert into ti values(6)
+master-bin.001 294 Query 1 79 use test; insert into tm select * from ti
+master-bin.001 360 Query 1 79 use test; rollback to savepoint my_savepoint
+master-bin.001 429 Query 1 79 use test; insert into ti values(7)
+master-bin.001 488 Query 1 488 use test; COMMIT
+delete from ti;
+delete from tm;
+reset master;
+select get_lock("a",10);
+get_lock("a",10)
+1
+begin;
+insert into ti values(8);
+insert into tm select * from ti;
+select get_lock("a",10);
+get_lock("a",10)
+1
+show binlog events from 79;
+Log_name Pos Event_type Server_id Orig_log_pos Info
+master-bin.001 79 Query 1 79 use test; BEGIN
+master-bin.001 119 Query 1 79 use test; insert into ti values(8)
+master-bin.001 178 Query 1 79 use test; insert into tm select * from ti
+master-bin.001 244 Query 1 244 use test; ROLLBACK
+delete from ti;
+delete from tm;
+reset master;
+insert into ti values(9);
+insert into tm select * from ti;
+show binlog events from 79;
+Log_name Pos Event_type Server_id Orig_log_pos Info
+master-bin.001 79 Query 1 79 use test; insert into ti values(9)
+master-bin.001 138 Query 1 138 use test; insert into tm select * from ti
+delete from ti;
+delete from tm;
+reset master;
+insert into ti values(10);
+begin;
+insert into tm select * from ti;
+show binlog events from 79;
+Log_name Pos Event_type Server_id Orig_log_pos Info
+master-bin.001 79 Query 1 79 use test; insert into ti values(10)
+master-bin.001 139 Query 1 139 use test; insert into tm select * from ti
+insert into ti values(11);
+commit;
+show binlog events from 79;
+Log_name Pos Event_type Server_id Orig_log_pos Info
+master-bin.001 79 Query 1 79 use test; insert into ti values(10)
+master-bin.001 139 Query 1 139 use test; insert into tm select * from ti
+master-bin.001 205 Query 1 205 use test; BEGIN
+master-bin.001 245 Query 1 205 use test; insert into ti values(11)
+master-bin.001 305 Query 1 305 use test; COMMIT
+alter table tm type=INNODB;
+delete from ti;
+delete from tm;
+reset master;
+begin;
+insert into ti values(12);
+insert into tm select * from ti;
+commit;
+show binlog events from 79;
+Log_name Pos Event_type Server_id Orig_log_pos Info
+master-bin.001 79 Query 1 79 use test; BEGIN
+master-bin.001 119 Query 1 79 use test; insert into ti values(12)
+master-bin.001 179 Query 1 79 use test; insert into tm select * from ti
+master-bin.001 245 Query 1 245 use test; COMMIT
+delete from ti;
+delete from tm;
+reset master;
+begin;
+insert into ti values(13);
+insert into tm select * from ti;
+rollback;
+show binlog events from 79;
+Log_name Pos Event_type Server_id Orig_log_pos Info
+delete from ti;
+delete from tm;
+reset master;
+begin;
+insert into ti values(14);
+savepoint my_savepoint;
+insert into ti values(15);
+insert into tm select * from ti;
+rollback to savepoint my_savepoint;
+commit;
+show binlog events from 79;
+Log_name Pos Event_type Server_id Orig_log_pos Info
+master-bin.001 79 Query 1 79 use test; BEGIN
+master-bin.001 119 Query 1 79 use test; insert into ti values(14)
+master-bin.001 179 Query 1 179 use test; COMMIT
+delete from ti;
+delete from tm;
+reset master;
+begin;
+insert into ti values(16);
+savepoint my_savepoint;
+insert into ti values(17);
+insert into tm select * from ti;
+rollback to savepoint my_savepoint;
+insert into ti values(18);
+commit;
+select a from ti order by a;
+a
+16
+18
+show binlog events from 79;
+Log_name Pos Event_type Server_id Orig_log_pos Info
+master-bin.001 79 Query 1 79 use test; BEGIN
+master-bin.001 119 Query 1 79 use test; insert into ti values(16)
+master-bin.001 179 Query 1 79 use test; insert into ti values(18)
+master-bin.001 239 Query 1 239 use test; COMMIT
+drop table ti,tm;
diff --git a/mysql-test/r/rpl_loaddata.result b/mysql-test/r/rpl_loaddata.result
index e93f8487c32..0302381c119 100644
--- a/mysql-test/r/rpl_loaddata.result
+++ b/mysql-test/r/rpl_loaddata.result
@@ -20,9 +20,9 @@ day id category name
2003-02-22 2461 b a a a @ %  ' " a
2003-03-22 2161 c asdf
2003-04-22 2416 a bbbbb
-show binlog events from 898;
-Log_name Pos Event_type Server_id Orig_log_pos Info
-slave-bin.001 898 Query 1 898 use test; insert into t3 select * from t2
+show master status;
+File Position Binlog_do_db Binlog_ignore_db
+slave-bin.001 964
drop table t1;
drop table t2;
drop table t3;
diff --git a/mysql-test/t/mix_innodb_myisam_binlog.test b/mysql-test/t/mix_innodb_myisam_binlog.test
new file mode 100644
index 00000000000..240aaefb349
--- /dev/null
+++ b/mysql-test/t/mix_innodb_myisam_binlog.test
@@ -0,0 +1,175 @@
+# Check that binlog is ok when a transaction mixes updates to InnoDB and
+# MyISAM. It would be nice to make this a replication test, but in 4.0 the slave
+# is always with --skip-innodb in the testsuite. I (Guilhem) however did some
+# tests manually on a slave; tables are replicated fine and Exec_master_log_pos
+# advances as expected.
+
+-- source include/have_innodb.inc
+
+connect (con1,localhost,root,,);
+connect (con2,localhost,root,,);
+
+connection con1;
+
+drop table if exists ti, tm;
+create table ti (a int) type=innodb;
+create table tm (a int) type=myisam;
+
+reset master;
+
+begin;
+insert into ti values(1);
+insert into tm select * from ti;
+commit;
+
+show binlog events from 79;
+
+delete from ti;
+delete from tm;
+reset master;
+
+begin;
+insert into ti values(2);
+insert into tm select * from ti;
+# should say some changes to non-transactional tables couldn't be rolled back
+--error 1196
+rollback;
+
+show binlog events from 79;
+
+delete from ti;
+delete from tm;
+reset master;
+
+begin;
+insert into ti values(3);
+savepoint my_savepoint;
+insert into ti values(4);
+insert into tm select * from ti;
+--error 1196
+rollback to savepoint my_savepoint;
+commit;
+
+show binlog events from 79;
+
+delete from ti;
+delete from tm;
+reset master;
+
+begin;
+insert into ti values(5);
+savepoint my_savepoint;
+insert into ti values(6);
+insert into tm select * from ti;
+--error 1196
+rollback to savepoint my_savepoint;
+insert into ti values(7);
+commit;
+select a from ti order by a; # check that savepoints work :)
+
+show binlog events from 79;
+
+# and when ROLLBACK is not explicit?
+delete from ti;
+delete from tm;
+reset master;
+
+select get_lock("a",10);
+begin;
+insert into ti values(8);
+insert into tm select * from ti;
+disconnect con1;
+
+connection con2;
+# 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 (it may not
+# even be started, so con1 may have not even attempted to lock the binlog yet;
+# so SHOW BINLOG EVENTS may come before con1 does the loggin. To be sure that
+# logging has been done, we use a user lock.
+select get_lock("a",10);
+show binlog events from 79;
+
+# and when not in a transaction?
+delete from ti;
+delete from tm;
+reset master;
+
+insert into ti values(9);
+insert into tm select * from ti;
+
+show binlog events from 79;
+
+# Check that when the query updating the MyISAM table is the first in the
+# transaction, we log it immediately.
+delete from ti;
+delete from tm;
+reset master;
+
+insert into ti values(10); # first make ti non-empty
+begin;
+insert into tm select * from ti;
+show binlog events from 79;
+insert into ti values(11);
+commit;
+
+show binlog events from 79;
+
+
+# Check that things work like before this BEGIN/ROLLBACK code was added, when tm
+# is INNODB
+
+alter table tm type=INNODB;
+
+delete from ti;
+delete from tm;
+reset master;
+
+begin;
+insert into ti values(12);
+insert into tm select * from ti;
+commit;
+
+show binlog events from 79;
+
+delete from ti;
+delete from tm;
+reset master;
+
+begin;
+insert into ti values(13);
+insert into tm select * from ti;
+rollback;
+
+show binlog events from 79;
+
+delete from ti;
+delete from tm;
+reset master;
+
+begin;
+insert into ti values(14);
+savepoint my_savepoint;
+insert into ti values(15);
+insert into tm select * from ti;
+rollback to savepoint my_savepoint;
+commit;
+
+show binlog events from 79;
+
+delete from ti;
+delete from tm;
+reset master;
+
+begin;
+insert into ti values(16);
+savepoint my_savepoint;
+insert into ti values(17);
+insert into tm select * from ti;
+rollback to savepoint my_savepoint;
+insert into ti values(18);
+commit;
+select a from ti order by a; # check that savepoints work :)
+
+show binlog events from 79;
+
+drop table ti,tm;
diff --git a/mysql-test/t/rpl_loaddata.test b/mysql-test/t/rpl_loaddata.test
index 65e07aaa823..4c4ff6a093e 100644
--- a/mysql-test/t/rpl_loaddata.test
+++ b/mysql-test/t/rpl_loaddata.test
@@ -32,15 +32,13 @@ sync_with_master;
select * from t1;
select * from t3;
# We want to be sure that LOAD DATA is in the slave's binlog.
-# But we can't simply read this binlog, because the file_id is uncertain (would
-# cause test failures). So instead, we test if the binlog looks long enough to
+# But we can't simply read this binlog, because as the slave has not been
+# restarted for this test, the file_id is uncertain (would cause test
+# failures). So instead, we test if the binlog looks long enough to
# contain LOAD DATA. That is, I (Guilhem) have done SHOW BINLOG EVENTS on my
-# machine, saw that the last event is 'create table t3' and is at position 898
-# when things go fine. If LOAD DATA was not logged, the binlog would be shorter
-# than 898 bytes and there would be an error in SHOW BINLOG EVENTS. Of course,
-# if someone changes the content of '../../std_data/rpl_loaddata2.dat', 898 will
-# have to be changed too.
-show binlog events from 898;
+# machine, saw that the binlog is of size 964 when things go fine.
+# If LOAD DATA was not logged, the binlog would be shorter.
+show master status;
connection master;
diff --git a/sql/handler.cc b/sql/handler.cc
index 96611301bfa..0d29dbeaa31 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -349,7 +349,7 @@ int ha_commit_trans(THD *thd, THD_TRANS* trans)
if (trans == &thd->transaction.all && mysql_bin_log.is_open() &&
my_b_tell(&thd->transaction.trans_log))
{
- mysql_bin_log.write(thd, &thd->transaction.trans_log);
+ mysql_bin_log.write(thd, &thd->transaction.trans_log, 1);
reinit_io_cache(&thd->transaction.trans_log,
WRITE_CACHE, (my_off_t) 0, 0, 1);
thd->transaction.trans_log.end_of_file= max_binlog_cache_size;
@@ -432,9 +432,21 @@ int ha_rollback_trans(THD *thd, THD_TRANS *trans)
}
#endif
if (trans == &thd->transaction.all)
+ {
+ /*
+ Update the binary log with a BEGIN/ROLLBACK block if we have cached some
+ queries and we updated some non-transactional table. Such cases should
+ be rare (updating a non-transactional table inside a transaction...).
+ */
+ if (unlikely((thd->options & OPTION_STATUS_NO_TRANS_UPDATE) &&
+ mysql_bin_log.is_open() &&
+ my_b_tell(&thd->transaction.trans_log)))
+ mysql_bin_log.write(thd, &thd->transaction.trans_log, 0);
+ /* Flushed or not, empty the binlog cache */
reinit_io_cache(&thd->transaction.trans_log,
- WRITE_CACHE, (my_off_t) 0, 0, 1);
- thd->transaction.trans_log.end_of_file= max_binlog_cache_size;
+ WRITE_CACHE, (my_off_t) 0, 0, 1);
+ thd->transaction.trans_log.end_of_file= max_binlog_cache_size;
+ }
thd->variables.tx_isolation=thd->session_tx_isolation;
if (operation_done)
{
@@ -448,9 +460,27 @@ int ha_rollback_trans(THD *thd, THD_TRANS *trans)
/*
-Rolls the current transaction back to a savepoint.
-Return value: 0 if success, 1 if there was not a savepoint of the given
-name.
+ Rolls the current transaction back to a savepoint.
+ Return value: 0 if success, 1 if there was not a savepoint of the given
+ name.
+ NOTE: how do we handle this (unlikely but legal) case:
+ [transaction] + [update to non-trans table] + [rollback to savepoint] ?
+ The problem occurs when a savepoint is before the update to the
+ non-transactional table. Then when there's a rollback to the savepoint, if we
+ simply truncate the binlog cache, we lose the part of the binlog cache where
+ the update is. If we want to not lose it, we need to write the SAVEPOINT
+ command and the ROLLBACK TO SAVEPOINT command to the binlog cache. The latter
+ is easy: it's just write at the end of the binlog cache, but the former should
+ be *inserted* to the place where the user called SAVEPOINT. The solution is
+ that when the user calls SAVEPOINT, we write it to the binlog cache (so no
+ need to later insert it). As transactions are never intermixed in the binary log
+ (i.e. they are serialized), we won't have conflicts with savepoint names when
+ using mysqlbinlog or in the slave SQL thread.
+ Then when ROLLBACK TO SAVEPOINT is called, if we updated some
+ non-transactional table, we don't truncate the binlog cache but instead write
+ ROLLBACK TO SAVEPOINT to it; otherwise we truncate the binlog cache (which
+ will chop the SAVEPOINT command from the binlog cache, which is good as in
+ that case there is no need to have it in the binlog).
*/
int ha_rollback_to_savepoint(THD *thd, char *savepoint_name)
@@ -475,8 +505,24 @@ int ha_rollback_to_savepoint(THD *thd, char *savepoint_name)
error=1;
}
else
- reinit_io_cache(&thd->transaction.trans_log, WRITE_CACHE,
- binlog_cache_pos, 0, 0);
+ {
+ /*
+ Write ROLLBACK TO SAVEPOINT to the binlog cache if we have updated some
+ non-transactional table. Otherwise, truncate the binlog cache starting
+ from the SAVEPOINT command.
+ */
+ if (unlikely((thd->options & OPTION_STATUS_NO_TRANS_UPDATE) &&
+ mysql_bin_log.is_open() &&
+ my_b_tell(&thd->transaction.trans_log)))
+ {
+ Query_log_event qinfo(thd, thd->query, thd->query_length, TRUE);
+ if (mysql_bin_log.write(&qinfo))
+ error= 1;
+ }
+ else
+ reinit_io_cache(&thd->transaction.trans_log, WRITE_CACHE,
+ binlog_cache_pos, 0, 0);
+ }
operation_done=1;
#endif
if (operation_done)
@@ -505,6 +551,13 @@ int ha_savepoint(THD *thd, char *savepoint_name)
#ifdef HAVE_INNOBASE_DB
innobase_savepoint(thd,savepoint_name, binlog_cache_pos);
#endif
+ /* Write it to the binary log (see comments of ha_rollback_to_savepoint). */
+ if (mysql_bin_log.is_open())
+ {
+ Query_log_event qinfo(thd, thd->query, thd->query_length, TRUE);
+ if (mysql_bin_log.write(&qinfo))
+ error= 1;
+ }
}
#endif /* USING_TRANSACTIONS */
DBUG_RETURN(error);
diff --git a/sql/log.cc b/sql/log.cc
index ee774ea3700..6e9fa38c407 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -1062,7 +1062,17 @@ bool MYSQL_LOG::write(Log_event* event_info)
bool should_rotate = 0;
const char *local_db = event_info->get_db();
#ifdef USING_TRANSACTIONS
- IO_CACHE *file = ((event_info->get_cache_stmt()) ?
+ /*
+ Should we write to the binlog cache or to the binlog on disk?
+ Write to the binlog cache if:
+ - it is already not empty (meaning we're in a transaction; note that the
+ present event could be about a non-transactional table, but still we need
+ to write to the binlog cache in that case to handle updates to mixed
+ trans/non-trans table types the best possible in binlogging)
+ - or if the event asks for it (cache_stmt == true).
+ */
+ IO_CACHE *file = ((event_info->get_cache_stmt() ||
+ my_b_tell(&thd->transaction.trans_log)) ?
&thd->transaction.trans_log :
&log_file);
#else
@@ -1258,6 +1268,13 @@ uint MYSQL_LOG::next_file_id()
/*
Write a cached log entry to the binary log
+ SYNOPSIS
+ write()
+ thd
+ cache The cache to copy to the binlog
+ commit_or_rollback If true, will write "COMMIT" in the end, if false will
+ write "ROLLBACK".
+
NOTE
- We only come here if there is something in the cache.
- The thing in the cache is always a complete transaction
@@ -1265,10 +1282,13 @@ uint MYSQL_LOG::next_file_id()
IMPLEMENTATION
- To support transaction over replication, we wrap the transaction
- with BEGIN/COMMIT in the binary log.
+ with BEGIN/COMMIT or BEGIN/ROLLBACK in the binary log.
+ We want to write a BEGIN/ROLLBACK block when a non-transactional table was
+ updated in a transaction which was rolled back. This is to ensure that the
+ same updates are run on the slave.
*/
-bool MYSQL_LOG::write(THD *thd, IO_CACHE *cache)
+bool MYSQL_LOG::write(THD *thd, IO_CACHE *cache, bool commit_or_rollback)
{
VOID(pthread_mutex_lock(&LOCK_log));
DBUG_ENTER("MYSQL_LOG::write(cache");
@@ -1322,7 +1342,10 @@ bool MYSQL_LOG::write(THD *thd, IO_CACHE *cache)
*/
{
- Query_log_event qinfo(thd, "COMMIT", 6, TRUE);
+ Query_log_event qinfo(thd,
+ commit_or_rollback ? "COMMIT" : "ROLLBACK",
+ commit_or_rollback ? 6 : 8,
+ TRUE);
qinfo.set_log_pos(this);
if (qinfo.write(&log_file) || flush_io_cache(&log_file))
goto err;
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 9e7546dd635..54e4d34f77e 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -1803,7 +1803,7 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli)
*/
if (!strcmp(thd->query,"BEGIN"))
rli->inside_transaction= opt_using_transactions;
- else if (!strcmp(thd->query,"COMMIT"))
+ else if (!(strcmp(thd->query,"COMMIT") && strcmp(thd->query,"ROLLBACK")))
rli->inside_transaction=0;
/*
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 49a364856eb..b30faa3e9d9 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -140,7 +140,7 @@ public:
bool write(THD *thd, const char *query, uint query_length,
time_t query_start=0);
bool write(Log_event* event_info); // binary log write
- bool write(THD *thd, IO_CACHE *cache);
+ bool write(THD *thd, IO_CACHE *cache, bool commit_or_rollback);
/*
v stands for vector
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 167ccf974c7..0a83358e8c6 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -1367,6 +1367,8 @@ void select_insert::send_error(uint errcode,const char *err)
table->file->has_transactions());
mysql_bin_log.write(&qinfo);
}
+ if (!table->tmp_table)
+ thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
}
ha_rollback_stmt(thd);
if (info.copied || info.deleted)
@@ -1398,6 +1400,8 @@ bool select_insert::send_eof()
if (info.copied || info.deleted)
{
query_cache_invalidate3(thd, table, 1);
+ if (!(table->file->has_transactions() || table->tmp_table))
+ thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
}
if (error)
{
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 1479a611b5a..548714345f8 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -2553,7 +2553,16 @@ mysql_execute_command(void)
thd->server_status&= ~SERVER_STATUS_IN_TRANS;
if (!ha_rollback(thd))
{
- if (thd->options & OPTION_STATUS_NO_TRANS_UPDATE)
+ /*
+ If a non-transactional table was updated, warn; don't warn if this is a
+ slave thread (because when a slave thread executes a ROLLBACK, it has
+ been read from the binary log, so it's 100% sure and normal to produce
+ error ER_WARNING_NOT_COMPLETE_ROLLBACK. If we sent the warning to the
+ slave SQL thread, it would not stop the thread but just be printed in
+ the error log; but we don't want users to wonder why they have this
+ message in the error log, so we don't send it.
+ */
+ if ((thd->options & OPTION_STATUS_NO_TRANS_UPDATE) && !thd->slave_thread)
send_warning(&thd->net,ER_WARNING_NOT_COMPLETE_ROLLBACK,0);
else
send_ok(&thd->net);
@@ -2565,7 +2574,7 @@ mysql_execute_command(void)
case SQLCOM_ROLLBACK_TO_SAVEPOINT:
if (!ha_rollback_to_savepoint(thd, lex->savepoint_name))
{
- if (thd->options & OPTION_STATUS_NO_TRANS_UPDATE)
+ if ((thd->options & OPTION_STATUS_NO_TRANS_UPDATE) && !thd->slave_thread)
send_warning(&thd->net,ER_WARNING_NOT_COMPLETE_ROLLBACK,0);
else
send_ok(&thd->net);