List:Commits« Previous MessageNext Message »
From:Alfranio Correia Date:September 24 2010 9:34am
Subject:bzr commit into mysql-5.5-bugfixing branch (alfranio.correia:3203) Bug#56343
View as plain text  
#At file:///home/acorreia/workspace.sun/repository.mysql.new/bzrwork/bug-56343/mysql-5.5-bugfixing/ based on revid:mats.kindahl@stripped

 3203 Alfranio Correia	2010-09-24
      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.

    renamed:
      mysql-test/extra/binlog_tests/innodb_stat.test => mysql-test/extra/binlog_tests/binlog_cache_stat.test
      mysql-test/suite/binlog/r/binlog_mix_innodb_stat.result => mysql-test/suite/binlog/r/binlog_mixed_cache_stat.result
      mysql-test/suite/binlog/r/binlog_row_innodb_stat.result => mysql-test/suite/binlog/r/binlog_row_cache_stat.result
      mysql-test/suite/binlog/r/binlog_stm_innodb_stat.result => mysql-test/suite/binlog/r/binlog_stm_cache_stat.result
      mysql-test/suite/binlog/t/binlog_mix_innodb_stat.test => mysql-test/suite/binlog/t/binlog_mixed_cache_stat.test
      mysql-test/suite/binlog/t/binlog_row_innodb_stat.test => mysql-test/suite/binlog/t/binlog_row_cache_stat.test
      mysql-test/suite/binlog/t/binlog_stm_innodb_stat.test => mysql-test/suite/binlog/t/binlog_stm_cache_stat.test
    modified:
      mysql-test/suite/binlog/r/binlog_innodb.result
      sql/log.cc
      mysql-test/extra/binlog_tests/binlog_cache_stat.test
      mysql-test/suite/binlog/r/binlog_mixed_cache_stat.result
      mysql-test/suite/binlog/r/binlog_row_cache_stat.result
      mysql-test/suite/binlog/r/binlog_stm_cache_stat.result
      mysql-test/suite/binlog/t/binlog_mixed_cache_stat.test
      mysql-test/suite/binlog/t/binlog_row_cache_stat.test
      mysql-test/suite/binlog/t/binlog_stm_cache_stat.test
=== renamed file 'mysql-test/extra/binlog_tests/innodb_stat.test' => 'mysql-test/extra/binlog_tests/binlog_cache_stat.test'
--- a/mysql-test/extra/binlog_tests/innodb_stat.test	2008-09-22 19:15:52 +0000
+++ b/mysql-test/extra/binlog_tests/binlog_cache_stat.test	2010-09-24 09:34:33 +0000
@@ -2,22 +2,36 @@
 -- 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. 
+# 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";
---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...
+--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;
@@ -31,11 +45,85 @@ 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.
+--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;
-delete from t1;
+insert into t1 values( 1 );
 commit;
 show status like "binlog_cache_use";
 show status like "binlog_cache_disk_use";
-drop table t1;
+
+--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;

=== modified file 'mysql-test/suite/binlog/r/binlog_innodb.result'
--- a/mysql-test/suite/binlog/r/binlog_innodb.result	2010-06-17 13:31:51 +0000
+++ b/mysql-test/suite/binlog/r/binlog_innodb.result	2010-09-24 09:34:33 +0000
@@ -123,7 +123,7 @@ Binlog_cache_disk_use	0
 create table t1 (a int) engine=innodb;
 show status like "binlog_cache_use";
 Variable_name	Value
-Binlog_cache_use	2
+Binlog_cache_use	1
 show status like "binlog_cache_disk_use";
 Variable_name	Value
 Binlog_cache_disk_use	1
@@ -132,7 +132,7 @@ delete from t1;
 commit;
 show status like "binlog_cache_use";
 Variable_name	Value
-Binlog_cache_use	4
+Binlog_cache_use	2
 show status like "binlog_cache_disk_use";
 Variable_name	Value
 Binlog_cache_disk_use	1

