mirror of
https://github.com/MariaDB/server.git
synced 2025-01-30 18:41:56 +01:00
BUG#56343 binlog_cache_use status is bigger than expected
The binlog_cache_use is incremented twice when changes to a transactional table are committed, i.e. TC_LOG_BINLOG::log_xid calls is called. The problem happens because log_xid calls both binlog_flush_stmt_cache and binlog_flush_trx_cache without checking if such caches are empty thus unintentionally increasing the binlog_cache_use value twice. To fix the problem we avoided incrementing the binlog_cache_use if the cache is empty. We also decided to increment binlog_cache_use when the cache is truncated as the cache is used although its content is discarded and is not written to the binary log. Note that binlog_cache_use is incremented for both types of cache, transactional and non-transactional and that the behavior presented in this patch also applies to the binlog_cache_disk_use. Finally, we re-organized the code around the functions binlog_flush_trx_cache and binlog_flush_stmt_cache. mysql-test/extra/binlog_tests/binlog_cache_stat.test: Updated the test case with comments and additional tests to check both transactional and non-transactional changes and what happens when a is transaction either committed or aborted. mysql-test/suite/binlog/r/binlog_innodb.result: Updated the result file. mysql-test/suite/binlog/r/binlog_mixed_cache_stat.result: Updated the result file. mysql-test/suite/binlog/r/binlog_row_cache_stat.result: Updated the result file. mysql-test/suite/binlog/r/binlog_stm_cache_stat.result: Updated the result file. mysql-test/suite/binlog/t/binlog_mixed_cache_stat.test: Updated the test case with a new source file. mysql-test/suite/binlog/t/binlog_row_cache_stat.test: Updated the test case with a new source file. mysql-test/suite/binlog/t/binlog_stm_cache_stat.test: Updated the test case with a new source file. sql/log_event.cc: Introduced debug information to check if Query_log_event("BEGIN"), Query_log_event("COMMIT") and Query_log_event("ROLLBACK"). sql/log_event.h: Guaranteed Xid_log_event is always classified as a transactional event.
This commit is contained in:
parent
3f975a7fcf
commit
8504580ced
15 changed files with 701 additions and 249 deletions
129
mysql-test/extra/binlog_tests/binlog_cache_stat.test
Normal file
129
mysql-test/extra/binlog_tests/binlog_cache_stat.test
Normal file
|
@ -0,0 +1,129 @@
|
||||||
|
# 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;
|
||||||
|
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
#
|
||||||
|
# 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;
|
||||||
|
show status like "binlog_cache_use";
|
||||||
|
show status like "binlog_cache_disk_use";
|
||||||
|
|
||||||
|
--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;
|
||||||
|
show status like "binlog_cache_use";
|
||||||
|
show status like "binlog_cache_disk_use";
|
||||||
|
|
||||||
|
--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;
|
||||||
|
show status like "binlog_cache_use";
|
||||||
|
show status like "binlog_cache_disk_use";
|
||||||
|
|
||||||
|
--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;
|
||||||
|
show status like "binlog_cache_use";
|
||||||
|
show status like "binlog_cache_disk_use";
|
||||||
|
|
||||||
|
--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;
|
||||||
|
show status like "binlog_cache_use";
|
||||||
|
show status like "binlog_cache_disk_use";
|
||||||
|
|
||||||
|
#
|
||||||
|
# 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;
|
||||||
|
show status like "binlog_cache_use";
|
||||||
|
show status like "binlog_cache_disk_use";
|
||||||
|
|
||||||
|
--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;
|
||||||
|
show status like "binlog_cache_use";
|
||||||
|
show status like "binlog_cache_disk_use";
|
||||||
|
|
||||||
|
--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;
|
||||||
|
show status like "binlog_cache_use";
|
||||||
|
show status like "binlog_cache_disk_use";
|
||||||
|
|
||||||
|
--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;
|
||||||
|
show status like "binlog_cache_use";
|
||||||
|
show status like "binlog_cache_disk_use";
|
||||||
|
|
||||||
|
--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;
|
||||||
|
show status like "binlog_cache_use";
|
||||||
|
show status like "binlog_cache_disk_use";
|
||||||
|
drop table t1, t2;
|
|
@ -1,41 +0,0 @@
|
||||||
# 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
|
||||||
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;
|
||||||
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
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
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;
|
|
120
mysql-test/suite/binlog/r/binlog_mixed_cache_stat.result
Normal file
120
mysql-test/suite/binlog/r/binlog_mixed_cache_stat.result
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
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;
|
||||||
|
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
|
||||||
|
**** 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.
|
||||||
|
show status like "binlog_cache_use";
|
||||||
|
Variable_name Value
|
||||||
|
Binlog_cache_use 1
|
||||||
|
show status like "binlog_cache_disk_use";
|
||||||
|
Variable_name Value
|
||||||
|
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;
|
||||||
|
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
|
||||||
|
**** 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;
|
||||||
|
show status like "binlog_cache_use";
|
||||||
|
Variable_name Value
|
||||||
|
Binlog_cache_use 3
|
||||||
|
show status like "binlog_cache_disk_use";
|
||||||
|
Variable_name Value
|
||||||
|
Binlog_cache_disk_use 1
|
||||||
|
**** 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;
|
||||||
|
show status like "binlog_cache_use";
|
||||||
|
Variable_name Value
|
||||||
|
Binlog_cache_use 5
|
||||||
|
show status like "binlog_cache_disk_use";
|
||||||
|
Variable_name Value
|
||||||
|
Binlog_cache_disk_use 1
|
||||||
|
**** 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;
|
||||||
|
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
|
||||||
|
**** 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.
|
||||||
|
show status like "binlog_cache_use";
|
||||||
|
Variable_name Value
|
||||||
|
Binlog_cache_use 1
|
||||||
|
show status like "binlog_cache_disk_use";
|
||||||
|
Variable_name Value
|
||||||
|
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;
|
||||||
|
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
|
||||||
|
**** 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
|
||||||
|
show status like "binlog_cache_use";
|
||||||
|
Variable_name Value
|
||||||
|
Binlog_cache_use 3
|
||||||
|
show status like "binlog_cache_disk_use";
|
||||||
|
Variable_name Value
|
||||||
|
Binlog_cache_disk_use 1
|
||||||
|
**** 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
|
||||||
|
show status like "binlog_cache_use";
|
||||||
|
Variable_name Value
|
||||||
|
Binlog_cache_use 5
|
||||||
|
show status like "binlog_cache_disk_use";
|
||||||
|
Variable_name Value
|
||||||
|
Binlog_cache_disk_use 1
|
||||||
|
drop table t1, t2;
|
120
mysql-test/suite/binlog/r/binlog_row_cache_stat.result
Normal file
120
mysql-test/suite/binlog/r/binlog_row_cache_stat.result
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
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;
|
||||||
|
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
|
||||||
|
**** 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.
|
||||||
|
show status like "binlog_cache_use";
|
||||||
|
Variable_name Value
|
||||||
|
Binlog_cache_use 1
|
||||||
|
show status like "binlog_cache_disk_use";
|
||||||
|
Variable_name Value
|
||||||
|
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;
|
||||||
|
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
|
||||||
|
**** 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;
|
||||||
|
show status like "binlog_cache_use";
|
||||||
|
Variable_name Value
|
||||||
|
Binlog_cache_use 3
|
||||||
|
show status like "binlog_cache_disk_use";
|
||||||
|
Variable_name Value
|
||||||
|
Binlog_cache_disk_use 1
|
||||||
|
**** 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;
|
||||||
|
show status like "binlog_cache_use";
|
||||||
|
Variable_name Value
|
||||||
|
Binlog_cache_use 5
|
||||||
|
show status like "binlog_cache_disk_use";
|
||||||
|
Variable_name Value
|
||||||
|
Binlog_cache_disk_use 1
|
||||||
|
**** 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;
|
||||||
|
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
|
||||||
|
**** 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.
|
||||||
|
show status like "binlog_cache_use";
|
||||||
|
Variable_name Value
|
||||||
|
Binlog_cache_use 1
|
||||||
|
show status like "binlog_cache_disk_use";
|
||||||
|
Variable_name Value
|
||||||
|
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;
|
||||||
|
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
|
||||||
|
**** 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
|
||||||
|
show status like "binlog_cache_use";
|
||||||
|
Variable_name Value
|
||||||
|
Binlog_cache_use 3
|
||||||
|
show status like "binlog_cache_disk_use";
|
||||||
|
Variable_name Value
|
||||||
|
Binlog_cache_disk_use 1
|
||||||
|
**** 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
|
||||||
|
show status like "binlog_cache_use";
|
||||||
|
Variable_name Value
|
||||||
|
Binlog_cache_use 5
|
||||||
|
show status like "binlog_cache_disk_use";
|
||||||
|
Variable_name Value
|
||||||
|
Binlog_cache_disk_use 1
|
||||||
|
drop table t1, t2;
|
|
@ -1,25 +0,0 @@
|
||||||
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;
|
|
120
mysql-test/suite/binlog/r/binlog_stm_cache_stat.result
Normal file
120
mysql-test/suite/binlog/r/binlog_stm_cache_stat.result
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
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;
|
||||||
|
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
|
||||||
|
**** 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.
|
||||||
|
show status like "binlog_cache_use";
|
||||||
|
Variable_name Value
|
||||||
|
Binlog_cache_use 1
|
||||||
|
show status like "binlog_cache_disk_use";
|
||||||
|
Variable_name Value
|
||||||
|
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;
|
||||||
|
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
|
||||||
|
**** 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;
|
||||||
|
show status like "binlog_cache_use";
|
||||||
|
Variable_name Value
|
||||||
|
Binlog_cache_use 3
|
||||||
|
show status like "binlog_cache_disk_use";
|
||||||
|
Variable_name Value
|
||||||
|
Binlog_cache_disk_use 1
|
||||||
|
**** 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;
|
||||||
|
show status like "binlog_cache_use";
|
||||||
|
Variable_name Value
|
||||||
|
Binlog_cache_use 5
|
||||||
|
show status like "binlog_cache_disk_use";
|
||||||
|
Variable_name Value
|
||||||
|
Binlog_cache_disk_use 1
|
||||||
|
**** 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;
|
||||||
|
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
|
||||||
|
**** 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.
|
||||||
|
show status like "binlog_cache_use";
|
||||||
|
Variable_name Value
|
||||||
|
Binlog_cache_use 1
|
||||||
|
show status like "binlog_cache_disk_use";
|
||||||
|
Variable_name Value
|
||||||
|
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;
|
||||||
|
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
|
||||||
|
**** 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
|
||||||
|
show status like "binlog_cache_use";
|
||||||
|
Variable_name Value
|
||||||
|
Binlog_cache_use 3
|
||||||
|
show status like "binlog_cache_disk_use";
|
||||||
|
Variable_name Value
|
||||||
|
Binlog_cache_disk_use 1
|
||||||
|
**** 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
|
||||||
|
show status like "binlog_cache_use";
|
||||||
|
Variable_name Value
|
||||||
|
Binlog_cache_use 5
|
||||||
|
show status like "binlog_cache_disk_use";
|
||||||
|
Variable_name Value
|
||||||
|
Binlog_cache_disk_use 1
|
||||||
|
drop table t1, t2;
|
|
@ -1,25 +0,0 @@
|
||||||
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 @@
|
||||||
# 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 @@
|
||||||
# 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 @@
|
||||||
# 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
|
276
sql/log.cc
276
sql/log.cc
|
@ -210,6 +210,9 @@ class binlog_cache_data
|
||||||
public:
|
public:
|
||||||
binlog_cache_data(): m_pending(0), before_stmt_pos(MY_OFF_T_UNDEF),
|
binlog_cache_data(): m_pending(0), before_stmt_pos(MY_OFF_T_UNDEF),
|
||||||
incident(FALSE), changes_to_non_trans_temp_table_flag(FALSE)
|
incident(FALSE), changes_to_non_trans_temp_table_flag(FALSE)
|
||||||
|
#ifndef DBUG_OFF
|
||||||
|
, has_trans(FALSE)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
cache_log.end_of_file= max_binlog_cache_size;
|
cache_log.end_of_file= max_binlog_cache_size;
|
||||||
}
|
}
|
||||||
|
@ -262,6 +265,14 @@ public:
|
||||||
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;
|
||||||
|
/*
|
||||||
|
When a truncate is called there may be write activity and by consequence
|
||||||
|
"disk_writes" is increased. 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());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -292,6 +303,18 @@ public:
|
||||||
before_stmt_pos= MY_OFF_T_UNDEF;
|
before_stmt_pos= MY_OFF_T_UNDEF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef DBUG_OFF
|
||||||
|
bool is_transactional()
|
||||||
|
{
|
||||||
|
return(has_trans);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_transactional(bool is_transactional)
|
||||||
|
{
|
||||||
|
has_trans= is_transactional;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Cache to store data before copying it to the binary log.
|
Cache to store data before copying it to the binary log.
|
||||||
*/
|
*/
|
||||||
|
@ -321,6 +344,13 @@ private:
|
||||||
*/
|
*/
|
||||||
bool changes_to_non_trans_temp_table_flag;
|
bool changes_to_non_trans_temp_table_flag;
|
||||||
|
|
||||||
|
#ifndef DBUG_OFF
|
||||||
|
/*
|
||||||
|
Defines the type of the cache either: transactional or non-transactional.
|
||||||
|
*/
|
||||||
|
bool has_trans;
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
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,29 +1536,50 @@ static int binlog_close_connection(handlerton *hton, THD *thd)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This function flushes a transactional cache upon commit/rollback.
|
This function computes binlog cache and disk usage.
|
||||||
|
|
||||||
|
@param cache_data Pointer to the cache where data is
|
||||||
|
stored.
|
||||||
|
*/
|
||||||
|
static inline void
|
||||||
|
binlog_compute_statistics(binlog_cache_data* cache_data)
|
||||||
|
{
|
||||||
|
if (!cache_data->empty())
|
||||||
|
{
|
||||||
|
statistic_increment(binlog_cache_use, &LOCK_status);
|
||||||
|
if (cache_data->cache_log.disk_writes != 0)
|
||||||
|
statistic_increment(binlog_cache_disk_use, &LOCK_status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
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 (!cache_data->empty())
|
||||||
|
{
|
||||||
|
#ifndef DBUG_OFF
|
||||||
|
DBUG_PRINT("info", ("is_transactional(%d), event(%d), cache_data(%d)",
|
||||||
|
is_transactional, end_evt->use_trans_cache(),
|
||||||
|
cache_data->is_transactional()));
|
||||||
|
DBUG_ASSERT(is_transactional == end_evt->use_trans_cache() &&
|
||||||
|
is_transactional == cache_data->is_transactional());
|
||||||
|
#endif
|
||||||
if (thd->binlog_flush_pending_rows_event(TRUE, is_transactional))
|
if (thd->binlog_flush_pending_rows_event(TRUE, is_transactional))
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
/*
|
/*
|
||||||
|
@ -1541,19 +1592,88 @@ binlog_flush_trx_cache(THD *thd, binlog_cache_mngr *cache_mngr,
|
||||||
were, we would have to ensure that we're not ending a statement
|
were, we would have to ensure that we're not ending a statement
|
||||||
inside a stored function.
|
inside a stored function.
|
||||||
*/
|
*/
|
||||||
error= mysql_bin_log.write(thd, &cache_mngr->trx_cache.cache_log, end_ev,
|
error= mysql_bin_log.write(thd, &cache_data->cache_log, end_evt,
|
||||||
cache_mngr->trx_cache.has_incident());
|
cache_data->has_incident());
|
||||||
cache_mngr->reset_cache(&cache_mngr->trx_cache);
|
}
|
||||||
|
binlog_compute_statistics(cache_data);
|
||||||
|
cache_data->reset();
|
||||||
|
|
||||||
statistic_increment(binlog_cache_use, &LOCK_status);
|
DBUG_ASSERT(cache_data->empty());
|
||||||
if (cache_log->disk_writes != 0)
|
DBUG_RETURN(error);
|
||||||
{
|
|
||||||
statistic_increment(binlog_cache_disk_use, &LOCK_status);
|
|
||||||
cache_log->disk_writes= 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DBUG_ASSERT(cache_mngr->trx_cache.empty());
|
/**
|
||||||
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1583,19 +1703,22 @@ binlog_truncate_trx_cache(THD *thd, binlog_cache_mngr *cache_mngr, bool all)
|
||||||
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();
|
||||||
|
|
||||||
|
binlog_compute_statistics(&cache_mngr->trx_cache);
|
||||||
|
|
||||||
|
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 +1742,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.
|
||||||
|
|
||||||
|
@ -1690,19 +1768,7 @@ static int binlog_commit(handlerton *hton, THD *thd, bool all)
|
||||||
YESNO(thd->transaction.all.modified_non_trans_table),
|
YESNO(thd->transaction.all.modified_non_trans_table),
|
||||||
YESNO(thd->transaction.stmt.modified_non_trans_table)));
|
YESNO(thd->transaction.stmt.modified_non_trans_table)));
|
||||||
|
|
||||||
if (!cache_mngr->stmt_cache.empty())
|
binlog_commit_flush_stmt_cache(thd, cache_mngr);
|
||||||
{
|
|
||||||
binlog_flush_stmt_cache(thd, cache_mngr);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cache_mngr->trx_cache.empty())
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
we're here because cache_log was flushed in MYSQL_BIN_LOG::log_xid()
|
|
||||||
*/
|
|
||||||
cache_mngr->reset_cache(&cache_mngr->trx_cache);
|
|
||||||
DBUG_RETURN(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
We commit the transaction if:
|
We commit the transaction if:
|
||||||
|
@ -1711,16 +1777,14 @@ static int binlog_commit(handlerton *hton, THD *thd, bool all)
|
||||||
Otherwise, we accumulate the changes.
|
Otherwise, we accumulate the changes.
|
||||||
*/
|
*/
|
||||||
if (ending_trans(thd, all))
|
if (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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1755,19 +1819,8 @@ static int binlog_rollback(handlerton *hton, THD *thd, bool all)
|
||||||
error= mysql_bin_log.write_incident(thd, TRUE);
|
error= mysql_bin_log.write_incident(thd, TRUE);
|
||||||
cache_mngr->reset_cache(&cache_mngr->stmt_cache);
|
cache_mngr->reset_cache(&cache_mngr->stmt_cache);
|
||||||
}
|
}
|
||||||
else if (!cache_mngr->stmt_cache.empty())
|
else
|
||||||
{
|
binlog_commit_flush_stmt_cache(thd, cache_mngr);
|
||||||
binlog_flush_stmt_cache(thd, cache_mngr);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cache_mngr->trx_cache.empty())
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
we're here because cache_log was flushed in MYSQL_BIN_LOG::log_xid()
|
|
||||||
*/
|
|
||||||
cache_mngr->reset_cache(&cache_mngr->trx_cache);
|
|
||||||
DBUG_RETURN(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mysql_bin_log.check_write_error(thd))
|
if (mysql_bin_log.check_write_error(thd))
|
||||||
{
|
{
|
||||||
|
@ -1796,7 +1849,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 +1858,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;
|
||||||
|
@ -1833,6 +1882,7 @@ static int binlog_rollback(handlerton *hton, THD *thd, bool all)
|
||||||
*/
|
*/
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4364,6 +4414,11 @@ int THD::binlog_setup_trx_data()
|
||||||
|
|
||||||
cache_mngr= new (thd_get_ha_data(this, binlog_hton)) binlog_cache_mngr;
|
cache_mngr= new (thd_get_ha_data(this, binlog_hton)) binlog_cache_mngr;
|
||||||
|
|
||||||
|
#ifndef DBUG_OFF
|
||||||
|
cache_mngr->trx_cache.set_transactional(TRUE);
|
||||||
|
cache_mngr->stmt_cache.set_transactional(FALSE);
|
||||||
|
#endif
|
||||||
|
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6291,15 +6346,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)
|
||||||
|
|
|
@ -2537,6 +2537,22 @@ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg,
|
||||||
bool trx_cache= FALSE;
|
bool trx_cache= FALSE;
|
||||||
cache_type= Log_event::EVENT_INVALID_CACHE;
|
cache_type= Log_event::EVENT_INVALID_CACHE;
|
||||||
|
|
||||||
|
#ifndef DBUG_OFF
|
||||||
|
/*
|
||||||
|
If debug is enabled, we make sure that begin, commit and rollback
|
||||||
|
have the cache_type exclusively defined by the param using_trans.
|
||||||
|
as this is important while checking if the correct cache is used.
|
||||||
|
|
||||||
|
Note this is the only way to accurately set the type of the cache
|
||||||
|
when a begin, commit or rollback event is created because such
|
||||||
|
events may be artificially produced to compose the binary log.
|
||||||
|
*/
|
||||||
|
if (strncmp("BEGIN", query_arg, query_length) &&
|
||||||
|
strncmp("COMMIT", query_arg, query_length) &&
|
||||||
|
strncmp("ROLLBACK", query_arg, query_length))
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
switch (lex->sql_command)
|
switch (lex->sql_command)
|
||||||
{
|
{
|
||||||
case SQLCOM_DROP_TABLE:
|
case SQLCOM_DROP_TABLE:
|
||||||
|
@ -2574,6 +2590,15 @@ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg,
|
||||||
cache_type= Log_event::EVENT_TRANSACTIONAL_CACHE;
|
cache_type= Log_event::EVENT_TRANSACTIONAL_CACHE;
|
||||||
else
|
else
|
||||||
cache_type= Log_event::EVENT_STMT_CACHE;
|
cache_type= Log_event::EVENT_STMT_CACHE;
|
||||||
|
|
||||||
|
#ifndef DBUG_OFF
|
||||||
|
}
|
||||||
|
else if (using_trans)
|
||||||
|
cache_type= Log_event::EVENT_TRANSACTIONAL_CACHE;
|
||||||
|
else
|
||||||
|
cache_type= Log_event::EVENT_STMT_CACHE;
|
||||||
|
#endif
|
||||||
|
|
||||||
DBUG_ASSERT(cache_type != Log_event::EVENT_INVALID_CACHE);
|
DBUG_ASSERT(cache_type != Log_event::EVENT_INVALID_CACHE);
|
||||||
DBUG_PRINT("info",("Query_log_event has flags2: %lu sql_mode: %lu",
|
DBUG_PRINT("info",("Query_log_event has flags2: %lu sql_mode: %lu",
|
||||||
(ulong) flags2, sql_mode));
|
(ulong) flags2, sql_mode));
|
||||||
|
|
|
@ -2504,7 +2504,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 */
|
||||||
|
|
Loading…
Add table
Reference in a new issue