Merge gbichot@bk-internal.mysql.com:/home/bk/mysql-4.0
into mysql.com:/home/mysql_src/mysql-4.0
This commit is contained in:
commit
9676fdcbcd
@ -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);
|
||||
}
|
||||
|
180
mysql-test/r/mix_innodb_myisam_binlog.result
Normal file
180
mysql-test/r/mix_innodb_myisam_binlog.result
Normal file
@ -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;
|
@ -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;
|
||||
|
175
mysql-test/t/mix_innodb_myisam_binlog.test
Normal file
175
mysql-test/t/mix_innodb_myisam_binlog.test
Normal file
@ -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;
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
31
sql/log.cc
31
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;
|
||||
|
@ -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;
|
||||
|
||||
/*
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user