=== renamed file 'mysql-test/suite/binlog/r/binlog_mix_innodb_stat.result' => 'mysql-test/suite/binlog/r/binlog_mixed_cache_stat.result'
--- a/mysql-test/suite/binlog/r/binlog_mix_innodb_stat.result	2010-01-05 16:55:23 +0000
+++ b/mysql-test/suite/binlog/r/binlog_mixed_cache_stat.result	2010-09-24 09:34:33 +0000
@@ -1,3 +1,9 @@
+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
@@ -5,21 +11,110 @@ 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;
+**** 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;
-delete from t1;
+insert into t1 values( 1 );
+insert into t2 values( 1 );
 commit;
 show status like "binlog_cache_use";
 Variable_name	Value
-Binlog_cache_use	4
+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;
+drop table t1, t2;

=== renamed file 'mysql-test/suite/binlog/r/binlog_row_innodb_stat.result' => 'mysql-test/suite/binlog/r/binlog_row_cache_stat.result'
--- a/mysql-test/suite/binlog/r/binlog_row_innodb_stat.result	2010-01-05 16:55:23 +0000
+++ b/mysql-test/suite/binlog/r/binlog_row_cache_stat.result	2010-09-24 09:34:33 +0000
@@ -1,3 +1,9 @@
+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
@@ -5,21 +11,110 @@ 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;
+**** 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;
-delete from t1;
+insert into t1 values( 1 );
+insert into t2 values( 1 );
 commit;
 show status like "binlog_cache_use";
 Variable_name	Value
-Binlog_cache_use	4
+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;
+drop table t1, t2;

=== renamed file 'mysql-test/suite/binlog/r/binlog_stm_innodb_stat.result' => 'mysql-test/suite/binlog/r/binlog_stm_cache_stat.result'
--- a/mysql-test/suite/binlog/r/binlog_stm_innodb_stat.result	2010-01-05 16:55:23 +0000
+++ b/mysql-test/suite/binlog/r/binlog_stm_cache_stat.result	2010-09-24 09:34:33 +0000
@@ -1,3 +1,9 @@
+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
@@ -5,21 +11,110 @@ 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;
+**** 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;
-delete from t1;
+insert into t1 values( 1 );
+insert into t2 values( 1 );
 commit;
 show status like "binlog_cache_use";
 Variable_name	Value
-Binlog_cache_use	4
+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;
+drop table t1, t2;

=== renamed file 'mysql-test/suite/binlog/t/binlog_mix_innodb_stat.test' => 'mysql-test/suite/binlog/t/binlog_mixed_cache_stat.test'
--- a/mysql-test/suite/binlog/t/binlog_mix_innodb_stat.test	2008-09-08 20:23:55 +0000
+++ b/mysql-test/suite/binlog/t/binlog_mixed_cache_stat.test	2010-09-24 09:34:33 +0000
@@ -2,4 +2,4 @@
 # For both statement and row based bin logs 9/19/2005 [jbm]
 
 -- source include/have_binlog_format_mixed.inc
--- source extra/binlog_tests/innodb_stat.test
+-- source extra/binlog_tests/binlog_cache_stat.test

=== renamed file 'mysql-test/suite/binlog/t/binlog_row_innodb_stat.test' => 'mysql-test/suite/binlog/t/binlog_row_cache_stat.test'
--- a/mysql-test/suite/binlog/t/binlog_row_innodb_stat.test	2007-06-27 12:28:02 +0000
+++ b/mysql-test/suite/binlog/t/binlog_row_cache_stat.test	2010-09-24 09:34:33 +0000
@@ -2,4 +2,4 @@
 # For both statement and row based bin logs 9/19/2005 [jbm]
 
 -- source include/have_binlog_format_row.inc
--- source extra/binlog_tests/innodb_stat.test
+-- source extra/binlog_tests/binlog_cache_stat.test

=== renamed file 'mysql-test/suite/binlog/t/binlog_stm_innodb_stat.test' => 'mysql-test/suite/binlog/t/binlog_stm_cache_stat.test'
--- a/mysql-test/suite/binlog/t/binlog_stm_innodb_stat.test	2008-09-08 20:23:55 +0000
+++ b/mysql-test/suite/binlog/t/binlog_stm_cache_stat.test	2010-09-24 09:34:33 +0000
@@ -2,4 +2,4 @@
 # For both statement and row based bin logs 9/19/2005 [jbm]
 
 -- source include/have_binlog_format_statement.inc
