Hi Alfranio,
Nice Work. I'll need a patch that I can apply before conducting my
final review. I tried to apply Libing's latest patch from
BUG#11763471 before applying yours, but that did not work out
(conflicts and once resolved bzr would still say that it needed some
other revision while merging the patch from WL#4832).
In any case, I have some comments already, please find them below.
STATUS
------
Not approved.
REQUIRED CHANGES
----------------
RC1. The patch does not apply to a latest mysql-trunk. When I try to
merge the bundle I get a message stating that the tree does not
have all the required revisions in it.
RC2. @@ -189,6 +195,12 @@ protected:
About the comment... does it mean that the cache will only
stores *only* transactional or non-transactional updates? Or
that the cache can have both types of updates?
RC3. @@ -918,8 +922,8 @@ my_bool Log_event::need_checksum()
Would you please rewrite that "ret= ..." assignement ?
I get a hard time following what's going on there...
RC4. @@ -1131,16 +1158,29 @@ public:
Perhaps I would unfold set_cache to:
- use_trans_cache()
- use_stmt_cache()
- use_no_cache() <--- you already have this one
I would rename:
- use_trans_cache() --> is_using_trans_cache()
- use_stmt_cache() --> is_using_stmt_cache()
- use_immediate_logging() --> is_using_immediate_logging()
Why ? Because use_ and set_ make everything a bit
ambiguous. One can, for instance, thing that use_* is a setter...
I think my suggestions make the code easier to read.
RC5. @@ -3895,23 +3895,9 @@ select_create::prepare(List<Item> &value
Please, remove the empty lines you've added. There may be other
places in the patch to fix.
RC6. In the commit message you have:
"DDLs go through the stmt-cache but a immediately written to the binary."
and then:
"Any Query event that requests an immediate logging such as
DDLs are tagged as EVENT_IMMEDIATE_LOGGING and EVENT_NO_CACHE"
and finally:
"Any event that does not go through a cache, such as an
Incident or a Rotate event, is tagged as
. EVENT_NO_CACHE and EVENT_IMMEDIATE_LOGGING"
This is ambiguous, do DDLs go through the STMT-cache or not?
RC7. @@ -565,10 +586,15 @@ static inline int
Please improve the comment, I find it hard to follow.
Also, if we are forcing (which is not entirely clear), why not
use a constant instead, e.g., end_evt.set_cache(FALSE) .
But then again, why not rename the set_cache to
set_stmt_cache(), or even better use_stmt_cache(). See also
comment on RC4.
The very same comment applies to hunks:
@@ -583,10 +609,15 @@ binlog_commit_flush_stmt_cache(THD *thd,
@@ -601,10 +632,15 @@ binlog_commit_flush_trx_cache(THD *thd,
RC8. In some cases, I think you could use the initializer list, see:
@@ -2358,9 +2399,12 @@ public:
@@ -2435,9 +2479,12 @@ class Rand_log_event: public Log_event
@@ -2535,11 +2582,15 @@ public:
REQUESTS
--------
R1. Would be nice to have a block diagram/workflow of the events
logging lifecycle, would that be too much to ask for? ;)
SUGGESTIONS
-----------
n/a
DETAILS
-------
n/a
On 02/04/2011 02:17 PM, Alfranio Correia wrote:
> #At
> file:///home/acorreia/workspace.oracle/repository.mysql/bzrwork/wl-4832/mysql-trunk/ based
> on revid:alfranio.correia@stripped
>
> 3564 Alfranio Correia 2011-02-04
> WL#4832
> @ mysql-test/extra/binlog_tests/binlog_cache_stat.test
> Updated test case because DDLs go through the stmt-cache before being
> flushed.
> @ mysql-test/extra/rpl_tests/rpl_binlog_max_cache_size.test
> Updated test case because DDLs go through the stmt-cache before being
> flushed.
> @ mysql-test/suite/binlog/r/binlog_mixed_cache_stat.result
> Updated test case because DDLs go through the stmt-cache before being
> flushed.
> @ mysql-test/suite/binlog/r/binlog_row_cache_stat.result
> Updated test case because DDLs go through the stmt-cache before being
> flushed.
> @ mysql-test/suite/binlog/r/binlog_stm_cache_stat.result
> Updated test case because DDLs go through the stmt-cache before being
> flushed.
> @ mysql-test/suite/rpl/r/rpl_row_binlog_max_cache_size.result
> Updated test case because DDLs go through the stmt-cache before being
> flushed.
> @ sql/binlog.cc
> The following changes were made:
>
> . "BEGIN" is appended to either the trx- or stmt-cache when a transaction
> begins.
>
> . "COMMIT/ROLLBACK" is appened to either the trx- or stmt-cache when a
> transaction ends.
>
> . DDLs go through the stmt-cache but a immediately written to the binary.
>
> . Simplified the logic that decides which cache should be used.
>
> . Merged binlog_start_trans_and_stmt() and binlog_set_stmt_begin().
> @ sql/binlog.h
> use_trans_cache was merged into Query_log_event::Query_log_event and
> created write_incident(Incident_log_event *ev, bool lock).
> @ sql/log_event.cc
> Any Query event that requests an immediate logging such as DDLs are
> tagged as EVENT_IMMEDIATE_LOGGING and EVENT_NO_CACHE. Other statements
> are tagged as EVENT_NORMAL_LOGGING.
>
> The routine that decides which cache should be used was improved by
> merging code from the binlog.cc in order to ease maintenance and
> improve supportability.
> @ sql/log_event.h
> Created two different variables to denoate when a change should go
> through a cache or not and when it should be written to the binary
> log.
>
> The first variable, event_cache_type, may assume:
>
> . EVENT_NO_CACHE
> . EVENT_STMT_CACHE
> . EVENT_TRANSACTIONAL_CACHE
>
> The variable, event_logging_type, may assume:
>
> . EVENT_NORMAL_LOGGING
> . EVENT_IMMEDIATE_LOGGING
>
> Any event that does not go through a cache, such as
> an Incident or a Rotate event, is tagged as
>
> . EVENT_NO_CACHE and EVENT_IMMEDIATE_LOGGING
> @ sql/rpl_injector.cc
> When an incident event is logged rotation is automatically forced.
> @ sql/sql_class.h
> Removed this classes from the THD as they are now local to
> the MYSQL_BIN_LOG after its improvement.
> @ sql/sql_insert.cc
> Removed this unecessary code after improving MYSQL_BIN_LOG as
> an optimized version of binlog_start_trans_and_stmt is called
> for each event if RBR is in use.
> @ sql/sql_parse.cc
> When an incident event is logged rotation is automatically forced.
>
> modified:
> mysql-test/extra/binlog_tests/binlog_cache_stat.test
> mysql-test/extra/rpl_tests/rpl_binlog_max_cache_size.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/rpl/r/rpl_row_binlog_max_cache_size.result
> sql/binlog.cc
> sql/binlog.h
> sql/log_event.cc
> sql/log_event.h
> sql/rpl_injector.cc
> sql/sql_class.h
> sql/sql_insert.cc
> sql/sql_parse.cc
> === modified file 'mysql-test/extra/binlog_tests/binlog_cache_stat.test'
> --- a/mysql-test/extra/binlog_tests/binlog_cache_stat.test 2010-11-05 17:42:37 +0000
> +++ b/mysql-test/extra/binlog_tests/binlog_cache_stat.test 2011-02-04 14:17:40 +0000
> @@ -20,13 +20,13 @@ create table t2 (a int) engine=myisam;
> #
> --echo **** Preparing the enviroment to check commit and its effect on status
> variables.
> --echo **** Expected: binlog_cache_use = 0, binlog_cache_disk_use = 0.
> ---echo **** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
> +--echo **** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
> flush status;
> let $exp_cache= 0;
> let $got_cache= query_get_value(show status like "binlog_cache_use", Value, 1);
> let $exp_disk= 0;
> let $got_disk= query_get_value(show status like "binlog_cache_disk_use", Value,
> 1);
> -let $exp_stmt_cache= 0;
> +let $exp_stmt_cache= 1;
> let $got_stmt_cache= query_get_value(show status like "binlog_stmt_cache_use",
> Value, 1);
> let $exp_stmt_disk= 0;
> let $got_stmt_disk= query_get_value(show status like "binlog_stmt_cache_disk_use",
> Value, 1);
> @@ -39,7 +39,7 @@ if (`SELECT $got_cache<> $exp_cache ||
>
> --echo **** Transactional changes which are long enough so they will be flushed to
> disk...
> --echo **** Expected: binlog_cache_use = 1, binlog_cache_disk_use = 1.
> ---echo **** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
> +--echo **** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
> let $1=2000;
> disable_query_log;
> begin;
> @@ -54,7 +54,7 @@ let $exp_cache= 1;
> let $got_cache= query_get_value(show status like "binlog_cache_use", Value, 1);
> let $exp_disk= 1;
> let $got_disk= query_get_value(show status like "binlog_cache_disk_use", Value,
> 1);
> -let $exp_stmt_cache= 0;
> +let $exp_stmt_cache= 1;
> let $got_stmt_cache= query_get_value(show status like "binlog_stmt_cache_use",
> Value, 1);
> let $exp_stmt_disk= 0;
> let $got_stmt_disk= query_get_value(show status like "binlog_stmt_cache_disk_use",
> Value, 1);
> @@ -68,7 +68,7 @@ if (`SELECT $got_cache<> $exp_cache ||
> --echo **** Transactional changes which should not be flushed to disk and so should
> not
> --echo **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
> --echo **** Expected: binlog_cache_use = 2, binlog_cache_disk_use = 1.
> ---echo **** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
> +--echo **** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
> begin;
> insert into t1 values( 1 );
> commit;
> @@ -76,7 +76,7 @@ let $exp_cache= 2;
> let $got_cache= query_get_value(show status like "binlog_cache_use", Value, 1);
> let $exp_disk= 1;
> let $got_disk= query_get_value(show status like "binlog_cache_disk_use", Value,
> 1);
> -let $exp_stmt_cache= 0;
> +let $exp_stmt_cache= 1;
> let $got_stmt_cache= query_get_value(show status like "binlog_stmt_cache_use",
> Value, 1);
> let $exp_stmt_disk= 0;
> let $got_stmt_disk= query_get_value(show status like "binlog_stmt_cache_disk_use",
> Value, 1);
> @@ -90,7 +90,7 @@ if (`SELECT $got_cache<> $exp_cache ||
> --echo **** Non-Transactional changes which should not be flushed to disk and so
> should not
> --echo **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
> --echo **** Expected: binlog_cache_use = 2, binlog_cache_disk_use = 1.
> ---echo **** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
> +--echo **** Expected: binlog_stmt_cache_use = 2, binlog_stmt_cache_disk_use = 0.
> begin;
> insert into t2 values( 1 );
> commit;
> @@ -98,7 +98,7 @@ let $exp_cache= 2;
> let $got_cache= query_get_value(show status like "binlog_cache_use", Value, 1);
> let $exp_disk= 1;
> let $got_disk= query_get_value(show status like "binlog_cache_disk_use", Value,
> 1);
> -let $exp_stmt_cache= 1;
> +let $exp_stmt_cache= 2;
> let $got_stmt_cache= query_get_value(show status like "binlog_stmt_cache_use",
> Value, 1);
> let $exp_stmt_disk= 0;
> let $got_stmt_disk= query_get_value(show status like "binlog_stmt_cache_disk_use",
> Value, 1);
> @@ -112,7 +112,7 @@ if (`SELECT $got_cache<> $exp_cache ||
> --echo **** Mixed changes which should not be flushed to disk and so should not
> --echo **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
> --echo **** Expected: binlog_cache_use = 3, binlog_cache_disk_use = 1.
> ---echo **** Expected: binlog_stmt_cache_use = 2, binlog_stmt_cache_disk_use = 0.
> +--echo **** Expected: binlog_stmt_cache_use = 3, binlog_stmt_cache_disk_use = 0.
> begin;
> insert into t1 values( 1 );
> insert into t2 values( 1 );
> @@ -121,7 +121,7 @@ let $exp_cache= 3;
> let $got_cache= query_get_value(show status like "binlog_cache_use", Value, 1);
> let $exp_disk= 1;
> let $got_disk= query_get_value(show status like "binlog_cache_disk_use", Value,
> 1);
> -let $exp_stmt_cache= 2;
> +let $exp_stmt_cache= 3;
> let $got_stmt_cache= query_get_value(show status like "binlog_stmt_cache_use",
> Value, 1);
> let $exp_stmt_disk= 0;
> let $got_stmt_disk= query_get_value(show status like "binlog_stmt_cache_disk_use",
> Value, 1);
> @@ -137,13 +137,13 @@ if (`SELECT $got_cache<> $exp_cache ||
> #
> --echo **** Preparing the enviroment to check abort and its effect on the status
> variables.
> --echo **** Expected: binlog_cache_use = 0, binlog_cache_disk_use = 0.
> ---echo **** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
> +--echo **** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
> flush status;
> let $exp_cache= 0;
> let $got_cache= query_get_value(show status like "binlog_cache_use", Value, 1);
> let $exp_disk= 0;
> let $got_disk= query_get_value(show status like "binlog_cache_disk_use", Value,
> 1);
> -let $exp_stmt_cache= 0;
> +let $exp_stmt_cache= 1;
> let $got_stmt_cache= query_get_value(show status like "binlog_stmt_cache_use",
> Value, 1);
> let $exp_stmt_disk= 0;
> let $got_stmt_disk= query_get_value(show status like "binlog_stmt_cache_disk_use",
> Value, 1);
> @@ -156,7 +156,7 @@ if (`SELECT $got_cache<> $exp_cache ||
>
> --echo **** Transactional changes which are long enough so they will be flushed to
> disk...
> --echo **** Expected: binlog_cache_use = 1, binlog_cache_disk_use = 1.
> ---echo **** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
> +--echo **** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
> let $1=2000;
> disable_query_log;
> begin;
> @@ -171,7 +171,7 @@ let $exp_cache= 1;
> let $got_cache= query_get_value(show status like "binlog_cache_use", Value, 1);
> let $exp_disk= 1;
> let $got_disk= query_get_value(show status like "binlog_cache_disk_use", Value,
> 1);
> -let $exp_stmt_cache= 0;
> +let $exp_stmt_cache= 1;
> let $got_stmt_cache= query_get_value(show status like "binlog_stmt_cache_use",
> Value, 1);
> let $exp_stmt_disk= 0;
> let $got_stmt_disk= query_get_value(show status like "binlog_stmt_cache_disk_use",
> Value, 1);
> @@ -185,7 +185,7 @@ if (`SELECT $got_cache<> $exp_cache ||
> --echo **** Transactional changes which should not be flushed to disk and so should
> not
> --echo **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
> --echo **** Expected: binlog_cache_use = 2, binlog_cache_disk_use = 1.
> ---echo **** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
> +--echo **** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
> begin;
> insert into t1 values( 1 );
> rollback;
> @@ -193,7 +193,7 @@ let $exp_cache= 2;
> let $got_cache= query_get_value(show status like "binlog_cache_use", Value, 1);
> let $exp_disk= 1;
> let $got_disk= query_get_value(show status like "binlog_cache_disk_use", Value,
> 1);
> -let $exp_stmt_cache= 0;
> +let $exp_stmt_cache= 1;
> let $got_stmt_cache= query_get_value(show status like "binlog_stmt_cache_use",
> Value, 1);
> let $exp_stmt_disk= 0;
> let $got_stmt_disk= query_get_value(show status like "binlog_stmt_cache_disk_use",
> Value, 1);
> @@ -207,7 +207,7 @@ if (`SELECT $got_cache<> $exp_cache ||
> --echo **** Non-Transactional changes which should not be flushed to disk and so
> should not
> --echo **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
> --echo **** Expected: binlog_cache_use = 2, binlog_cache_disk_use = 1.
> ---echo **** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
> +--echo **** Expected: binlog_stmt_cache_use = 2, binlog_stmt_cache_disk_use = 0.
> begin;
> insert into t2 values( 1 );
> rollback;
> @@ -215,7 +215,7 @@ let $exp_cache= 2;
> let $got_cache= query_get_value(show status like "binlog_cache_use", Value, 1);
> let $exp_disk= 1;
> let $got_disk= query_get_value(show status like "binlog_cache_disk_use", Value,
> 1);
> -let $exp_stmt_cache= 1;
> +let $exp_stmt_cache= 2;
> let $got_stmt_cache= query_get_value(show status like "binlog_stmt_cache_use",
> Value, 1);
> let $exp_stmt_disk= 0;
> let $got_stmt_disk= query_get_value(show status like "binlog_stmt_cache_disk_use",
> Value, 1);
> @@ -229,7 +229,7 @@ if (`SELECT $got_cache<> $exp_cache ||
> --echo **** Mixed changes which should not be flushed to disk and so should not
> --echo **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
> --echo **** Expected: binlog_cache_use = 3, binlog_cache_disk_use = 1.
> ---echo **** Expected: binlog_stmt_cache_use = 2, binlog_stmt_cache_disk_use = 0.
> +--echo **** Expected: binlog_stmt_cache_use = 3, binlog_stmt_cache_disk_use = 0.
> begin;
> insert into t1 values( 1 );
> insert into t2 values( 1 );
> @@ -238,7 +238,7 @@ let $exp_cache= 3;
> let $got_cache= query_get_value(show status like "binlog_cache_use", Value, 1);
> let $exp_disk= 1;
> let $got_disk= query_get_value(show status like "binlog_cache_disk_use", Value,
> 1);
> -let $exp_stmt_cache= 2;
> +let $exp_stmt_cache= 3;
> let $got_stmt_cache= query_get_value(show status like "binlog_stmt_cache_use",
> Value, 1);
> let $exp_stmt_disk= 0;
> let $got_stmt_disk= query_get_value(show status like "binlog_stmt_cache_disk_use",
> Value, 1);
>
> === modified file 'mysql-test/extra/rpl_tests/rpl_binlog_max_cache_size.test'
> --- a/mysql-test/extra/rpl_tests/rpl_binlog_max_cache_size.test 2010-12-19 17:22:30
> +0000
> +++ b/mysql-test/extra/rpl_tests/rpl_binlog_max_cache_size.test 2011-02-04 14:17:40
> +0000
> @@ -422,10 +422,6 @@ COMMIT;
>
> --connection slave
> --let $slave_sql_errno= 1197
> -if (`SELECT @@binlog_format = 'ROW'`)
> -{
> - --let $slave_sql_errno= 1534
> -}
> source include/wait_for_slave_sql_error.inc;
>
> SELECT count(*) FROM t1;
>
> === modified file 'mysql-test/suite/binlog/r/binlog_mixed_cache_stat.result'
> --- a/mysql-test/suite/binlog/r/binlog_mixed_cache_stat.result 2010-11-05 17:42:37
> +0000
> +++ b/mysql-test/suite/binlog/r/binlog_mixed_cache_stat.result 2011-02-04 14:17:40
> +0000
> @@ -3,51 +3,51 @@ create table t1 (a int) engine=innodb;
> create table t2 (a int) engine=myisam;
> **** Preparing the enviroment to check commit and its effect on status variables.
> **** Expected: binlog_cache_use = 0, binlog_cache_disk_use = 0.
> -**** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
> +**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
> flush status;
> **** Transactional changes which are long enough so they will be flushed to
> disk...
> **** Expected: binlog_cache_use = 1, binlog_cache_disk_use = 1.
> -**** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
> +**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
> **** Transactional changes which should not be flushed to disk and so should not
> **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
> **** Expected: binlog_cache_use = 2, binlog_cache_disk_use = 1.
> -**** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
> +**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
> begin;
> insert into t1 values( 1 );
> commit;
> **** Non-Transactional changes which should not be flushed to disk and so should
> not
> **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
> **** Expected: binlog_cache_use = 2, binlog_cache_disk_use = 1.
> -**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
> +**** Expected: binlog_stmt_cache_use = 2, binlog_stmt_cache_disk_use = 0.
> begin;
> insert into t2 values( 1 );
> commit;
> **** Mixed changes which should not be flushed to disk and so should not
> **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
> **** Expected: binlog_cache_use = 3, binlog_cache_disk_use = 1.
> -**** Expected: binlog_stmt_cache_use = 2, binlog_stmt_cache_disk_use = 0.
> +**** Expected: binlog_stmt_cache_use = 3, binlog_stmt_cache_disk_use = 0.
> begin;
> insert into t1 values( 1 );
> insert into t2 values( 1 );
> commit;
> **** Preparing the enviroment to check abort and its effect on the status
> variables.
> **** Expected: binlog_cache_use = 0, binlog_cache_disk_use = 0.
> -**** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
> +**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
> flush status;
> **** Transactional changes which are long enough so they will be flushed to
> disk...
> **** Expected: binlog_cache_use = 1, binlog_cache_disk_use = 1.
> -**** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
> +**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
> **** Transactional changes which should not be flushed to disk and so should not
> **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
> **** Expected: binlog_cache_use = 2, binlog_cache_disk_use = 1.
> -**** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
> +**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
> begin;
> insert into t1 values( 1 );
> rollback;
> **** Non-Transactional changes which should not be flushed to disk and so should
> not
> **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
> **** Expected: binlog_cache_use = 2, binlog_cache_disk_use = 1.
> -**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
> +**** Expected: binlog_stmt_cache_use = 2, binlog_stmt_cache_disk_use = 0.
> begin;
> insert into t2 values( 1 );
> rollback;
> @@ -56,7 +56,7 @@ Warning 1196 Some non-transactional chan
> **** Mixed changes which should not be flushed to disk and so should not
> **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
> **** Expected: binlog_cache_use = 3, binlog_cache_disk_use = 1.
> -**** Expected: binlog_stmt_cache_use = 2, binlog_stmt_cache_disk_use = 0.
> +**** Expected: binlog_stmt_cache_use = 3, binlog_stmt_cache_disk_use = 0.
> begin;
> insert into t1 values( 1 );
> insert into t2 values( 1 );
>
> === modified file 'mysql-test/suite/binlog/r/binlog_row_cache_stat.result'
> --- a/mysql-test/suite/binlog/r/binlog_row_cache_stat.result 2010-11-05 17:42:37
> +0000
> +++ b/mysql-test/suite/binlog/r/binlog_row_cache_stat.result 2011-02-04 14:17:40
> +0000
> @@ -3,51 +3,51 @@ create table t1 (a int) engine=innodb;
> create table t2 (a int) engine=myisam;
> **** Preparing the enviroment to check commit and its effect on status variables.
> **** Expected: binlog_cache_use = 0, binlog_cache_disk_use = 0.
> -**** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
> +**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
> flush status;
> **** Transactional changes which are long enough so they will be flushed to
> disk...
> **** Expected: binlog_cache_use = 1, binlog_cache_disk_use = 1.
> -**** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
> +**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
> **** Transactional changes which should not be flushed to disk and so should not
> **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
> **** Expected: binlog_cache_use = 2, binlog_cache_disk_use = 1.
> -**** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
> +**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
> begin;
> insert into t1 values( 1 );
> commit;
> **** Non-Transactional changes which should not be flushed to disk and so should
> not
> **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
> **** Expected: binlog_cache_use = 2, binlog_cache_disk_use = 1.
> -**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
> +**** Expected: binlog_stmt_cache_use = 2, binlog_stmt_cache_disk_use = 0.
> begin;
> insert into t2 values( 1 );
> commit;
> **** Mixed changes which should not be flushed to disk and so should not
> **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
> **** Expected: binlog_cache_use = 3, binlog_cache_disk_use = 1.
> -**** Expected: binlog_stmt_cache_use = 2, binlog_stmt_cache_disk_use = 0.
> +**** Expected: binlog_stmt_cache_use = 3, binlog_stmt_cache_disk_use = 0.
> begin;
> insert into t1 values( 1 );
> insert into t2 values( 1 );
> commit;
> **** Preparing the enviroment to check abort and its effect on the status
> variables.
> **** Expected: binlog_cache_use = 0, binlog_cache_disk_use = 0.
> -**** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
> +**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
> flush status;
> **** Transactional changes which are long enough so they will be flushed to
> disk...
> **** Expected: binlog_cache_use = 1, binlog_cache_disk_use = 1.
> -**** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
> +**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
> **** Transactional changes which should not be flushed to disk and so should not
> **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
> **** Expected: binlog_cache_use = 2, binlog_cache_disk_use = 1.
> -**** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
> +**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
> begin;
> insert into t1 values( 1 );
> rollback;
> **** Non-Transactional changes which should not be flushed to disk and so should
> not
> **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
> **** Expected: binlog_cache_use = 2, binlog_cache_disk_use = 1.
> -**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
> +**** Expected: binlog_stmt_cache_use = 2, binlog_stmt_cache_disk_use = 0.
> begin;
> insert into t2 values( 1 );
> rollback;
> @@ -56,7 +56,7 @@ Warning 1196 Some non-transactional chan
> **** Mixed changes which should not be flushed to disk and so should not
> **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
> **** Expected: binlog_cache_use = 3, binlog_cache_disk_use = 1.
> -**** Expected: binlog_stmt_cache_use = 2, binlog_stmt_cache_disk_use = 0.
> +**** Expected: binlog_stmt_cache_use = 3, binlog_stmt_cache_disk_use = 0.
> begin;
> insert into t1 values( 1 );
> insert into t2 values( 1 );
>
> === modified file 'mysql-test/suite/binlog/r/binlog_stm_cache_stat.result'
> --- a/mysql-test/suite/binlog/r/binlog_stm_cache_stat.result 2010-11-05 17:42:37
> +0000
> +++ b/mysql-test/suite/binlog/r/binlog_stm_cache_stat.result 2011-02-04 14:17:40
> +0000
> @@ -3,51 +3,51 @@ create table t1 (a int) engine=innodb;
> create table t2 (a int) engine=myisam;
> **** Preparing the enviroment to check commit and its effect on status variables.
> **** Expected: binlog_cache_use = 0, binlog_cache_disk_use = 0.
> -**** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
> +**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
> flush status;
> **** Transactional changes which are long enough so they will be flushed to
> disk...
> **** Expected: binlog_cache_use = 1, binlog_cache_disk_use = 1.
> -**** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
> +**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
> **** Transactional changes which should not be flushed to disk and so should not
> **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
> **** Expected: binlog_cache_use = 2, binlog_cache_disk_use = 1.
> -**** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
> +**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
> begin;
> insert into t1 values( 1 );
> commit;
> **** Non-Transactional changes which should not be flushed to disk and so should
> not
> **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
> **** Expected: binlog_cache_use = 2, binlog_cache_disk_use = 1.
> -**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
> +**** Expected: binlog_stmt_cache_use = 2, binlog_stmt_cache_disk_use = 0.
> begin;
> insert into t2 values( 1 );
> commit;
> **** Mixed changes which should not be flushed to disk and so should not
> **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
> **** Expected: binlog_cache_use = 3, binlog_cache_disk_use = 1.
> -**** Expected: binlog_stmt_cache_use = 2, binlog_stmt_cache_disk_use = 0.
> +**** Expected: binlog_stmt_cache_use = 3, binlog_stmt_cache_disk_use = 0.
> begin;
> insert into t1 values( 1 );
> insert into t2 values( 1 );
> commit;
> **** Preparing the enviroment to check abort and its effect on the status
> variables.
> **** Expected: binlog_cache_use = 0, binlog_cache_disk_use = 0.
> -**** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
> +**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
> flush status;
> **** Transactional changes which are long enough so they will be flushed to
> disk...
> **** Expected: binlog_cache_use = 1, binlog_cache_disk_use = 1.
> -**** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
> +**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
> **** Transactional changes which should not be flushed to disk and so should not
> **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
> **** Expected: binlog_cache_use = 2, binlog_cache_disk_use = 1.
> -**** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
> +**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
> begin;
> insert into t1 values( 1 );
> rollback;
> **** Non-Transactional changes which should not be flushed to disk and so should
> not
> **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
> **** Expected: binlog_cache_use = 2, binlog_cache_disk_use = 1.
> -**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
> +**** Expected: binlog_stmt_cache_use = 2, binlog_stmt_cache_disk_use = 0.
> begin;
> insert into t2 values( 1 );
> rollback;
> @@ -56,7 +56,7 @@ Warning 1196 Some non-transactional chan
> **** Mixed changes which should not be flushed to disk and so should not
> **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
> **** Expected: binlog_cache_use = 3, binlog_cache_disk_use = 1.
> -**** Expected: binlog_stmt_cache_use = 2, binlog_stmt_cache_disk_use = 0.
> +**** Expected: binlog_stmt_cache_use = 3, binlog_stmt_cache_disk_use = 0.
> begin;
> insert into t1 values( 1 );
> insert into t2 values( 1 );
>
> === modified file 'mysql-test/suite/rpl/r/rpl_row_binlog_max_cache_size.result'
> --- a/mysql-test/suite/rpl/r/rpl_row_binlog_max_cache_size.result 2010-12-19 17:22:30
> +0000
> +++ b/mysql-test/suite/rpl/r/rpl_row_binlog_max_cache_size.result 2011-02-04 14:17:40
> +0000
> @@ -149,7 +149,7 @@ SET GLOBAL binlog_stmt_cache_size= ORIGI
> BEGIN;
> Repeat statement 'INSERT INTO t1 VALUES($n, repeat("a", 32))' 128 times
> COMMIT;
> -include/wait_for_slave_sql_error.inc [errno=1534]
> +include/wait_for_slave_sql_error.inc [errno=1197]
> SELECT count(*) FROM t1;
> count(*)
> 0
>
> === modified file 'sql/binlog.cc'
> --- a/sql/binlog.cc 2011-01-05 05:21:07 +0000
> +++ b/sql/binlog.cc 2011-02-04 14:17:40 +0000
> @@ -35,6 +35,7 @@ const char *log_bin_basename= 0;
> MYSQL_BIN_LOG mysql_bin_log(&sync_binlog_period);
>
> static int binlog_init(void *p);
> +static void binlog_start_trans_and_stmt(THD *thd, Log_event *start_event);
> static int binlog_close_connection(handlerton *hton, THD *thd);
> static int binlog_savepoint_set(handlerton *hton, THD *thd, void *sv);
> static int binlog_savepoint_rollback(handlerton *hton, THD *thd, void *sv);
> @@ -85,7 +86,7 @@ class binlog_cache_data
> {
> public:
>
> - binlog_cache_data(): m_pending(0),
> + binlog_cache_data(): is_transactional(FALSE), m_pending(0),
> incident(FALSE), saved_max_binlog_cache_size(0), ptr_binlog_cache_use(0),
> ptr_binlog_cache_disk_use(0)
> { }
> @@ -121,6 +122,11 @@ public:
> return(incident);
> }
>
> + bool has_trans_updates()
> + {
> + return(is_transactional);
> + }
> +
> virtual void reset()
> {
> compute_statistics();
> @@ -189,6 +195,12 @@ protected:
> cache_log.end_of_file= saved_max_binlog_cache_size;
> }
>
> + /*
> + Defines if the cache stores transactional or non-transactional
> + updates.
> + */
> + bool is_transactional;
> +
> private:
> /*
> Pending binrows event. This event is the event where the rows are currently
> @@ -245,7 +257,9 @@ class binlog_trx_cache_data : public bin
> public:
> binlog_trx_cache_data() : m_cannot_rollback(FALSE),
> before_stmt_pos(MY_OFF_T_UNDEF)
> - {}
> + {
> + is_transactional= TRUE;
> + }
>
> void reset()
> {
> @@ -303,6 +317,9 @@ private:
> Binlog position before the start of the current statement.
> */
> my_off_t before_stmt_pos;
> +
> + binlog_trx_cache_data& operator=(const binlog_trx_cache_data& info);
> + binlog_trx_cache_data(const binlog_trx_cache_data& info);
> };
>
> class binlog_cache_mngr {
> @@ -434,8 +451,6 @@ binlog_trans_log_savepos(THD *thd, my_of
> {
> DBUG_ENTER("binlog_trans_log_savepos");
> DBUG_ASSERT(pos != NULL);
> - if (thd_get_ha_data(thd, binlog_hton) == NULL)
> - thd->binlog_setup_trx_data();
> binlog_cache_mngr *const cache_mngr=
> (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton);
> DBUG_ASSERT(mysql_bin_log.is_open());
> @@ -467,12 +482,12 @@ binlog_trans_log_truncate(THD *thd, my_o
> DBUG_PRINT("enter", ("pos: %lu", (ulong) pos));
>
> DBUG_ASSERT(thd_get_ha_data(thd, binlog_hton) != NULL);
> - /* Only true if binlog_trans_log_savepos() wasn't called before */
> DBUG_ASSERT(pos != ~(my_off_t) 0);
>
> binlog_cache_mngr *const cache_mngr=
> (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton);
> cache_mngr->trx_cache.restore_savepoint(pos);
> +
> DBUG_VOID_RETURN;
> }
>
> @@ -516,23 +531,27 @@ static int binlog_close_connection(handl
> @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
>
> @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)
> +binlog_flush_cache(THD *thd, binlog_cache_data* cache_data, Log_event *end_evt)
> {
> DBUG_ENTER("binlog_flush_cache");
> int error= 0;
>
> + DBUG_ASSERT((end_evt->use_trans_cache()&&
> cache_data->has_trans_updates()) ||
> + (!end_evt->use_trans_cache()&&
> !cache_data->has_trans_updates()));
> +
> if (!cache_data->empty())
> {
> - if (thd->binlog_flush_pending_rows_event(TRUE, is_transactional))
> + if (thd->binlog_flush_pending_rows_event(TRUE,
> cache_data->has_trans_updates()))
> + DBUG_RETURN(1);
> +
> + if (end_evt->write(&cache_data->cache_log))
> DBUG_RETURN(1);
> +
> /*
> Doing a commit or a rollback including non-transactional tables,
> i.e., ending a transaction where we might write the transaction
> @@ -543,8 +562,10 @@ binlog_flush_cache(THD *thd, binlog_cach
> 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());
> + bool prepared= (end_evt->get_type_code() == XID_EVENT);
> + error= mysql_bin_log.write(thd,&cache_data->cache_log,
> + cache_data->has_incident(),
> + prepared);
> }
> cache_data->reset();
>
> @@ -565,10 +586,15 @@ static inline int
> binlog_commit_flush_stmt_cache(THD *thd,
> binlog_cache_mngr *cache_mngr)
> {
> + binlog_cache_data* cache_data=&cache_mngr->stmt_cache;
> Query_log_event end_evt(thd, STRING_WITH_LEN("COMMIT"),
> - FALSE, TRUE, TRUE, 0);
> - return (binlog_flush_cache(thd,&cache_mngr->stmt_cache,&end_evt,
> - FALSE));
> + cache_data->has_trans_updates(), FALSE, TRUE, 0);
> + /*
> + Force the use of the stmt-cache because the current statement may
> + be something that makes Query_log_event to choose another cache.
> + */
> + end_evt.set_cache(cache_data->has_trans_updates());
> + return (binlog_flush_cache(thd, cache_data,&end_evt));
> }
>
> /**
> @@ -583,10 +609,15 @@ binlog_commit_flush_stmt_cache(THD *thd,
> static inline int
> binlog_commit_flush_trx_cache(THD *thd, binlog_cache_mngr *cache_mngr)
> {
> + binlog_cache_data* cache_data=&cache_mngr->trx_cache;
> Query_log_event end_evt(thd, STRING_WITH_LEN("COMMIT"),
> - TRUE, TRUE, TRUE, 0);
> - return (binlog_flush_cache(thd,&cache_mngr->trx_cache,&end_evt,
> - TRUE));
> + cache_data->has_trans_updates(), FALSE, TRUE, 0);
> + /*
> + Force the use of the trx-cache because the current statement may
> + be something that makes Query_log_event to choose another cache.
> + */
> + end_evt.set_cache(cache_data->has_trans_updates());
> + return (binlog_flush_cache(thd, cache_data,&end_evt));
> }
>
> /**
> @@ -601,10 +632,15 @@ binlog_commit_flush_trx_cache(THD *thd,
> static inline int
> binlog_rollback_flush_trx_cache(THD *thd, binlog_cache_mngr *cache_mngr)
> {
> + binlog_cache_data* cache_data=&cache_mngr->trx_cache;
> Query_log_event end_evt(thd, STRING_WITH_LEN("ROLLBACK"),
> - TRUE, TRUE, TRUE, 0);
> - return (binlog_flush_cache(thd,&cache_mngr->trx_cache,&end_evt,
> - TRUE));
> + cache_data->has_trans_updates(), FALSE, TRUE, 0);
> + /*
> + Force the use of the trx-cache because the current statement may
> + be something that makes Query_log_event to choose another cache.
> + */
> + end_evt.set_cache(cache_data->has_trans_updates());
> + return (binlog_flush_cache(thd, cache_data,&end_evt));
> }
>
> /**
> @@ -622,8 +658,7 @@ binlog_commit_flush_trx_cache(THD *thd,
> my_xid xid)
> {
> Xid_log_event end_evt(thd, xid);
> - return (binlog_flush_cache(thd,&cache_mngr->trx_cache,&end_evt,
> - TRUE));
> + return (binlog_flush_cache(thd,&cache_mngr->trx_cache,&end_evt));
> }
>
> /**
> @@ -643,18 +678,13 @@ binlog_truncate_trx_cache(THD *thd, binl
> {
> DBUG_ENTER("binlog_truncate_trx_cache");
> int error=0;
> - /*
> - This function handles transactional changes and as such this flag
> - equals to true.
> - */
> - bool const is_transactional= TRUE;
>
> 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);
> + thd->binlog_remove_pending_rows_event(TRUE, TRUE);
> /*
> If rolling back an entire transaction or a single statement not
> inside a transaction, we reset the transaction cache.
> @@ -675,7 +705,7 @@ binlog_truncate_trx_cache(THD *thd, binl
> else
> cache_mngr->trx_cache.restore_prev_position();
>
> - DBUG_ASSERT(thd->binlog_get_pending_rows_event(is_transactional) == NULL);
> + DBUG_ASSERT(thd->binlog_get_pending_rows_event(TRUE) == NULL);
> DBUG_RETURN(error);
> }
>
> @@ -1102,33 +1132,6 @@ stmt_has_updated_trans_table(const THD *
> return (FALSE);
> }
>
> -/**
> - This function checks if either a trx-cache or a non-trx-cache should
> - be used. If @c bin_log_direct_non_trans_update is active or the format
> - is either MIXED or ROW, the cache to be used depends on the flag @c
> - is_transactional.
> -
> - On the other hand, if binlog_format is STMT or direct option is
> - OFF, the trx-cache should be used if and only if the statement is
> - transactional or the trx-cache is not empty. Otherwise, the
> - non-trx-cache should be used.
> -
> - @param thd The client thread.
> - @param is_transactional The changes are related to a trx-table.
> - @return
> - @c true if a trx-cache should be used, @c false otherwise.
> -*/
> -bool use_trans_cache(const THD* thd, bool is_transactional)
> -{
> - binlog_cache_mngr *const cache_mngr=
> - (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton);
> -
> - return
> - ((thd->is_current_stmt_binlog_format_row() ||
> - thd->variables.binlog_direct_non_trans_update) ? is_transactional :
> - (is_transactional || !cache_mngr->trx_cache.empty()));
> -}
> -
> /**
> This function checks if a transaction, either a multi-statement
> or a single statement transaction is about to commit or not.
> @@ -3199,7 +3202,7 @@ MYSQL_BIN_LOG::remove_pending_rows_event
> DBUG_ASSERT(cache_mngr);
>
> binlog_cache_data *cache_data=
> - cache_mngr->get_binlog_cache_data(use_trans_cache(thd, is_transactional));
> + cache_mngr->get_binlog_cache_data(is_transactional);
>
> if (Rows_log_event* pending= cache_data->pending())
> {
> @@ -3236,7 +3239,7 @@ MYSQL_BIN_LOG::flush_and_set_pending_row
> DBUG_ASSERT(cache_mngr);
>
> binlog_cache_data *cache_data=
> - cache_mngr->get_binlog_cache_data(use_trans_cache(thd, is_transactional));
> + cache_mngr->get_binlog_cache_data(is_transactional);
>
> DBUG_PRINT("info", ("cache_mngr->pending(): 0x%lx", (long)
> cache_data->pending()));
>
> @@ -3318,30 +3321,16 @@ bool MYSQL_BIN_LOG::write(Log_event *eve
> DBUG_RETURN(0);
> #endif /* HAVE_REPLICATION */
>
> - IO_CACHE *file= NULL;
> - binlog_cache_mngr *cache_mngr= NULL;
> - binlog_cache_data *cache_data= 0;
> - bool is_trans_cache= FALSE;
> -
> - if (event_info->use_direct_logging())
> - {
> - file=&log_file;
> - mysql_mutex_lock(&LOCK_log);
> - }
> - else
> - {
> - if (thd->binlog_setup_trx_data())
> - goto err;
> -
> - cache_mngr= (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton);
> - is_trans_cache= use_trans_cache(thd, event_info->use_trans_cache());
> - file= cache_mngr->get_binlog_cache_log(is_trans_cache);
> - cache_data= cache_mngr->get_binlog_cache_data(is_trans_cache);
> + DBUG_ASSERT(event_info->use_trans_cache() ||
> event_info->use_stmt_cache());
> +
> + binlog_start_trans_and_stmt(thd, event_info);
>
> - thd->binlog_start_trans_and_stmt();
> - }
> + bool is_trans_cache= event_info->use_trans_cache();
> + binlog_cache_mngr *cache_mngr= (binlog_cache_mngr*) thd_get_ha_data(thd,
> binlog_hton);
> + IO_CACHE *file= cache_mngr->get_binlog_cache_log(is_trans_cache);
> + binlog_cache_data *cache_data=
> cache_mngr->get_binlog_cache_data(is_trans_cache);
> +
> DBUG_PRINT("info",("event type: %d",event_info->get_type_code()));
> -
> /*
> No check for auto events flag here - this write method should
> never be called if auto-events are enabled.
> @@ -3354,16 +3343,11 @@ bool MYSQL_BIN_LOG::write(Log_event *eve
> {
> if (!thd->is_current_stmt_binlog_format_row())
> {
> - /* three possibility for cache_type at this point */
> - DBUG_ASSERT(event_info->cache_type ==
> Log_event::EVENT_TRANSACTIONAL_CACHE ||
> - event_info->cache_type == Log_event::EVENT_STMT_CACHE ||
> - event_info->cache_type == Log_event::EVENT_NO_CACHE);
> -
> if (thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt)
> {
> Intvar_log_event e(thd,(uchar) LAST_INSERT_ID_EVENT,
>
> thd->first_successful_insert_id_in_prev_stmt_for_binlog,
> - event_info->cache_type);
> + event_info->event_cache_type,
> event_info->event_logging_type);
> if (e.write(file))
> goto err;
> }
> @@ -3374,14 +3358,16 @@ bool MYSQL_BIN_LOG::write(Log_event *eve
> nb_elements()));
> Intvar_log_event e(thd, (uchar) INSERT_ID_EVENT,
> thd->auto_inc_intervals_in_cur_stmt_for_binlog.
> - minimum(), event_info->cache_type);
> + minimum(), event_info->event_cache_type,
> + event_info->event_logging_type);
> if (e.write(file))
> goto err;
> }
> if (thd->rand_used)
> {
> Rand_log_event e(thd,thd->rand_saved_seed1,thd->rand_saved_seed2,
> - event_info->cache_type);
> + event_info->event_cache_type,
> + event_info->event_logging_type);
> if (e.write(file))
> goto err;
> }
> @@ -3403,7 +3389,8 @@ bool MYSQL_BIN_LOG::write(Log_event *eve
> user_var_event->length,
> user_var_event->type,
> user_var_event->charset_number, flags,
> - event_info->cache_type);
> + event_info->event_cache_type,
> + event_info->event_logging_type);
> if (e.write(file))
> goto err;
> }
> @@ -3420,28 +3407,18 @@ bool MYSQL_BIN_LOG::write(Log_event *eve
>
> error= 0;
>
> + /*
> + Checks if a non-transactional event was written to a trx-cache.
> + */
> if (is_trans_cache&& stmt_cannot_safely_rollback(thd))
> cache_mngr->set_trx_cache_cannot_rollback();
> err:
> - if (event_info->use_direct_logging())
> + if (event_info->use_immediate_logging())
> {
> - if (!error)
> - {
> - bool synced;
> - if ((error= flush_and_sync(&synced)))
> - goto unlock;
> -
> - if ((error= RUN_HOOK(binlog_storage, after_flush,
> - (thd, log_file_name, file->pos_in_file, synced))))
> - {
> - sql_print_error("Failed to run 'after_flush' hooks");
> - goto unlock;
> - }
> - signal_update();
> - rotate_and_purge(RP_LOCK_LOG_IS_ALREADY_LOCKED);
> - }
> -unlock:
> - mysql_mutex_unlock(&LOCK_log);
> + error |= mysql_bin_log.write(thd,&cache_data->cache_log,
> + cache_data->has_incident(),
> + FALSE);
> + cache_data->reset();
> }
>
> if (error)
> @@ -3791,7 +3768,18 @@ int MYSQL_BIN_LOG::write_cache(IO_CACHE
> return 0; // All OK
> }
>
> -bool MYSQL_BIN_LOG::write_incident(THD *thd, bool lock)
> +/**
> + Writes an incident event to the binary log.
> +
> + @param ev Incident event to be written
> + @param lock If the binary lock should be locked or not
> +
> + @retval
> + 0 error
> + @retval
> + 1 success
> +*/
> +bool MYSQL_BIN_LOG::write_incident(Incident_log_event *ev, bool lock)
> {
> uint error= 0;
> DBUG_ENTER("MYSQL_BIN_LOG::write_incident");
> @@ -3799,40 +3787,61 @@ bool MYSQL_BIN_LOG::write_incident(THD *
> if (!is_open())
> DBUG_RETURN(error);
>
> - LEX_STRING const write_error_msg=
> - { C_STRING_WITH_LEN("error writing to the binary log") };
> - Incident incident= INCIDENT_LOST_EVENTS;
> - Incident_log_event ev(thd, incident, write_error_msg);
> if (lock)
> mysql_mutex_lock(&LOCK_log);
> - error= ev.write(&log_file);
> +
> + error= ev->write(&log_file);
> +
> if (lock)
> {
> if (!error&& !(error= flush_and_sync(0)))
> {
> signal_update();
> - error= rotate_and_purge(RP_LOCK_LOG_IS_ALREADY_LOCKED);
> + error= rotate_and_purge(RP_LOCK_LOG_IS_ALREADY_LOCKED |
> + RP_FORCE_ROTATE);
> }
> mysql_mutex_unlock(&LOCK_log);
> }
> +
> DBUG_RETURN(error);
> }
>
> /**
> + Creates an incident event and writes it to the binary log.
> +
> + @param thd Thread variable
> + @param ev Incident event to be written
> + @param lock If the binary lock should be locked or not
> +
> + @retval
> + 0 error
> + @retval
> + 1 success
> +*/
> +bool MYSQL_BIN_LOG::write_incident(THD *thd, bool lock)
> +{
> + DBUG_ENTER("MYSQL_BIN_LOG::write_incident");
> +
> + if (!is_open())
> + DBUG_RETURN(0);
> +
> + LEX_STRING const write_error_msg=
> + { C_STRING_WITH_LEN("error writing to the binary log") };
> + Incident incident= INCIDENT_LOST_EVENTS;
> + Incident_log_event ev(thd, incident, write_error_msg);
> +
> + DBUG_RETURN(write_incident(&ev, lock));
> +}
> +
> +/**
> Write a cached log entry to the binary log.
> - - To support transaction over replication, we wrap the transaction
> - with BEGIN/COMMIT or BEGIN/ROLLBACK in the binary log.
> - We want to write a BEGIN/ROLLBACK block when a non-transactional table
> - was updated in a transaction which was rolled back. This is to ensure
> - that the same updates are run on the slave.
>
> - @param thd
> + @param thd Thread variable
> @param cache The cache to copy to the binlog
> - @param commit_event The commit event to print after writing the
> - contents of the cache.
> @param incident Defines if an incident event should be created to
> notify that some non-transactional changes did
> not get into the binlog.
> + @param prepared Defines if a transaction is part of a 2-PC.
>
> @note
> We only come here if there is something in the cache.
> @@ -3842,8 +3851,7 @@ bool MYSQL_BIN_LOG::write_incident(THD *
> 'cache' needs to be reinitialized after this functions returns.
> */
>
> -bool MYSQL_BIN_LOG::write(THD *thd, IO_CACHE *cache, Log_event *commit_event,
> - bool incident)
> +bool MYSQL_BIN_LOG::write(THD *thd, IO_CACHE *cache, bool incident, bool prepared)
> {
> DBUG_ENTER("MYSQL_BIN_LOG::write(THD *, IO_CACHE *, Log_event *)");
> mysql_mutex_lock(&LOCK_log);
> @@ -3857,14 +3865,6 @@ bool MYSQL_BIN_LOG::write(THD *thd, IO_C
> */
> if (my_b_tell(cache)> 0)
> {
> - /*
> - Log "BEGIN" at the beginning of every transaction. Here, a
> - transaction is either a BEGIN..COMMIT block or a single
> - statement in autocommit mode.
> - */
> - Query_log_event qinfo(thd, STRING_WITH_LEN("BEGIN"), TRUE, TRUE, TRUE, 0);
> - if (qinfo.write(&log_file))
> - goto err;
> DBUG_EXECUTE_IF("crash_before_writing_xid",
> {
> if ((write_error= write_cache(cache, false, true)))
> @@ -3877,9 +3877,6 @@ bool MYSQL_BIN_LOG::write(THD *thd, IO_C
> if ((write_error= write_cache(cache, false, false)))
> goto err;
>
> - if (commit_event&& commit_event->write(&log_file))
> - goto err;
> -
> if (incident&& write_incident(thd, FALSE))
> goto err;
>
> @@ -3913,7 +3910,7 @@ bool MYSQL_BIN_LOG::write(THD *thd, IO_C
> If the commit_event is not Xid_log_event (then it's a Query_log_event)
> rotate binlog, if necessary.
> */
> - if (commit_event&& commit_event->get_type_code() == XID_EVENT)
> + if (prepared)
> {
> mysql_mutex_lock(&LOCK_prep_xids);
> prepared_xids++;
> @@ -4322,17 +4319,12 @@ int THD::binlog_setup_trx_data()
> DBUG_RETURN(0);
> }
>
> -/*
> +/**
> Function to start a statement and optionally a transaction for the
> binary log.
>
> - SYNOPSIS
> - binlog_start_trans_and_stmt()
> -
> - DESCRIPTION
> -
> - This function does three things:
> - - Start a transaction if not in autocommit mode or if a BEGIN
> + This function does three things:
> + - Starts a transaction if not in autocommit mode or if a BEGIN
> statement has been seen.
>
> - Start a statement transaction to allow us to truncate the cache.
> @@ -4347,55 +4339,86 @@ int THD::binlog_setup_trx_data()
> we should use the first. This means that calls to this function
> can be used to start the statement before the first table map
> event, to include some extra events.
> - */
>
> -void
> -THD::binlog_start_trans_and_stmt()
> + @param thd Thread variable
> + @param start_event The first event requested to be written into the
> + binary log
> + */
> +inline void binlog_start_trans_and_stmt(THD *thd, Log_event *start_event)
> {
> - binlog_cache_mngr *cache_mngr= (binlog_cache_mngr*) thd_get_ha_data(this,
> binlog_hton);
> DBUG_ENTER("binlog_start_trans_and_stmt");
> - DBUG_PRINT("enter", ("cache_mngr: %p
> cache_mngr->trx_cache.get_prev_position(): %lu",
> - cache_mngr,
> - (cache_mngr ? (ulong)
> cache_mngr->trx_cache.get_prev_position() :
> - (ulong) 0)));
> -
> - if (cache_mngr == NULL ||
> - cache_mngr->trx_cache.get_prev_position() == MY_OFF_T_UNDEF)
> - {
> - this->binlog_set_stmt_begin();
> - if (in_multi_stmt_transaction_mode())
> - trans_register_ha(this, TRUE, binlog_hton);
> - trans_register_ha(this, FALSE, binlog_hton);
> +
> + /*
> + Initialize the cache manager if this was not done yet.
> + */
> + if (thd_get_ha_data(thd, binlog_hton) == NULL)
> + thd->binlog_setup_trx_data();
> +
> + /*
> + If the event is requesting immediatly logging, there is no need to go
> + further and set savepoint and register callbacks.
> + */
> + if (start_event->use_immediate_logging())
> + DBUG_VOID_RETURN;
> +
> + /*
> + Retrieve the appropriated cache.
> + */
> + bool is_transactional= start_event->use_trans_cache();
> + binlog_cache_mngr *cache_mngr= (binlog_cache_mngr*) thd_get_ha_data(thd,
> binlog_hton);
> + binlog_cache_data *cache= cache_mngr->get_binlog_cache_data(is_transactional);
> +
> + /*
> + If this is the first call to this funciton while processing a statement,
> + the transactional cache does not have a savepoint defined. So, in what
> + follows:
> + . an implicit savepoint is defined;
> + . callbacks are registered;
> + . binary log is set as read/write.
> +
> + The savepoint allows for truncating the trx-cache transactional changes
> + fail. Callbacks are necessary to flush caches upon committing or rolling
> + back a statement or a transaction. However, notifications do not happen
> + if the binary log is set as read/write.
> + */
> + if (cache_mngr->trx_cache.get_prev_position() == MY_OFF_T_UNDEF)
> + {
> /*
> - Mark statement transaction as read/write. We never start
> - a binary log transaction and keep it read-only,
> - therefore it's best to mark the transaction read/write just
> - at the same time we start it.
> - Not necessary to mark the normal transaction read/write
> - since the statement-level flag will be propagated automatically
> - inside ha_commit_trans.
> + Set an implicit savepoint in order to be able to truncate a trx-cache.
> */
> - ha_data[binlog_hton->slot].ha_info[0].set_trx_read_write();
> - }
> - DBUG_VOID_RETURN;
> -}
> + my_off_t pos= 0;
> + binlog_trans_log_savepos(thd,&pos);
> + cache_mngr->trx_cache.set_prev_position(pos);
>
> -void THD::binlog_set_stmt_begin() {
> - binlog_cache_mngr *cache_mngr=
> - (binlog_cache_mngr*) thd_get_ha_data(this, binlog_hton);
> + /*
> + Set callbacks in order to be able to call commmit or rollback.
> + */
> + if (thd->in_multi_stmt_transaction_mode())
> + trans_register_ha(thd, TRUE, binlog_hton);
> + trans_register_ha(thd, FALSE, binlog_hton);
> +
> + /*
> + Set the binary log as read/write otherwise callbacks are not called.
> + */
> + thd->ha_data[binlog_hton->slot].ha_info[0].set_trx_read_write();
> + }
>
> /*
> - The call to binlog_trans_log_savepos() might create the cache_mngr
> - structure, if it didn't exist before, so we save the position
> - into an auto variable and then write it into the transaction
> - data for the binary log (i.e., cache_mngr).
> - */
> - my_off_t pos= 0;
> - binlog_trans_log_savepos(this,&pos);
> - cache_mngr= (binlog_cache_mngr*) thd_get_ha_data(this, binlog_hton);
> - cache_mngr->trx_cache.set_prev_position(pos);
> -}
> + If the cache is empty log "BEGIN" at the beginning of every transaction.
> + Here, a transaction is either a BEGIN..COMMIT/ROLLBACK block or a single
> + statement in autocommit mode.
> + */
> + if (cache->empty())
> + {
> + IO_CACHE *file=
> + cache_mngr->get_binlog_cache_log(is_transactional);
> + Query_log_event qinfo(thd, STRING_WITH_LEN("BEGIN"), is_transactional, FALSE,
> TRUE, 0);
> + qinfo.set_cache(is_transactional);
> + qinfo.write(file);
> + }
>
> + DBUG_VOID_RETURN;
> +}
>
> /**
> This function writes a table map to the binary log.
> @@ -4432,14 +4455,13 @@ int THD::binlog_write_table_map(TABLE *t
> Table_map_log_event
> the_event(this, table, table->s->table_map_id, is_transactional);
>
> - if (binlog_table_maps == 0)
> - binlog_start_trans_and_stmt();
> + binlog_start_trans_and_stmt(this,&the_event);
>
> binlog_cache_mngr *const cache_mngr=
> (binlog_cache_mngr*) thd_get_ha_data(this, binlog_hton);
>
> IO_CACHE *file=
> - cache_mngr->get_binlog_cache_log(use_trans_cache(this, is_transactional));
> + cache_mngr->get_binlog_cache_log(is_transactional);
>
> if (binlog_rows_query&& this->query())
> {
> @@ -4483,7 +4505,7 @@ THD::binlog_get_pending_rows_event(bool
> if (cache_mngr)
> {
> binlog_cache_data *cache_data=
> - cache_mngr->get_binlog_cache_data(use_trans_cache(this,
> is_transactional));
> + cache_mngr->get_binlog_cache_data(is_transactional);
>
> rows= cache_data->pending();
> }
> @@ -4503,16 +4525,13 @@ THD::binlog_get_pending_rows_event(bool
> void
> THD::binlog_set_pending_rows_event(Rows_log_event* ev, bool is_transactional)
> {
> - if (thd_get_ha_data(this, binlog_hton) == NULL)
> - binlog_setup_trx_data();
> -
> binlog_cache_mngr *const cache_mngr=
> (binlog_cache_mngr*) thd_get_ha_data(this, binlog_hton);
>
> DBUG_ASSERT(cache_mngr);
>
> binlog_cache_data *cache_data=
> - cache_mngr->get_binlog_cache_data(use_trans_cache(this, is_transactional));
> + cache_mngr->get_binlog_cache_data(is_transactional);
>
> cache_data->set_pending(ev);
> }
> @@ -4936,13 +4955,6 @@ THD::binlog_prepare_pending_rows_event(T
> /* Fetch the type code for the RowsEventT template parameter */
> int const type_code= RowsEventT::TYPE_CODE;
>
> - /*
> - There is no good place to set up the transactional data, so we
> - have to do it here.
> - */
> - if (binlog_setup_trx_data())
> - DBUG_RETURN(NULL);
> -
> Rows_log_event* pending= binlog_get_pending_rows_event(is_transactional);
>
> if (unlikely(pending&& !pending->is_valid()))
>
> === modified file 'sql/binlog.h'
> --- a/sql/binlog.h 2011-01-05 05:21:07 +0000
> +++ b/sql/binlog.h 2011-02-04 14:17:40 +0000
> @@ -198,12 +198,13 @@ public:
> int new_file();
>
> bool write(Log_event* event_info); // binary log write
> - bool write(THD *thd, IO_CACHE *cache, Log_event *commit_event, bool incident);
> -
> - bool write_incident(THD *thd, bool lock);
> + bool write(THD *thd, IO_CACHE *cache, bool incident, bool prepared);
> int write_cache(IO_CACHE *cache, bool lock_log, bool flush_and_sync);
> +
> void set_write_error(THD *thd, bool is_transactional);
> bool check_write_error(THD *thd);
> + bool write_incident(THD *thd, bool lock);
> + bool write_incident(Incident_log_event *ev, bool lock);
>
> void start_union_events(THD *thd, query_id_t query_id_param);
> void stop_union_events(THD *thd);
> @@ -284,7 +285,6 @@ extern MYSQL_PLUGIN_IMPORT MYSQL_BIN_LOG
>
> bool trans_has_updated_trans_table(const THD* thd);
> bool stmt_has_updated_trans_table(const THD *thd);
> -bool use_trans_cache(const THD* thd, bool is_transactional);
> bool ending_trans(THD* thd, const bool all);
> bool ending_single_stmt_trans(THD* thd, const bool all);
> bool stmt_cannot_safely_rollback(const THD* thd);
>
> === modified file 'sql/log_event.cc'
> --- a/sql/log_event.cc 2011-01-28 14:49:41 +0000
> +++ b/sql/log_event.cc 2011-02-04 14:17:40 +0000
> @@ -684,16 +684,18 @@ const char* Log_event::get_type_str()
> #ifndef MYSQL_CLIENT
> Log_event::Log_event(THD* thd_arg, uint16 flags_arg, bool using_trans)
> :log_pos(0), temp_buf(0), exec_time(0), flags(flags_arg),
> - cache_type(Log_event::EVENT_INVALID_CACHE), crc(0), thd(thd_arg),
> - checksum_alg(BINLOG_CHECKSUM_ALG_UNDEF)
> + event_cache_type(EVENT_INVALID_CACHE),
> + event_logging_type(EVENT_INVALID_LOGGING),
> + crc(0), thd(thd_arg), checksum_alg(BINLOG_CHECKSUM_ALG_UNDEF)
> {
> server_id= thd->server_id;
> when= thd->start_time;
>
> if (using_trans)
> - cache_type= Log_event::EVENT_TRANSACTIONAL_CACHE;
> + event_cache_type= Log_event::EVENT_TRANSACTIONAL_CACHE;
> else
> - cache_type= Log_event::EVENT_STMT_CACHE;
> + event_cache_type= Log_event::EVENT_STMT_CACHE;
> + event_logging_type= Log_event::EVENT_NORMAL_LOGGING;
> }
>
> /**
> @@ -724,8 +726,10 @@ Log_event::Log_event()
>
> Log_event::Log_event(const char* buf,
> const Format_description_log_event* description_event)
> - :temp_buf(0), exec_time(0), cache_type(Log_event::EVENT_INVALID_CACHE),
> - crc(0), checksum_alg(BINLOG_CHECKSUM_ALG_UNDEF)
> + :temp_buf(0), exec_time(0),
> + event_cache_type(EVENT_INVALID_CACHE),
> + event_logging_type(EVENT_INVALID_LOGGING),
> + crc(0), checksum_alg(BINLOG_CHECKSUM_ALG_UNDEF)
> {
> #ifndef MYSQL_CLIENT
> thd = 0;
> @@ -918,8 +922,8 @@ my_bool Log_event::need_checksum()
> ret= (checksum_alg != BINLOG_CHECKSUM_ALG_UNDEF) ?
> (checksum_alg != BINLOG_CHECKSUM_ALG_OFF) :
> ((binlog_checksum_options != BINLOG_CHECKSUM_ALG_OFF)&&
> - (cache_type == Log_event::EVENT_NO_CACHE))? binlog_checksum_options :
> - FALSE;
> + (event_cache_type == Log_event::EVENT_NO_CACHE))?
> + binlog_checksum_options : FALSE;
>
> /*
> FD calls the methods before data_written has been calculated.
> @@ -959,7 +963,7 @@ my_bool Log_event::need_checksum()
> DBUG_ASSERT(((get_type_code() != ROTATE_EVENT&&
> get_type_code() != STOP_EVENT) ||
> get_type_code() != FORMAT_DESCRIPTION_EVENT) ||
> - cache_type == Log_event::EVENT_NO_CACHE);
> + event_cache_type == Log_event::EVENT_NO_CACHE);
>
> DBUG_RETURN(ret);
> }
> @@ -2688,23 +2692,20 @@ Query_log_event::Query_log_event()
> }
>
>
> -/*
> - SYNOPSIS
> - Query_log_event::Query_log_event()
> - thd_arg - thread handle
> - query_arg - array of char representing the query
> - query_length - size of the `query_arg' array
> - using_trans - there is a modified transactional table
> - suppress_use - suppress the generation of 'USE' statements
> - errcode - the error code of the query
> -
> - DESCRIPTION
> - Creates an event for binlogging
> - The value for `errcode' should be supplied by caller.
> +/**
> + Creates an event for binlogging.
> +
> + @param thd_arg Thread handle
> + @param query_arg Array of char representing the query
> + @param query_length Size of the `query_arg' array
> + @param using_trans There is a modified transactional table
> + @param immediate Should be flushed immediately
> + @param suppress_use Suppress the generation of 'USE' statements
> + @param errcode The error code of the query
> */
> Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg,
> ulong query_length, bool using_trans,
> - bool direct, bool suppress_use, int errcode)
> + bool immediate, bool suppress_use, int errcode)
>
> :Log_event(thd_arg,
> (thd_arg->thread_specific_used ? LOG_EVENT_THREAD_SPECIFIC_F :
> @@ -2804,7 +2805,8 @@ Query_log_event::Query_log_event(THD* th
> Note that a cache will not be used if the parameter direct is TRUE.
> */
> bool trx_cache= FALSE;
> - cache_type= Log_event::EVENT_INVALID_CACHE;
> + event_cache_type= Log_event::EVENT_INVALID_CACHE;
> + event_logging_type= Log_event::EVENT_INVALID_LOGGING;
>
> switch (lex->sql_command)
> {
> @@ -2831,19 +2833,29 @@ Query_log_event::Query_log_event(THD* th
> break;
> }
>
> - if (!use_cache || direct)
> + if (!use_cache || immediate)
> {
> - cache_type= Log_event::EVENT_NO_CACHE;
> + event_logging_type= Log_event::EVENT_IMMEDIATE_LOGGING;
> + event_cache_type= Log_event::EVENT_STMT_CACHE;
> }
> else if (using_trans || trx_cache || stmt_has_updated_trans_table(thd) ||
>
> thd->lex->is_mixed_stmt_unsafe(thd->in_multi_stmt_transaction_mode(),
>
> thd->variables.binlog_direct_non_trans_update,
> trans_has_updated_trans_table(thd),
> - thd->tx_isolation))
> - cache_type= Log_event::EVENT_TRANSACTIONAL_CACHE;
> + thd->tx_isolation) ||
> + (!thd->variables.binlog_direct_non_trans_update&&
> + trans_has_updated_trans_table(thd)))
> + {
> + event_logging_type= Log_event::EVENT_NORMAL_LOGGING;
> + event_cache_type= Log_event::EVENT_TRANSACTIONAL_CACHE;
> + }
> else
> - cache_type= Log_event::EVENT_STMT_CACHE;
> - DBUG_ASSERT(cache_type != Log_event::EVENT_INVALID_CACHE);
> + {
> + event_logging_type= Log_event::EVENT_NORMAL_LOGGING;
> + event_cache_type= Log_event::EVENT_STMT_CACHE;
> + }
> + DBUG_ASSERT(event_cache_type != Log_event::EVENT_INVALID_CACHE);
> + DBUG_ASSERT(event_logging_type != Log_event::EVENT_INVALID_LOGGING);
> DBUG_PRINT("info",("Query_log_event has flags2: %lu sql_mode: %llu",
> (ulong) flags2, sql_mode));
> }
> @@ -5489,7 +5501,8 @@ Rotate_log_event::Rotate_log_event(const
> DBUG_PRINT("enter",("new_log_ident: %s pos: %s flags: %lu", new_log_ident_arg,
> llstr(pos_arg, buff), (ulong) flags));
> #endif
> - cache_type= EVENT_NO_CACHE;
> + event_cache_type= EVENT_NO_CACHE;
> + event_logging_type= EVENT_IMMEDIATE_LOGGING;
> if (flags& DUP_NAME)
> new_log_ident= my_strndup(new_log_ident_arg, ident_len, MYF(MY_WME));
> if (flags& RELAY_LOG)
> @@ -7326,9 +7339,9 @@ Execute_load_query_log_event(THD *thd_ar
> ulong query_length_arg, uint fn_pos_start_arg,
> uint fn_pos_end_arg,
> enum_load_dup_handling dup_handling_arg,
> - bool using_trans, bool direct, bool suppress_use,
> + bool using_trans, bool immediate, bool suppress_use,
> int errcode):
> - Query_log_event(thd_arg, query_arg, query_length_arg, using_trans, direct,
> + Query_log_event(thd_arg, query_arg, query_length_arg, using_trans, immediate,
> suppress_use, errcode),
> file_id(thd_arg->file_id), fn_pos_start(fn_pos_start_arg),
> fn_pos_end(fn_pos_end_arg), dup_handling(dup_handling_arg)
>
> === modified file 'sql/log_event.h'
> --- a/sql/log_event.h 2011-01-11 05:13:23 +0000
> +++ b/sql/log_event.h 2011-02-04 14:17:40 +0000
> @@ -920,9 +920,10 @@ public:
> EVENT_SKIP_COUNT
> };
>
> +protected:
> enum enum_event_cache_type
> {
> - EVENT_INVALID_CACHE,
> + EVENT_INVALID_CACHE= 0,
> /*
> If possible the event should use a non-transactional cache before
> being flushed to the binary log. This means that it must be flushed
> @@ -937,15 +938,35 @@ public:
> EVENT_TRANSACTIONAL_CACHE,
> /*
> The event must be written directly to the binary log without going
> - through a cache.
> + through any cache.
> */
> EVENT_NO_CACHE,
> - /**
> + /*
> If there is a need for different types, introduce them before this.
> */
> EVENT_CACHE_COUNT
> };
>
> + enum enum_event_logging_type
> + {
> + EVENT_INVALID_LOGGING= 0,
> + /*
> + The event must be written to a cache and upon commit or rollback
> + written to the binary log.
> + */
> + EVENT_NORMAL_LOGGING,
> + /*
> + The event must be written to an empty cache and immediatly written
> + to the binary log without waiting for any other event.
> + */
> + EVENT_IMMEDIATE_LOGGING,
> + /*
> + If there is a need for different types, introduce them before this.
> + */
> + EVENT_CACHE_LOGGING_COUNT
> + };
> +
> +public:
> /*
> The following type definition is to be used whenever data is placed
> and manipulated in a common buffer. Use this typedef for buffers
> @@ -996,22 +1017,28 @@ public:
> */
> uint16 flags;
>
> - /*
> - Defines the type of the cache, if any, where the event will be
> - stored before being flushed to disk.
> - */
> - uint16 cache_type;
> -
> /**
> A storage to cache the global system variable's value.
> Handling of a separate event will be governed its member.
> */
> ulong slave_exec_mode;
>
> + /*
> + Defines the type of the cache, if any, where the event will be
> + stored before being flushed to disk.
> + */
> + uint16 event_cache_type;
> +
> + /*
> + Defines when information, i.e. event or cache will be stored into
> + disk.
> + */
> + uint16 event_logging_type;
> /**
> Placeholder for event checksum while writing to binlog.
> */
> ha_checksum crc;
> +
> #ifdef MYSQL_SERVER
> THD* thd;
>
> @@ -1131,16 +1158,29 @@ public:
> bool is_relay_log_event() const { return flags& LOG_EVENT_RELAY_LOG_F; }
> bool is_ignorable_event() const { return flags& LOG_EVENT_IGNORABLE_F; }
> inline bool use_trans_cache() const
> - {
> - return (cache_type == Log_event::EVENT_TRANSACTIONAL_CACHE);
> + {
> + return (event_cache_type == EVENT_TRANSACTIONAL_CACHE);
> }
> - inline void set_direct_logging()
> + inline bool use_stmt_cache() const
> {
> - cache_type = Log_event::EVENT_NO_CACHE;
> + return(event_cache_type == EVENT_STMT_CACHE);
> }
> - inline bool use_direct_logging()
> + inline bool use_immediate_logging() const
> {
> - return (cache_type == Log_event::EVENT_NO_CACHE);
> + return(event_logging_type == EVENT_IMMEDIATE_LOGGING);
> + }
> + inline void set_cache(bool is_transactional)
> + {
> + event_logging_type= EVENT_NORMAL_LOGGING;
> + if (is_transactional)
> + event_cache_type= EVENT_TRANSACTIONAL_CACHE;
> + else
> + event_cache_type= EVENT_STMT_CACHE;
> + }
> + inline void set_no_cache()
> + {
> + event_logging_type= EVENT_IMMEDIATE_LOGGING;
> + event_cache_type = EVENT_NO_CACHE;
> }
> Log_event(const char* buf, const Format_description_log_event
> *description_event);
> @@ -1767,7 +1807,8 @@ public:
> #ifdef MYSQL_SERVER
>
> Query_log_event(THD* thd_arg, const char* query_arg, ulong query_length,
> - bool using_trans, bool direct, bool suppress_use, int error);
> + bool using_trans, bool immediate, bool suppress_use,
> + int error);
> const char* get_db() { return db; }
> #ifdef HAVE_REPLICATION
> void pack_info(Protocol* protocol);
> @@ -2358,9 +2399,12 @@ public:
>
> #ifdef MYSQL_SERVER
> Intvar_log_event(THD* thd_arg, uchar type_arg, ulonglong val_arg,
> - uint16 cache_type_arg)
> + uint16 cache_type_arg, uint16 logging_type_arg)
> :Log_event(thd_arg, 0, 0), val(val_arg), type(type_arg)
> - { cache_type= cache_type_arg; }
> + {
> + event_cache_type= cache_type_arg;
> + event_logging_type= logging_type_arg;
> + }
> #ifdef HAVE_REPLICATION
> void pack_info(Protocol* protocol);
> #endif /* HAVE_REPLICATION */
> @@ -2435,9 +2479,12 @@ class Rand_log_event: public Log_event
>
> #ifdef MYSQL_SERVER
> Rand_log_event(THD* thd_arg, ulonglong seed1_arg, ulonglong seed2_arg,
> - uint16 cache_type_arg)
> + uint16 cache_type_arg, uint16 logging_type_arg)
> :Log_event(thd_arg, 0, 0), seed1(seed1_arg), seed2(seed2_arg)
> - { cache_type= cache_type_arg; }
> + {
> + event_cache_type= cache_type_arg;
> + event_logging_type= logging_type_arg;
> + }
> #ifdef HAVE_REPLICATION
> void pack_info(Protocol* protocol);
> #endif /* HAVE_REPLICATION */
> @@ -2482,7 +2529,7 @@ class Xid_log_event: public Log_event
>
> #ifdef MYSQL_SERVER
> Xid_log_event(THD* thd_arg, my_xid x): Log_event(thd_arg, 0, TRUE), xid(x)
> - { cache_type= EVENT_NO_CACHE; }
> + { }
> #ifdef HAVE_REPLICATION
> void pack_info(Protocol* protocol);
> #endif /* HAVE_REPLICATION */
> @@ -2535,11 +2582,15 @@ public:
> User_var_log_event(THD* thd_arg, char *name_arg, uint name_len_arg,
> char *val_arg, ulong val_len_arg, Item_result type_arg,
> uint charset_number_arg, uchar flags_arg,
> - uint16 cache_type_arg)
> + uint16 cache_type_arg, uint16 logging_type_arg)
> :Log_event(thd_arg, 0, 0), name(name_arg), name_len(name_len_arg),
> val(val_arg),
> val_len(val_len_arg), type(type_arg), charset_number(charset_number_arg),
> flags(flags_arg)
> - { is_null= !val; cache_type= cache_type_arg; }
> + {
> + is_null= !val;
> + event_cache_type= cache_type_arg;
> + event_logging_type= logging_type_arg;
> + }
> void pack_info(Protocol* protocol);
> #else
> void print(FILE* file, PRINT_EVENT_INFO* print_event_info);
> @@ -2979,7 +3030,7 @@ public:
> ulong query_length, uint fn_pos_start_arg,
> uint fn_pos_end_arg,
> enum_load_dup_handling dup_handling_arg,
> - bool using_trans, bool direct,
> + bool using_trans, bool immediate,
> bool suppress_use, int errcode);
> #ifdef HAVE_REPLICATION
> void pack_info(Protocol* protocol);
> @@ -4005,7 +4056,8 @@ public:
> DBUG_PRINT("enter", ("m_incident: %d", m_incident));
> m_message.str= NULL; /* Just as a precaution */
> m_message.length= 0;
> - set_direct_logging();
> + event_cache_type= Log_event::EVENT_NO_CACHE;
> + event_logging_type= Log_event::EVENT_IMMEDIATE_LOGGING;
> DBUG_VOID_RETURN;
> }
>
> @@ -4024,7 +4076,8 @@ public:
> }
> strmake(m_message.str, msg.str, msg.length);
> m_message.length= msg.length;
> - set_direct_logging();
> + event_cache_type= Log_event::EVENT_NO_CACHE;
> + event_logging_type= Log_event::EVENT_IMMEDIATE_LOGGING;
> DBUG_VOID_RETURN;
> }
> #endif
>
> === modified file 'sql/rpl_injector.cc'
> --- a/sql/rpl_injector.cc 2010-12-10 16:55:50 +0000
> +++ b/sql/rpl_injector.cc 2011-02-04 14:17:40 +0000
> @@ -242,15 +242,11 @@ void injector::new_trans(THD *thd, injec
> int injector::record_incident(THD *thd, Incident incident)
> {
> Incident_log_event ev(thd, incident);
> - if (int error= mysql_bin_log.write(&ev))
> - return error;
> - return mysql_bin_log.rotate_and_purge(RP_FORCE_ROTATE);
> + return (mysql_bin_log.write_incident(&ev, TRUE));
> }
>
> int injector::record_incident(THD *thd, Incident incident, LEX_STRING const
> message)
> {
> Incident_log_event ev(thd, incident, message);
> - if (int error= mysql_bin_log.write(&ev))
> - return error;
> - return mysql_bin_log.rotate_and_purge(RP_FORCE_ROTATE);
> + return (mysql_bin_log.write_incident(&ev, TRUE));
> }
>
> === modified file 'sql/sql_class.h'
> --- a/sql/sql_class.h 2011-01-28 14:49:41 +0000
> +++ b/sql/sql_class.h 2011-02-04 14:17:40 +0000
> @@ -1642,8 +1642,6 @@ public:
> /*
> Public interface to write RBR events to the binlog
> */
> - void binlog_start_trans_and_stmt();
> - void binlog_set_stmt_begin();
> int binlog_write_table_map(TABLE *table, bool is_transactional,
> bool binlog_rows_query);
> int binlog_write_row(TABLE* table, bool is_transactional,
>
> === modified file 'sql/sql_insert.cc'
> --- a/sql/sql_insert.cc 2011-01-28 14:49:41 +0000
> +++ b/sql/sql_insert.cc 2011-02-04 14:17:40 +0000
> @@ -3895,23 +3895,9 @@ select_create::prepare(List<Item> &value
>
> MY_HOOKS hooks(this, create_table, select_tables);
> hook_ptr=&hooks;
> -
> +
> unit= u;
> -
> - /*
> - Start a statement transaction before the create if we are using
> - row-based replication for the statement. If we are creating a
> - temporary table, we need to start a statement transaction.
> - */
> - if ((thd->lex->create_info.options& HA_LEX_CREATE_TMP_TABLE) ==
> 0&&
> - thd->is_current_stmt_binlog_format_row()&&
> - mysql_bin_log.is_open())
> - {
> - thd->binlog_start_trans_and_stmt();
> - }
> -
> DBUG_ASSERT(create_table->table == NULL);
> -
> DBUG_EXECUTE_IF("sleep_create_select_before_check_if_exists",
> my_sleep(6000000););
>
> if (!(table= create_table_from_items(thd, create_info, create_table,
>
> === modified file 'sql/sql_parse.cc'
> --- a/sql/sql_parse.cc 2011-01-28 14:49:41 +0000
> +++ b/sql/sql_parse.cc 2011-02-04 14:17:40 +0000
> @@ -2816,8 +2816,7 @@ end_with_restore_list:
> if (incident)
> {
> Incident_log_event ev(thd, incident);
> - (void) mysql_bin_log.write(&ev); /* error is ignored */
> - if (mysql_bin_log.rotate_and_purge(RP_FORCE_ROTATE))
> + if (mysql_bin_log.write_incident(&ev, TRUE))
> {
> res= 1;
> break;
>
>
>
>
>