Commit babe727b authored by Alfranio Correia's avatar Alfranio Correia

merge mysql-5.5-bugteam (local) --> mysql-5.5-bugteam

parents 4a1a6a2c c26c9b80
# Embedded server doesn't support binlog
-- source include/not_embedded.inc
-- source include/have_innodb.inc
# Creating tables
--disable_warnings
drop table if exists t1, t2;
--enable_warnings
create table t1 (a int) engine=innodb;
create table t2 (a int) engine=myisam;
#
# This test checks binlog_cache_use and binlog_cache_disk_use when
# transactions are committed and after when they are aborted.
#
#
# Checking commit.
#
--echo **** Preparing the enviroment to check commit and its effect on
--echo **** the binlog_cache_use and binlog_cache_disk_use.
--echo **** Expected: binlog_cache_use = 0, binlog_cache_disk_use = 0.
flush status;
let $exp_cache= 0;
let $got_cache= query_get_value(show status like "binlog_cache_use", Value, 1);
let $exp_disk= 0;
let $got_disk= query_get_value(show status like "binlog_cache_disk_use", Value, 1);
if (`SELECT $got_cache <> $exp_cache || $got_disk <> $exp_disk`)
{
-- echo "Expected: binlog_cache_use = $exp_cache, binlog_cache_disk_use = $exp_disk but got binlog_cache_use = $got_cache, binlog_cache_disk_use = $got_disk but"
-- die
}
--echo **** Now we are going to create transactional changes which are long enough so
--echo **** they will be flushed to disk...
--echo **** Expected: binlog_cache_use = 1, binlog_cache_disk_use = 1.
let $1=2000;
disable_query_log;
begin;
while ($1)
{
eval insert into t1 values( $1 );
dec $1;
}
commit;
enable_query_log;
let $exp_cache= 1;
let $got_cache= query_get_value(show status like "binlog_cache_use", Value, 1);
let $exp_disk= 1;
let $got_disk= query_get_value(show status like "binlog_cache_disk_use", Value, 1);
if (`SELECT $got_cache <> $exp_cache || $got_disk <> $exp_disk`)
{
-- echo "Expected: binlog_cache_use = $exp_cache, binlog_cache_disk_use = $exp_disk but got binlog_cache_use = $got_cache, binlog_cache_disk_use = $got_disk but"
-- die
}
--echo **** Transactional changes which should not be flushed to disk and so should not
--echo **** increase binlog_cache_disk_use.
--echo **** Expected: binlog_cache_use = 2, binlog_cache_disk_use = 1.
begin;
insert into t1 values( 1 );
commit;
let $exp_cache= 2;
let $got_cache= query_get_value(show status like "binlog_cache_use", Value, 1);
let $exp_disk= 1;
let $got_disk= query_get_value(show status like "binlog_cache_disk_use", Value, 1);
if (`SELECT $got_cache <> $exp_cache || $got_disk <> $exp_disk`)
{
-- echo "Expected: binlog_cache_use = $exp_cache, binlog_cache_disk_use = $exp_disk but got binlog_cache_use = $got_cache, binlog_cache_disk_use = $got_disk but"
-- die
}
--echo **** Non-Transactional changes which should not be flushed to disk and so should not
--echo **** increase binlog_cache_disk_use.
--echo **** Expected: binlog_cache_use = 3, binlog_cache_disk_use = 1.
begin;
insert into t2 values( 1 );
commit;
let $exp_cache= 3;
let $got_cache= query_get_value(show status like "binlog_cache_use", Value, 1);
let $exp_disk= 1;
let $got_disk= query_get_value(show status like "binlog_cache_disk_use", Value, 1);
if (`SELECT $got_cache <> $exp_cache || $got_disk <> $exp_disk`)
{
-- echo "Expected: binlog_cache_use = $exp_cache, binlog_cache_disk_use = $exp_disk but got binlog_cache_use = $got_cache, binlog_cache_disk_use = $got_disk but"
-- die
}
--echo **** Mixed changes which should not be flushed to disk and so should not
--echo **** increase binlog_cache_disk_use.
--echo **** Expected: binlog_cache_use = 5, binlog_cache_disk_use = 1.
begin;
insert into t1 values( 1 );
insert into t2 values( 1 );
commit;
let $exp_cache= 5;
let $got_cache= query_get_value(show status like "binlog_cache_use", Value, 1);
let $exp_disk= 1;
let $got_disk= query_get_value(show status like "binlog_cache_disk_use", Value, 1);
if (`SELECT $got_cache <> $exp_cache || $got_disk <> $exp_disk`)
{
-- echo "Expected: binlog_cache_use = $exp_cache, binlog_cache_disk_use = $exp_disk but got binlog_cache_use = $got_cache, binlog_cache_disk_use = $got_disk but"
-- die
}
#
# Checking abort.
#
--echo **** Preparing the enviroment to check abort and its effect on
--echo **** the binlog_cache_use and binlog_cache_disk_use
--echo **** Expected: binlog_cache_use = 0, binlog_cache_disk_use = 0.
flush status;
let $exp_cache= 0;
let $got_cache= query_get_value(show status like "binlog_cache_use", Value, 1);
let $exp_disk= 0;
let $got_disk= query_get_value(show status like "binlog_cache_disk_use", Value, 1);
if (`SELECT $got_cache <> $exp_cache || $got_disk <> $exp_disk`)
{
-- echo "Expected: binlog_cache_use = $exp_cache, binlog_cache_disk_use = $exp_disk but got binlog_cache_use = $got_cache, binlog_cache_disk_use = $got_disk but"
-- die
}
--echo **** Now we are going to create transactional changes which are long enough so
--echo **** they will be flushed to disk...
--echo **** Expected: binlog_cache_use = 1, binlog_cache_disk_use = 1.
let $1=2000;
disable_query_log;
begin;
while ($1)
{
eval insert into t1 values( $1 );
dec $1;
}
rollback;
enable_query_log;
let $exp_cache= 1;
let $got_cache= query_get_value(show status like "binlog_cache_use", Value, 1);
let $exp_disk= 1;
let $got_disk= query_get_value(show status like "binlog_cache_disk_use", Value, 1);
if (`SELECT $got_cache <> $exp_cache || $got_disk <> $exp_disk`)
{
-- echo "Expected: binlog_cache_use = $exp_cache, binlog_cache_disk_use = $exp_disk but got binlog_cache_use = $got_cache, binlog_cache_disk_use = $got_disk but"
-- die
}
--echo **** Transactional changes which should not be flushed to disk and so should not
--echo **** increase binlog_cache_disk_use.
--echo **** Expected: binlog_cache_use = 2, binlog_cache_disk_use = 1.
begin;
insert into t1 values( 1 );
rollback;
let $exp_cache= 2;
let $got_cache= query_get_value(show status like "binlog_cache_use", Value, 1);
let $exp_disk= 1;
let $got_disk= query_get_value(show status like "binlog_cache_disk_use", Value, 1);
if (`SELECT $got_cache <> $exp_cache || $got_disk <> $exp_disk`)
{
-- echo "Expected: binlog_cache_use = $exp_cache, binlog_cache_disk_use = $exp_disk but got binlog_cache_use = $got_cache, binlog_cache_disk_use = $got_disk but"
-- die
}
--echo **** Non-Transactional changes which should not be flushed to disk and so should not
--echo **** increase binlog_cache_disk_use.
--echo **** Expected: binlog_cache_use = 3, binlog_cache_disk_use = 1.
begin;
insert into t2 values( 1 );
rollback;
let $exp_cache= 3;
let $got_cache= query_get_value(show status like "binlog_cache_use", Value, 1);
let $exp_disk= 1;
let $got_disk= query_get_value(show status like "binlog_cache_disk_use", Value, 1);
if (`SELECT $got_cache <> $exp_cache || $got_disk <> $exp_disk`)
{
-- echo "Expected: binlog_cache_use = $exp_cache, binlog_cache_disk_use = $exp_disk but got binlog_cache_use = $got_cache, binlog_cache_disk_use = $got_disk but"
-- die
}
--echo **** Mixed changes which should not be flushed to disk and so should not
--echo **** increase binlog_cache_disk_use.
--echo **** Expected: binlog_cache_use = 5, binlog_cache_disk_use = 1.
begin;
insert into t1 values( 1 );
insert into t2 values( 1 );
rollback;
let $exp_cache= 5;
let $got_cache= query_get_value(show status like "binlog_cache_use", Value, 1);
let $exp_disk= 1;
let $got_disk= query_get_value(show status like "binlog_cache_disk_use", Value, 1);
if (`SELECT $got_cache <> $exp_cache || $got_disk <> $exp_disk`)
{
-- echo "Expected: binlog_cache_use = $exp_cache, binlog_cache_disk_use = $exp_disk but got binlog_cache_use = $got_cache, binlog_cache_disk_use = $got_disk but"
-- die
}
drop table t1, t2;
# Embedded server doesn't support binlog
-- source include/not_embedded.inc
-- source include/have_innodb.inc
#
# Let us test binlog_cache_use and binlog_cache_disk_use status vars.
# Actually this test has nothing to do with innodb per se, it just requires
# transactional table.
#
flush status;
show status like "binlog_cache_use";
show status like "binlog_cache_disk_use";
--disable_warnings
drop table if exists t1;
--enable_warnings
create table t1 (a int) engine=innodb;
# Now we are going to create transaction which is long enough so its
# transaction binlog will be flushed to disk...
let $1=2000;
disable_query_log;
begin;
while ($1)
{
eval insert into t1 values( $1 );
dec $1;
}
commit;
enable_query_log;
show status like "binlog_cache_use";
show status like "binlog_cache_disk_use";
# Transaction which should not be flushed to disk and so should not
# increase binlog_cache_disk_use.
begin;
delete from t1;
commit;
show status like "binlog_cache_use";
show status like "binlog_cache_disk_use";
drop table t1;
...@@ -123,7 +123,7 @@ Binlog_cache_disk_use 0 ...@@ -123,7 +123,7 @@ Binlog_cache_disk_use 0
create table t1 (a int) engine=innodb; create table t1 (a int) engine=innodb;
show status like "binlog_cache_use"; show status like "binlog_cache_use";
Variable_name Value Variable_name Value
Binlog_cache_use 2 Binlog_cache_use 1
show status like "binlog_cache_disk_use"; show status like "binlog_cache_disk_use";
Variable_name Value Variable_name Value
Binlog_cache_disk_use 1 Binlog_cache_disk_use 1
...@@ -132,7 +132,7 @@ delete from t1; ...@@ -132,7 +132,7 @@ delete from t1;
commit; commit;
show status like "binlog_cache_use"; show status like "binlog_cache_use";
Variable_name Value Variable_name Value
Binlog_cache_use 4 Binlog_cache_use 2
show status like "binlog_cache_disk_use"; show status like "binlog_cache_disk_use";
Variable_name Value Variable_name Value
Binlog_cache_disk_use 1 Binlog_cache_disk_use 1
......
flush status;
show status like "binlog_cache_use";
Variable_name Value
Binlog_cache_use 0
show status like "binlog_cache_disk_use";
Variable_name Value
Binlog_cache_disk_use 0
drop table if exists t1;
create table t1 (a int) engine=innodb;
show status like "binlog_cache_use";
Variable_name Value
Binlog_cache_use 2
show status like "binlog_cache_disk_use";
Variable_name Value
Binlog_cache_disk_use 1
begin;
delete from t1;
commit;
show status like "binlog_cache_use";
Variable_name Value
Binlog_cache_use 4
show status like "binlog_cache_disk_use";
Variable_name Value
Binlog_cache_disk_use 1
drop table t1;
drop table if exists t1, t2;
create table t1 (a int) engine=innodb;
create table t2 (a int) engine=myisam;
**** Preparing the enviroment to check commit and its effect on
**** the binlog_cache_use and binlog_cache_disk_use.
**** Expected: binlog_cache_use = 0, binlog_cache_disk_use = 0.
flush status;
**** Now we are going to create transactional changes which are long enough so
**** they will be flushed to disk...
**** Expected: binlog_cache_use = 1, binlog_cache_disk_use = 1.
**** Transactional changes which should not be flushed to disk and so should not
**** increase binlog_cache_disk_use.
**** Expected: binlog_cache_use = 2, binlog_cache_disk_use = 1.
begin;
insert into t1 values( 1 );
commit;
**** Non-Transactional changes which should not be flushed to disk and so should not
**** increase binlog_cache_disk_use.
**** Expected: binlog_cache_use = 3, binlog_cache_disk_use = 1.
begin;
insert into t2 values( 1 );
commit;
**** Mixed changes which should not be flushed to disk and so should not
**** increase binlog_cache_disk_use.
**** Expected: binlog_cache_use = 5, binlog_cache_disk_use = 1.
begin;
insert into t1 values( 1 );
insert into t2 values( 1 );
commit;
**** Preparing the enviroment to check abort and its effect on
**** the binlog_cache_use and binlog_cache_disk_use
**** Expected: binlog_cache_use = 0, binlog_cache_disk_use = 0.
flush status;
**** Now we are going to create transactional changes which are long enough so
**** they will be flushed to disk...
**** Expected: binlog_cache_use = 1, binlog_cache_disk_use = 1.
**** Transactional changes which should not be flushed to disk and so should not
**** increase binlog_cache_disk_use.
**** Expected: binlog_cache_use = 2, binlog_cache_disk_use = 1.
begin;
insert into t1 values( 1 );
rollback;
**** Non-Transactional changes which should not be flushed to disk and so should not
**** increase binlog_cache_disk_use.
**** Expected: binlog_cache_use = 3, binlog_cache_disk_use = 1.
begin;
insert into t2 values( 1 );
rollback;
Warnings:
Warning 1196 Some non-transactional changed tables couldn't be rolled back
**** Mixed changes which should not be flushed to disk and so should not
**** increase binlog_cache_disk_use.
**** Expected: binlog_cache_use = 5, binlog_cache_disk_use = 1.
begin;
insert into t1 values( 1 );
insert into t2 values( 1 );
rollback;
Warnings:
Warning 1196 Some non-transactional changed tables couldn't be rolled back
drop table t1, t2;
drop table if exists t1, t2;
create table t1 (a int) engine=innodb;
create table t2 (a int) engine=myisam;
**** Preparing the enviroment to check commit and its effect on
**** the binlog_cache_use and binlog_cache_disk_use.
**** Expected: binlog_cache_use = 0, binlog_cache_disk_use = 0.
flush status;
**** Now we are going to create transactional changes which are long enough so
**** they will be flushed to disk...
**** Expected: binlog_cache_use = 1, binlog_cache_disk_use = 1.
**** Transactional changes which should not be flushed to disk and so should not
**** increase binlog_cache_disk_use.
**** Expected: binlog_cache_use = 2, binlog_cache_disk_use = 1.
begin;
insert into t1 values( 1 );
commit;
**** Non-Transactional changes which should not be flushed to disk and so should not
**** increase binlog_cache_disk_use.
**** Expected: binlog_cache_use = 3, binlog_cache_disk_use = 1.
begin;
insert into t2 values( 1 );
commit;
**** Mixed changes which should not be flushed to disk and so should not
**** increase binlog_cache_disk_use.
**** Expected: binlog_cache_use = 5, binlog_cache_disk_use = 1.
begin;
insert into t1 values( 1 );
insert into t2 values( 1 );
commit;
**** Preparing the enviroment to check abort and its effect on
**** the binlog_cache_use and binlog_cache_disk_use
**** Expected: binlog_cache_use = 0, binlog_cache_disk_use = 0.
flush status;
**** Now we are going to create transactional changes which are long enough so
**** they will be flushed to disk...
**** Expected: binlog_cache_use = 1, binlog_cache_disk_use = 1.
**** Transactional changes which should not be flushed to disk and so should not
**** increase binlog_cache_disk_use.
**** Expected: binlog_cache_use = 2, binlog_cache_disk_use = 1.
begin;
insert into t1 values( 1 );
rollback;
**** Non-Transactional changes which should not be flushed to disk and so should not
**** increase binlog_cache_disk_use.
**** Expected: binlog_cache_use = 3, binlog_cache_disk_use = 1.
begin;
insert into t2 values( 1 );
rollback;
Warnings:
Warning 1196 Some non-transactional changed tables couldn't be rolled back
**** Mixed changes which should not be flushed to disk and so should not
**** increase binlog_cache_disk_use.
**** Expected: binlog_cache_use = 5, binlog_cache_disk_use = 1.
begin;
insert into t1 values( 1 );
insert into t2 values( 1 );
rollback;
Warnings:
Warning 1196 Some non-transactional changed tables couldn't be rolled back
drop table t1, t2;
flush status;
show status like "binlog_cache_use";
Variable_name Value
Binlog_cache_use 0
show status like "binlog_cache_disk_use";
Variable_name Value
Binlog_cache_disk_use 0
drop table if exists t1;
create table t1 (a int) engine=innodb;
show status like "binlog_cache_use";
Variable_name Value
Binlog_cache_use 2
show status like "binlog_cache_disk_use";
Variable_name Value
Binlog_cache_disk_use 1
begin;
delete from t1;
commit;
show status like "binlog_cache_use";
Variable_name Value
Binlog_cache_use 4
show status like "binlog_cache_disk_use";
Variable_name Value
Binlog_cache_disk_use 1
drop table t1;
drop table if exists t1, t2;
create table t1 (a int) engine=innodb;
create table t2 (a int) engine=myisam;
**** Preparing the enviroment to check commit and its effect on
**** the binlog_cache_use and binlog_cache_disk_use.
**** Expected: binlog_cache_use = 0, binlog_cache_disk_use = 0.
flush status;
**** Now we are going to create transactional changes which are long enough so
**** they will be flushed to disk...
**** Expected: binlog_cache_use = 1, binlog_cache_disk_use = 1.
**** Transactional changes which should not be flushed to disk and so should not
**** increase binlog_cache_disk_use.
**** Expected: binlog_cache_use = 2, binlog_cache_disk_use = 1.
begin;
insert into t1 values( 1 );
commit;
**** Non-Transactional changes which should not be flushed to disk and so should not
**** increase binlog_cache_disk_use.
**** Expected: binlog_cache_use = 3, binlog_cache_disk_use = 1.
begin;
insert into t2 values( 1 );
commit;
**** Mixed changes which should not be flushed to disk and so should not
**** increase binlog_cache_disk_use.
**** Expected: binlog_cache_use = 5, binlog_cache_disk_use = 1.
begin;
insert into t1 values( 1 );
insert into t2 values( 1 );
commit;
**** Preparing the enviroment to check abort and its effect on
**** the binlog_cache_use and binlog_cache_disk_use
**** Expected: binlog_cache_use = 0, binlog_cache_disk_use = 0.
flush status;
**** Now we are going to create transactional changes which are long enough so
**** they will be flushed to disk...
**** Expected: binlog_cache_use = 1, binlog_cache_disk_use = 1.
**** Transactional changes which should not be flushed to disk and so should not
**** increase binlog_cache_disk_use.
**** Expected: binlog_cache_use = 2, binlog_cache_disk_use = 1.
begin;
insert into t1 values( 1 );
rollback;
**** Non-Transactional changes which should not be flushed to disk and so should not
**** increase binlog_cache_disk_use.
**** Expected: binlog_cache_use = 3, binlog_cache_disk_use = 1.
begin;
insert into t2 values( 1 );
rollback;
Warnings:
Warning 1196 Some non-transactional changed tables couldn't be rolled back
**** Mixed changes which should not be flushed to disk and so should not
**** increase binlog_cache_disk_use.
**** Expected: binlog_cache_use = 5, binlog_cache_disk_use = 1.
begin;
insert into t1 values( 1 );
insert into t2 values( 1 );
rollback;
Warnings:
Warning 1196 Some non-transactional changed tables couldn't be rolled back
drop table t1, t2;
flush status;
show status like "binlog_cache_use";
Variable_name Value
Binlog_cache_use 0
show status like "binlog_cache_disk_use";
Variable_name Value
Binlog_cache_disk_use 0
drop table if exists t1;
create table t1 (a int) engine=innodb;
show status like "binlog_cache_use";
Variable_name Value
Binlog_cache_use 2
show status like "binlog_cache_disk_use";
Variable_name Value
Binlog_cache_disk_use 1
begin;
delete from t1;
commit;
show status like "binlog_cache_use";
Variable_name Value
Binlog_cache_use 4
show status like "binlog_cache_disk_use";
Variable_name Value
Binlog_cache_disk_use 1
drop table t1;
...@@ -2,4 +2,4 @@ ...@@ -2,4 +2,4 @@
# For both statement and row based bin logs 9/19/2005 [jbm] # For both statement and row based bin logs 9/19/2005 [jbm]
-- source include/have_binlog_format_mixed.inc -- source include/have_binlog_format_mixed.inc
-- source extra/binlog_tests/innodb_stat.test -- source extra/binlog_tests/binlog_cache_stat.test
...@@ -2,4 +2,4 @@ ...@@ -2,4 +2,4 @@
# For both statement and row based bin logs 9/19/2005 [jbm] # For both statement and row based bin logs 9/19/2005 [jbm]
-- source include/have_binlog_format_row.inc -- source include/have_binlog_format_row.inc
-- source extra/binlog_tests/innodb_stat.test -- source extra/binlog_tests/binlog_cache_stat.test
...@@ -2,4 +2,4 @@ ...@@ -2,4 +2,4 @@
# For both statement and row based bin logs 9/19/2005 [jbm] # For both statement and row based bin logs 9/19/2005 [jbm]
-- source include/have_binlog_format_statement.inc -- source include/have_binlog_format_statement.inc
-- source extra/binlog_tests/innodb_stat.test -- source extra/binlog_tests/binlog_cache_stat.test
...@@ -257,11 +257,20 @@ public: ...@@ -257,11 +257,20 @@ public:
void reset() void reset()
{ {
compute_statistics();
truncate(0); truncate(0);
changes_to_non_trans_temp_table_flag= FALSE; changes_to_non_trans_temp_table_flag= FALSE;
incident= FALSE; incident= FALSE;
before_stmt_pos= MY_OFF_T_UNDEF; before_stmt_pos= MY_OFF_T_UNDEF;
cache_log.end_of_file= max_binlog_cache_size; cache_log.end_of_file= max_binlog_cache_size;
/*
The truncate function calls reinit_io_cache that calls my_b_flush_io_cache
which may increase disk_write. This breaks the "disk_writes"' use by the
binary log which aims to compute the ratio between in-memory cache usage
and disk cache usage. To avoid this undesirable behavior, we reset the
variable after truncating the cache.
*/
cache_log.disk_writes= 0;
DBUG_ASSERT(empty()); DBUG_ASSERT(empty());
} }
...@@ -321,6 +330,22 @@ private: ...@@ -321,6 +330,22 @@ private:
*/ */
bool changes_to_non_trans_temp_table_flag; bool changes_to_non_trans_temp_table_flag;
/**
This function computes binlog cache and disk usage.
@param cache_data Pointer to the cache where data is
stored.
*/
void compute_statistics()
{
if (!empty())
{
statistic_increment(binlog_cache_use, &LOCK_status);
if (cache_log.disk_writes != 0)
statistic_increment(binlog_cache_disk_use, &LOCK_status);
}
}
/* /*
It truncates the cache to a certain position. This includes deleting the It truncates the cache to a certain position. This includes deleting the
pending event. pending event.
...@@ -1506,56 +1531,121 @@ static int binlog_close_connection(handlerton *hton, THD *thd) ...@@ -1506,56 +1531,121 @@ static int binlog_close_connection(handlerton *hton, THD *thd)
} }
/** /**
This function flushes a transactional cache upon commit/rollback. This function flushes a cache upon commit/rollback.
@param thd The thread whose transaction should be flushed @param thd The thread whose transaction should be flushed
@param cache_mngr Pointer to the cache data to be flushed @param cache_data Pointer to the cache
@param end_ev The end event either commit/rollback. @param end_ev The end event either commit/rollback
@param is_transactional The type of the cache: transactional or
non-transactional
@return @return
nonzero if an error pops up when flushing the transactional cache. nonzero if an error pops up when flushing the cache.
*/ */
static int static inline int
binlog_flush_trx_cache(THD *thd, binlog_cache_mngr *cache_mngr, binlog_flush_cache(THD *thd, binlog_cache_data* cache_data, Log_event *end_evt,
Log_event *end_ev) bool is_transactional)
{ {
DBUG_ENTER("binlog_flush_trx_cache"); DBUG_ENTER("binlog_flush_cache");
int error=0; int error= 0;
IO_CACHE *cache_log= &cache_mngr->trx_cache.cache_log;
/*
This function handles transactional changes and as such
this flag equals to true.
*/
bool const is_transactional= TRUE;
if (thd->binlog_flush_pending_rows_event(TRUE, is_transactional))
DBUG_RETURN(1);
/*
Doing a commit or a rollback including non-transactional tables,
i.e., ending a transaction where we might write the transaction
cache to the binary log.
We can always end the statement when ending a transaction since
transactions are not allowed inside stored functions. If they
were, we would have to ensure that we're not ending a statement
inside a stored function.
*/
error= mysql_bin_log.write(thd, &cache_mngr->trx_cache.cache_log, end_ev,
cache_mngr->trx_cache.has_incident());
cache_mngr->reset_cache(&cache_mngr->trx_cache);
statistic_increment(binlog_cache_use, &LOCK_status); if (!cache_data->empty())
if (cache_log->disk_writes != 0)
{ {
statistic_increment(binlog_cache_disk_use, &LOCK_status); if (thd->binlog_flush_pending_rows_event(TRUE, is_transactional))
cache_log->disk_writes= 0; DBUG_RETURN(1);
/*
Doing a commit or a rollback including non-transactional tables,
i.e., ending a transaction where we might write the transaction
cache to the binary log.
We can always end the statement when ending a transaction since
transactions are not allowed inside stored functions. If they
were, we would have to ensure that we're not ending a statement
inside a stored function.
*/
error= mysql_bin_log.write(thd, &cache_data->cache_log, end_evt,
cache_data->has_incident());
} }
cache_data->reset();
DBUG_ASSERT(cache_mngr->trx_cache.empty()); DBUG_ASSERT(cache_data->empty());
DBUG_RETURN(error); DBUG_RETURN(error);
} }
/**
This function flushes the stmt-cache upon commit.
@param thd The thread whose transaction should be flushed
@param cache_mngr Pointer to the cache manager
@return
nonzero if an error pops up when flushing the cache.
*/
static inline int
binlog_commit_flush_stmt_cache(THD *thd,
binlog_cache_mngr *cache_mngr)
{
Query_log_event end_evt(thd, STRING_WITH_LEN("COMMIT"),
FALSE, FALSE, TRUE, 0);
return (binlog_flush_cache(thd, &cache_mngr->stmt_cache, &end_evt,
FALSE));
}
/**
This function flushes the trx-cache upon commit.
@param thd The thread whose transaction should be flushed
@param cache_mngr Pointer to the cache manager
@return
nonzero if an error pops up when flushing the cache.
*/
static inline int
binlog_commit_flush_trx_cache(THD *thd, binlog_cache_mngr *cache_mngr)
{
Query_log_event end_evt(thd, STRING_WITH_LEN("COMMIT"),
TRUE, FALSE, TRUE, 0);
return (binlog_flush_cache(thd, &cache_mngr->trx_cache, &end_evt,
TRUE));
}
/**
This function flushes the trx-cache upon rollback.
@param thd The thread whose transaction should be flushed
@param cache_mngr Pointer to the cache manager
@return
nonzero if an error pops up when flushing the cache.
*/
static inline int
binlog_rollback_flush_trx_cache(THD *thd, binlog_cache_mngr *cache_mngr)
{
Query_log_event end_evt(thd, STRING_WITH_LEN("ROLLBACK"),
TRUE, FALSE, TRUE, 0);
return (binlog_flush_cache(thd, &cache_mngr->trx_cache, &end_evt,
TRUE));
}
/**
This function flushes the trx-cache upon commit.
@param thd The thread whose transaction should be flushed
@param cache_mngr Pointer to the cache manager
@param xid Transaction Id
@return
nonzero if an error pops up when flushing the cache.
*/
static inline int
binlog_commit_flush_trx_cache(THD *thd, binlog_cache_mngr *cache_mngr,
my_xid xid)
{
Xid_log_event end_evt(thd, xid);
return (binlog_flush_cache(thd, &cache_mngr->trx_cache, &end_evt,
TRUE));
}
/** /**
This function truncates the transactional cache upon committing or rolling This function truncates the transactional cache upon committing or rolling
back either a transaction or a statement. back either a transaction or a statement.
...@@ -1579,23 +1669,24 @@ binlog_truncate_trx_cache(THD *thd, binlog_cache_mngr *cache_mngr, bool all) ...@@ -1579,23 +1669,24 @@ binlog_truncate_trx_cache(THD *thd, binlog_cache_mngr *cache_mngr, bool all)
*/ */
bool const is_transactional= TRUE; bool const is_transactional= TRUE;
DBUG_PRINT("info", ("thd->options={ %s%s}, transaction: %s", DBUG_PRINT("info", ("thd->options={ %s %s}, transaction: %s",
FLAGSTR(thd->variables.option_bits, OPTION_NOT_AUTOCOMMIT), FLAGSTR(thd->variables.option_bits, OPTION_NOT_AUTOCOMMIT),
FLAGSTR(thd->variables.option_bits, OPTION_BEGIN), FLAGSTR(thd->variables.option_bits, OPTION_BEGIN),
all ? "all" : "stmt")); all ? "all" : "stmt"));
thd->binlog_remove_pending_rows_event(TRUE, is_transactional);
/* /*
If rolling back an entire transaction or a single statement not If rolling back an entire transaction or a single statement not
inside a transaction, we reset the transaction cache. inside a transaction, we reset the transaction cache.
*/ */
thd->binlog_remove_pending_rows_event(TRUE, is_transactional);
if (ending_trans(thd, all)) if (ending_trans(thd, all))
{ {
if (cache_mngr->trx_cache.has_incident()) if (cache_mngr->trx_cache.has_incident())
error= mysql_bin_log.write_incident(thd, TRUE); error= mysql_bin_log.write_incident(thd, TRUE);
cache_mngr->reset_cache(&cache_mngr->trx_cache);
thd->clear_binlog_table_maps(); thd->clear_binlog_table_maps();
cache_mngr->reset_cache(&cache_mngr->trx_cache);
} }
/* /*
If rolling back a statement in a transaction, we truncate the If rolling back a statement in a transaction, we truncate the
...@@ -1619,51 +1710,6 @@ static int binlog_prepare(handlerton *hton, THD *thd, bool all) ...@@ -1619,51 +1710,6 @@ static int binlog_prepare(handlerton *hton, THD *thd, bool all)
return 0; return 0;
} }
/**
This function flushes the non-transactional to the binary log upon
committing or rolling back a statement.
@param thd The thread whose transaction should be flushed
@param cache_mngr Pointer to the cache data to be flushed
@return
nonzero if an error pops up when flushing the non-transactional cache.
*/
static int
binlog_flush_stmt_cache(THD *thd, binlog_cache_mngr *cache_mngr)
{
int error= 0;
DBUG_ENTER("binlog_flush_stmt_cache");
/*
If we are flushing the statement cache, it means that the changes get
through otherwise the cache is empty and this routine should not be called.
*/
DBUG_ASSERT(cache_mngr->stmt_cache.has_incident() == FALSE);
/*
This function handles non-transactional changes and as such this flag equals
to false.
*/
bool const is_transactional= FALSE;
IO_CACHE *cache_log= &cache_mngr->stmt_cache.cache_log;
if (thd->binlog_flush_pending_rows_event(TRUE, is_transactional))
DBUG_RETURN(1);
Query_log_event qev(thd, STRING_WITH_LEN("COMMIT"), TRUE, FALSE, TRUE, 0);
if ((error= mysql_bin_log.write(thd, cache_log, &qev,
cache_mngr->stmt_cache.has_incident())))
DBUG_RETURN(error);
cache_mngr->reset_cache(&cache_mngr->stmt_cache);
statistic_increment(binlog_cache_use, &LOCK_status);
if (cache_log->disk_writes != 0)
{
statistic_increment(binlog_cache_disk_use, &LOCK_status);
cache_log->disk_writes= 0;
}
DBUG_RETURN(error);
}
/** /**
This function is called once after each statement. This function is called once after each statement.
...@@ -1692,7 +1738,7 @@ static int binlog_commit(handlerton *hton, THD *thd, bool all) ...@@ -1692,7 +1738,7 @@ static int binlog_commit(handlerton *hton, THD *thd, bool all)
if (!cache_mngr->stmt_cache.empty()) if (!cache_mngr->stmt_cache.empty())
{ {
binlog_flush_stmt_cache(thd, cache_mngr); error= binlog_commit_flush_stmt_cache(thd, cache_mngr);
} }
if (cache_mngr->trx_cache.empty()) if (cache_mngr->trx_cache.empty())
...@@ -1701,7 +1747,7 @@ static int binlog_commit(handlerton *hton, THD *thd, bool all) ...@@ -1701,7 +1747,7 @@ static int binlog_commit(handlerton *hton, THD *thd, bool all)
we're here because cache_log was flushed in MYSQL_BIN_LOG::log_xid() we're here because cache_log was flushed in MYSQL_BIN_LOG::log_xid()
*/ */
cache_mngr->reset_cache(&cache_mngr->trx_cache); cache_mngr->reset_cache(&cache_mngr->trx_cache);
DBUG_RETURN(0); DBUG_RETURN(error);
} }
/* /*
...@@ -1710,17 +1756,15 @@ static int binlog_commit(handlerton *hton, THD *thd, bool all) ...@@ -1710,17 +1756,15 @@ static int binlog_commit(handlerton *hton, THD *thd, bool all)
- We are in a transaction and a full transaction is committed. - We are in a transaction and a full transaction is committed.
Otherwise, we accumulate the changes. Otherwise, we accumulate the changes.
*/ */
if (ending_trans(thd, all)) if (!error && ending_trans(thd, all))
{ error= binlog_commit_flush_trx_cache(thd, cache_mngr);
Query_log_event qev(thd, STRING_WITH_LEN("COMMIT"), TRUE, FALSE, TRUE, 0);
error= binlog_flush_trx_cache(thd, cache_mngr, &qev);
}
/* /*
This is part of the stmt rollback. This is part of the stmt rollback.
*/ */
if (!all) if (!all)
cache_mngr->trx_cache.set_prev_position(MY_OFF_T_UNDEF); cache_mngr->trx_cache.set_prev_position(MY_OFF_T_UNDEF);
DBUG_RETURN(error); DBUG_RETURN(error);
} }
...@@ -1737,7 +1781,7 @@ static int binlog_commit(handlerton *hton, THD *thd, bool all) ...@@ -1737,7 +1781,7 @@ static int binlog_commit(handlerton *hton, THD *thd, bool all)
static int binlog_rollback(handlerton *hton, THD *thd, bool all) static int binlog_rollback(handlerton *hton, THD *thd, bool all)
{ {
DBUG_ENTER("binlog_rollback"); DBUG_ENTER("binlog_rollback");
int error=0; int error= 0;
binlog_cache_mngr *const cache_mngr= binlog_cache_mngr *const cache_mngr=
(binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton); (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton);
...@@ -1757,16 +1801,16 @@ static int binlog_rollback(handlerton *hton, THD *thd, bool all) ...@@ -1757,16 +1801,16 @@ static int binlog_rollback(handlerton *hton, THD *thd, bool all)
} }
else if (!cache_mngr->stmt_cache.empty()) else if (!cache_mngr->stmt_cache.empty())
{ {
binlog_flush_stmt_cache(thd, cache_mngr); error= binlog_commit_flush_stmt_cache(thd, cache_mngr);
} }
if (cache_mngr->trx_cache.empty()) if (cache_mngr->trx_cache.empty())
{ {
/* /*
we're here because cache_log was flushed in MYSQL_BIN_LOG::log_xid() we're here because cache_log was flushed in MYSQL_BIN_LOG::log_xid()
*/ */
cache_mngr->reset_cache(&cache_mngr->trx_cache); cache_mngr->reset_cache(&cache_mngr->trx_cache);
DBUG_RETURN(0); DBUG_RETURN(error);
} }
if (mysql_bin_log.check_write_error(thd)) if (mysql_bin_log.check_write_error(thd))
...@@ -1782,9 +1826,9 @@ static int binlog_rollback(handlerton *hton, THD *thd, bool all) ...@@ -1782,9 +1826,9 @@ static int binlog_rollback(handlerton *hton, THD *thd, bool all)
We reach this point if the effect of a statement did not properly get into We reach this point if the effect of a statement did not properly get into
a cache and need to be rolled back. a cache and need to be rolled back.
*/ */
error= binlog_truncate_trx_cache(thd, cache_mngr, all); error |= binlog_truncate_trx_cache(thd, cache_mngr, all);
} }
else else if (!error)
{ {
/* /*
We flush the cache wrapped in a beging/rollback if: We flush the cache wrapped in a beging/rollback if:
...@@ -1796,7 +1840,6 @@ static int binlog_rollback(handlerton *hton, THD *thd, bool all) ...@@ -1796,7 +1840,6 @@ static int binlog_rollback(handlerton *hton, THD *thd, bool all)
. the format is MIXED, non-trans table was updated and . the format is MIXED, non-trans table was updated and
aborting a single statement transaction; aborting a single statement transaction;
*/ */
if (ending_trans(thd, all) && if (ending_trans(thd, all) &&
((thd->variables.option_bits & OPTION_KEEP_LOG) || ((thd->variables.option_bits & OPTION_KEEP_LOG) ||
(trans_has_updated_non_trans_table(thd) && (trans_has_updated_non_trans_table(thd) &&
...@@ -1806,10 +1849,7 @@ static int binlog_rollback(handlerton *hton, THD *thd, bool all) ...@@ -1806,10 +1849,7 @@ static int binlog_rollback(handlerton *hton, THD *thd, bool all)
(trans_has_updated_non_trans_table(thd) && (trans_has_updated_non_trans_table(thd) &&
ending_single_stmt_trans(thd,all) && ending_single_stmt_trans(thd,all) &&
thd->variables.binlog_format == BINLOG_FORMAT_MIXED))) thd->variables.binlog_format == BINLOG_FORMAT_MIXED)))
{ error= binlog_rollback_flush_trx_cache(thd, cache_mngr);
Query_log_event qev(thd, STRING_WITH_LEN("ROLLBACK"), TRUE, FALSE, TRUE, 0);
error= binlog_flush_trx_cache(thd, cache_mngr, &qev);
}
/* /*
Truncate the cache if: Truncate the cache if:
. aborting a single or multi-statement transaction or; . aborting a single or multi-statement transaction or;
...@@ -1832,7 +1872,8 @@ static int binlog_rollback(handlerton *hton, THD *thd, bool all) ...@@ -1832,7 +1872,8 @@ static int binlog_rollback(handlerton *hton, THD *thd, bool all)
This is part of the stmt rollback. This is part of the stmt rollback.
*/ */
if (!all) if (!all)
cache_mngr->trx_cache.set_prev_position(MY_OFF_T_UNDEF); cache_mngr->trx_cache.set_prev_position(MY_OFF_T_UNDEF);
DBUG_RETURN(error); DBUG_RETURN(error);
} }
...@@ -6309,15 +6350,14 @@ void TC_LOG_BINLOG::close() ...@@ -6309,15 +6350,14 @@ void TC_LOG_BINLOG::close()
int TC_LOG_BINLOG::log_xid(THD *thd, my_xid xid) int TC_LOG_BINLOG::log_xid(THD *thd, my_xid xid)
{ {
DBUG_ENTER("TC_LOG_BINLOG::log"); DBUG_ENTER("TC_LOG_BINLOG::log");
Xid_log_event xle(thd, xid);
binlog_cache_mngr *cache_mngr= binlog_cache_mngr *cache_mngr=
(binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton); (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton);
/* /*
We always commit the entire transaction when writing an XID. Also We always commit the entire transaction when writing an XID. Also
note that the return value is inverted. note that the return value is inverted.
*/ */
DBUG_RETURN(!binlog_flush_stmt_cache(thd, cache_mngr) && DBUG_RETURN(!binlog_commit_flush_stmt_cache(thd, cache_mngr) &&
!binlog_flush_trx_cache(thd, cache_mngr, &xle)); !binlog_commit_flush_trx_cache(thd, cache_mngr, xid));
} }
void TC_LOG_BINLOG::unlog(ulong cookie, my_xid xid) void TC_LOG_BINLOG::unlog(ulong cookie, my_xid xid)
......
...@@ -2506,7 +2506,7 @@ class Xid_log_event: public Log_event ...@@ -2506,7 +2506,7 @@ class Xid_log_event: public Log_event
my_xid xid; my_xid xid;
#ifdef MYSQL_SERVER #ifdef MYSQL_SERVER
Xid_log_event(THD* thd_arg, my_xid x): Log_event(thd_arg,0,0), xid(x) {} Xid_log_event(THD* thd_arg, my_xid x): Log_event(thd_arg, 0, TRUE), xid(x) {}
#ifdef HAVE_REPLICATION #ifdef HAVE_REPLICATION
void pack_info(Protocol* protocol); void pack_info(Protocol* protocol);
#endif /* HAVE_REPLICATION */ #endif /* HAVE_REPLICATION */
......
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