--- source extra/binlog_tests/innodb_stat.test
+-- source extra/binlog_tests/binlog_cache_stat.test

=== modified file 'sql/log.cc'
--- a/sql/log.cc	2010-09-06 17:18:44 +0000
+++ b/sql/log.cc	2010-09-24 09:34:33 +0000
@@ -262,6 +262,14 @@ public:
     incident= FALSE;
     before_stmt_pos= MY_OFF_T_UNDEF;
     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());
   }
 
@@ -1506,53 +1514,64 @@ static int binlog_close_connection(handl
 }
 
 /**
-  This function flushes a transactional cache upon commit/rollback.
+  This function computes binlog cache and disk usage.
 
-  @param thd        The thread whose transaction should be flushed
-  @param cache_mngr Pointer to the cache data to be flushed
-  @param end_ev     The end event either commit/rollback.
+  @param ptr_cache  Pointer to the cache where data is
+                    stored.
+*/
+static void binlog_compute_statistics(binlog_cache_data* ptr_cache)
+{
+  statistic_increment(binlog_cache_use, &LOCK_status);
+  if (ptr_cache->cache_log.disk_writes != 0)
+  {
+    statistic_increment(binlog_cache_disk_use, &LOCK_status);
+    ptr_cache->cache_log.disk_writes= 0;
+  }
+}
+
+/**
+  This function flushes a cache upon commit/rollback.
+
+  @param thd                The thread whose transaction should be flushed
+  @param cache_mngr         Pointer to the cache manager
+  @param end_ev             The end event either commit/rollback
+  @param is_transactional   The type of the cache: transactional or
+                            non-transactional
 
   @return
     nonzero if an error pops up when flushing the transactional cache.
 */
 static int
-binlog_flush_trx_cache(THD *thd, binlog_cache_mngr *cache_mngr,
-                       Log_event *end_ev)
+binlog_flush_cache(THD *thd, binlog_cache_mngr *cache_mngr,
+                       Log_event *end_ev, bool is_transactional)
 {
-  DBUG_ENTER("binlog_flush_trx_cache");
+  DBUG_ENTER("binlog_flush_cache");
   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);
+  binlog_cache_data* ptr_cache= (is_transactional ? &cache_mngr->trx_cache :
+                                 &cache_mngr->stmt_cache);
 
-  statistic_increment(binlog_cache_use, &LOCK_status);
-  if (cache_log->disk_writes != 0)
+  if (!ptr_cache->empty())
   {
-    statistic_increment(binlog_cache_disk_use, &LOCK_status);
-    cache_log->disk_writes= 0;
+    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, &ptr_cache->cache_log, end_ev,
+                               ptr_cache->has_incident());
+
+    binlog_compute_statistics(ptr_cache);
   }
+  cache_mngr->reset_cache(ptr_cache);
 
-  DBUG_ASSERT(cache_mngr->trx_cache.empty());
+  DBUG_ASSERT(ptr_cache->empty());
   DBUG_RETURN(error);
 }
 
@@ -1579,23 +1598,27 @@ binlog_truncate_trx_cache(THD *thd, binl
   */
   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_BEGIN),
                       all ? "all" : "stmt"));
+
+  thd->binlog_remove_pending_rows_event(TRUE, is_transactional);
   /*
     If rolling back an entire transaction or a single statement not
     inside a transaction, we reset the transaction cache.
   */
