List:Commits« Previous MessageNext Message »
From:Alfranio Correia Date:October 6 2010 8:35am
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-10-06
      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.

    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
      sql/log_event.cc
      sql/log_event.h
      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-10-06 08:34:49 +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-10-06 08:34:49 +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-10-06 08:34:49 +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-10-06 08:34:49 +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-10-06 08:34:49 +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-10-06 08:34:49 +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-10-06 08:34:49 +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-10-06 08:34:49 +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-10-06 08:34:49 +0000
@@ -210,6 +210,9 @@ class binlog_cache_data
 public:
   binlog_cache_data(): m_pending(0), before_stmt_pos(MY_OFF_T_UNDEF),
   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;
   }
@@ -262,6 +265,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());
   }
 
@@ -292,6 +303,18 @@ public:
       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.
   */
@@ -321,6 +344,13 @@ private:
   */
   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
     pending event.
@@ -1506,57 +1536,147 @@ static int binlog_close_connection(handl
 }
 
 /**
-  This function flushes a transactional cache upon commit/rollback.
-
-  @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.
+  This function computes binlog cache and disk usage.
 
-  @return
-    nonzero if an error pops up when flushing the transactional cache.
+  @param cache_data  Pointer to the cache where data is
+                     stored.
 */
-static int
-binlog_flush_trx_cache(THD *thd, binlog_cache_mngr *cache_mngr,
-                       Log_event *end_ev)
+static inline void
+binlog_compute_statistics(binlog_cache_data* cache_data)
 {
-  DBUG_ENTER("binlog_flush_trx_cache");
-  int error=0;
-  IO_CACHE *cache_log= &cache_mngr->trx_cache.cache_log;
+  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 handles transactional changes and as such
-    this flag equals to true.
-  */
-  bool const is_transactional= TRUE;
+/**
+  This function flushes a cache upon commit/rollback.
 
-  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.
+  @param thd                The thread whose transaction should be flushed
+  @param cache_data         Pointer to the cache
+  @param end_ev             The end event either commit/rollback
+  @param is_transactional   The type of the cache: transactional or
+                            non-transactional
 
-    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);
+  @return
+    nonzero if an error pops up when flushing the cache.
+*/
+static inline int
+binlog_flush_cache(THD *thd, binlog_cache_data* cache_data, Log_event *end_evt,
+                   bool is_transactional)
+{
+  DBUG_ENTER("binlog_flush_cache");
+  int error= 0;
 
-  statistic_increment(binlog_cache_use, &LOCK_status);
-  if (cache_log->disk_writes != 0)
+  if (!cache_data->empty())
   {
-    statistic_increment(binlog_cache_disk_use, &LOCK_status);
-    cache_log->disk_writes= 0;
+#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))
+      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());
   }
+  binlog_compute_statistics(cache_data);
+  cache_data->reset();
 
-  DBUG_ASSERT(cache_mngr->trx_cache.empty());
+  DBUG_ASSERT(cache_data->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));
+}
+
+/**
   This function truncates the transactional cache upon committing or rolling
   back either a transaction or a statement.
 
@@ -1579,23 +1699,26 @@ 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();
+
+    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 +1743,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 +1768,7 @@ 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);
-  }
+  binlog_commit_flush_stmt_cache(thd, cache_mngr);
 
   /*
     We commit the transaction if:
@@ -1711,16 +1777,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_commit_flush_trx_cache(thd, cache_mngr);
 
   /*
     This is part of the stmt rollback.
   */
   if (!all)
     cache_mngr->trx_cache.set_prev_position(MY_OFF_T_UNDEF);
+
   DBUG_RETURN(error);
 }
 
@@ -1755,19 +1819,8 @@ static int binlog_rollback(handlerton *h
     error= mysql_bin_log.write_incident(thd, TRUE);
     cache_mngr->reset_cache(&cache_mngr->stmt_cache);
   }
-  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);
-  }
+  else
+    binlog_commit_flush_stmt_cache(thd, cache_mngr);
 
   if (mysql_bin_log.check_write_error(thd))
   {
@@ -1796,7 +1849,6 @@ static int binlog_rollback(handlerton *h
         . the format is MIXED, non-trans table was updated and
           aborting a single statement transaction;
     */
-
     if (ending_trans(thd, all) &&
         ((thd->variables.option_bits & OPTION_KEEP_LOG) ||
          (trans_has_updated_non_trans_table(thd) &&
@@ -1806,10 +1858,7 @@ static int binlog_rollback(handlerton *h
          (trans_has_updated_non_trans_table(thd) &&
           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);
-    }
+      error= binlog_rollback_flush_trx_cache(thd, cache_mngr);
     /*
       Truncate the cache if:
         . aborting a single or multi-statement transaction or;
@@ -1832,7 +1881,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);
 }
 
@@ -4364,6 +4414,11 @@ int THD::binlog_setup_trx_data()
 
   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);
 }
 
@@ -6291,15 +6346,14 @@ void TC_LOG_BINLOG::close()
 int TC_LOG_BINLOG::log_xid(THD *thd, my_xid xid)
 {
   DBUG_ENTER("TC_LOG_BINLOG::log");
-  Xid_log_event xle(thd, xid);
   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_commit_flush_stmt_cache(thd, cache_mngr) &&
+              !binlog_commit_flush_trx_cache(thd, cache_mngr, xid));
 }
 
 void TC_LOG_BINLOG::unlog(ulong cookie, my_xid xid)

=== modified file 'sql/log_event.cc'
--- a/sql/log_event.cc	2010-08-23 22:31:12 +0000
+++ b/sql/log_event.cc	2010-10-06 08:34:49 +0000
@@ -2537,6 +2537,22 @@ Query_log_event::Query_log_event(THD* th
   bool trx_cache= FALSE;
   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)
   {
     case SQLCOM_DROP_TABLE:
@@ -2574,6 +2590,15 @@ Query_log_event::Query_log_event(THD* th
     cache_type= Log_event::EVENT_TRANSACTIONAL_CACHE;
   else
     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_PRINT("info",("Query_log_event has flags2: %lu  sql_mode: %lu",
                      (ulong) flags2, sql_mode));

=== modified file 'sql/log_event.h'
--- a/sql/log_event.h	2010-07-15 13:47:50 +0000
+++ b/sql/log_event.h	2010-10-06 08:34:49 +0000
@@ -2504,7 +2504,7 @@ class Xid_log_event: public Log_event
    my_xid xid;
 
 #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
   void pack_info(Protocol* protocol);
 #endif /* HAVE_REPLICATION */


Attachment: [text/bzr-bundle] bzr/alfranio.correia@oracle.com-20101006083449-9p236n0arpkrx1sq.bundle
Thread
bzr commit into mysql-5.5-bugfixing branch (alfranio.correia:3203) Bug#56343Alfranio Correia6 Oct
  • Re: bzr commit into mysql-5.5-bugfixing branch (alfranio.correia:3203)Bug#56343Luís Soares14 Oct
    • Re: bzr commit into mysql-5.5-bugfixing branch (alfranio.correia:3203)Bug#56343Alfranio Correia18 Oct
      • Re: bzr commit into mysql-5.5-bugfixing branch (alfranio.correia:3203)Bug#56343Luís Soares5 Nov
  • Re: bzr commit into mysql-5.5-bugfixing branch (alfranio.correia:3203)Bug#56343Alfranio Correia18 Oct