-  thd->binlog_remove_pending_rows_event(TRUE, is_transactional);
   if (ending_trans(thd, all))
   {
     if (cache_mngr->trx_cache.has_incident())
       error= mysql_bin_log.write_incident(thd, TRUE);
 
-    cache_mngr->reset_cache(&cache_mngr->trx_cache);
-
     thd->clear_binlog_table_maps();
+
+    if (!cache_mngr->trx_cache.empty())
+      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
@@ -1620,51 +1643,6 @@ static int binlog_prepare(handlerton *ht
 }
 
 /**
-  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.
 
   It has the responsibility to flush the caches to the binary log on commits.
@@ -1690,19 +1668,8 @@ static int binlog_commit(handlerton *hto
               YESNO(thd->transaction.all.modified_non_trans_table),
               YESNO(thd->transaction.stmt.modified_non_trans_table)));
 
-  if (!cache_mngr->stmt_cache.empty())
-  {
-    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);
-  }
+  Query_log_event cev(thd, STRING_WITH_LEN("COMMIT"), TRUE, FALSE, TRUE, 0);
+  binlog_flush_cache(thd, cache_mngr, &cev, FALSE);
 
   /*
     We commit the transaction if:
@@ -1711,16 +1678,14 @@ static int binlog_commit(handlerton *hto
     Otherwise, we accumulate the changes.
   */
   if (ending_trans(thd, all))
-  {
-    Query_log_event qev(thd, STRING_WITH_LEN("COMMIT"), TRUE, FALSE, TRUE, 0);
-    error= binlog_flush_trx_cache(thd, cache_mngr, &qev);
-  }
+    error= binlog_flush_cache(thd, cache_mngr, &cev, TRUE);
 
   /*
     This is part of the stmt rollback.
   */
   if (!all)
     cache_mngr->trx_cache.set_prev_position(MY_OFF_T_UNDEF);
+
   DBUG_RETURN(error);
 }
 
@@ -1757,16 +1722,8 @@ static int binlog_rollback(handlerton *h
   }
   else if (!cache_mngr->stmt_cache.empty())
   {
-    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);
+    Query_log_event cev(thd, STRING_WITH_LEN("COMMIT"), TRUE, FALSE, TRUE, 0);
+    binlog_flush_cache(thd, cache_mngr, &cev, FALSE);
   }
 
   if (mysql_bin_log.check_write_error(thd))
@@ -1807,8 +1764,8 @@ static int binlog_rollback(handlerton *h
           ending_single_stmt_trans(thd,all) &&
           thd->variables.binlog_format == BINLOG_FORMAT_MIXED)))
     {
-      Query_log_event qev(thd, STRING_WITH_LEN("ROLLBACK"), TRUE, FALSE, TRUE, 0);
-      error= binlog_flush_trx_cache(thd, cache_mngr, &qev);
+      Query_log_event rev(thd, STRING_WITH_LEN("ROLLBACK"), TRUE, FALSE, TRUE, 0);
+      error= binlog_flush_cache(thd, cache_mngr, &rev, TRUE);
     }
     /*
       Truncate the cache if:
@@ -1832,7 +1789,8 @@ static int binlog_rollback(handlerton *h
     This is part of the stmt rollback.
   */
   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);
 }
 
@@ -4177,6 +4135,7 @@ bool MYSQL_BIN_LOG::flush_and_sync(bool 
   if (synced)
     *synced= 0;
   mysql_mutex_assert_owner(&LOCK_log);
+
   if (flush_io_cache(&log_file))
     return 1;
   uint sync_period= get_sync_period();
@@ -6292,14 +6251,16 @@ int TC_LOG_BINLOG::log_xid(THD *thd, my_
 {
   DBUG_ENTER("TC_LOG_BINLOG::log");
   Xid_log_event xle(thd, xid);
+  Query_log_event cev(thd, STRING_WITH_LEN("COMMIT"), TRUE,
+                      FALSE, TRUE, 0);
   binlog_cache_mngr *cache_mngr=
     (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton);
   /*
     We always commit the entire transaction when writing an XID. Also
     note that the return value is inverted.
    */
-  DBUG_RETURN(!binlog_flush_stmt_cache(thd, cache_mngr) &&
-              !binlog_flush_trx_cache(thd, cache_mngr, &xle));
+  DBUG_RETURN(!binlog_flush_cache(thd, cache_mngr, &cev, FALSE) &&
+              !binlog_flush_cache(thd, cache_mngr, &xle, TRUE));
 }
 
 void TC_LOG_BINLOG::unlog(ulong cookie, my_xid xid)


Attachment: [text/bzr-bundle] bzr/alfranio.correia@oracle.com-20100924093433-35hohy6lmz78zmzz.bundle
Thread
bzr commit into mysql-5.5-bugfixing branch (alfranio.correia:3203) Bug#56343Alfranio Correia24 Sep