#At file:///home/acorreia/workspace.sun/repository.mysql/bzrwork/bug-40278/mysql-pe-wl2687-push/ based on revid:alfranio.correia@stripped
3519 Alfranio Correia 2009-10-04
BUG#47327 ROLLBACK TO SAVEPOINT binlogged if trx contains non-trx updates before savepoint
Draft of a patch based on the WL#2687.
modified:
sql/log.cc
=== modified file 'sql/log.cc'
--- a/sql/log.cc 2009-10-04 01:04:30 +0000
+++ b/sql/log.cc 2009-10-04 11:28:18 +0000
@@ -341,7 +341,7 @@ private:
class binlog_cache_mngr {
public:
- binlog_cache_mngr() {}
+ binlog_cache_mngr(): pos_stmt_committed(0), has_stmt_committed(FALSE) {}
void reset_cache(binlog_cache_data* cache_data)
{
@@ -358,12 +358,49 @@ public:
return (is_transactional ? &trx_cache.cache_log : &stmt_cache.cache_log);
}
+ void calc_pos_stmt_committed()
+ {
+ pos_stmt_committed= (has_stmt_committed ? pos_stmt_committed :
+ trx_cache.get_byte_position());
+ has_stmt_committed= TRUE;
+ }
+
+ void recalc_pos_stmt_committed()
+ {
+ if (has_stmt_committed)
+ {
+ my_off_t pos= trx_cache.get_byte_position();
+ has_stmt_committed= pos > pos_stmt_committed ? TRUE : FALSE;
+ pos_stmt_committed= pos > pos_stmt_committed ? pos_stmt_committed : 0;
+ }
+ }
+
+ my_off_t get_pos_stmt_committed()
+ {
+ return (pos_stmt_committed);
+ }
+
+ bool is_stmt_committed()
+ {
+ return (has_stmt_committed);
+ }
+
+ void clear_stmt_committed()
+ {
+ pos_stmt_committed= 0;
+ has_stmt_committed= FALSE;
+ }
+
binlog_cache_data stmt_cache;
binlog_cache_data trx_cache;
private:
+ my_off_t pos_stmt_committed;
+
+ bool has_stmt_committed;
+
binlog_cache_mngr& operator=(const binlog_cache_mngr& info);
binlog_cache_mngr(const binlog_cache_mngr& info);
};
@@ -2680,6 +2717,7 @@ binlog_flush_trx_cache(THD *thd, binlog_
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);
+ cache_mngr->clear_stmt_committed();
/*
We need to step the table map version after writing the
@@ -2726,7 +2764,7 @@ binlog_truncate_trx_cache(THD *thd, binl
all ? "all" : "stmt"));
/*
If rolling back an entire transaction or a single statement not
- inside a transaction, we reset the transaction cache.
+ inside a transaction, we reset the transactional cache.
*/
thd->binlog_remove_pending_rows_event(TRUE, is_transactional);
if (all || !thd->in_multi_stmt_transaction())
@@ -2735,6 +2773,7 @@ binlog_truncate_trx_cache(THD *thd, binl
error= mysql_bin_log.write_incident(thd, TRUE);
cache_mngr->reset_cache(&cache_mngr->trx_cache);
+ cache_mngr->clear_stmt_committed();
thd->clear_binlog_table_maps();
}
@@ -2743,7 +2782,10 @@ binlog_truncate_trx_cache(THD *thd, binl
transaction cache to remove the statement.
*/
else
+ {
cache_mngr->trx_cache.restore_prev_position();
+ cache_mngr->recalc_pos_stmt_committed();
+ }
/*
We need to step the table map version on a rollback to ensure that a new
@@ -2854,6 +2896,7 @@ static int binlog_commit(handlerton *hto
*/
// Alfranio
cache_mngr->reset_cache(&cache_mngr->trx_cache);
+ cache_mngr->clear_stmt_committed();
DBUG_RETURN(0);
}
@@ -2920,6 +2963,7 @@ static int binlog_rollback(handlerton *h
*/
// Alfranio
cache_mngr->reset_cache(&cache_mngr->trx_cache);
+ cache_mngr->clear_stmt_committed();
DBUG_RETURN(0);
}
@@ -2950,10 +2994,11 @@ static int binlog_rollback(handlerton *h
. the OPTION_KEEP_LOG is activate.
*/
if (thd->variables.binlog_format == BINLOG_FORMAT_STMT &&
- ((all && thd->transaction.all.modified_non_trans_table) ||
- (!all && thd->transaction.stmt.modified_non_trans_table &&
- !thd->in_multi_stmt_transaction()) ||
- (thd->options & OPTION_KEEP_LOG)))
+ ((all && thd->transaction.all.modified_non_trans_table &&
+ cache_mngr->is_stmt_committed()) ||
+ (!all && thd->transaction.stmt.modified_non_trans_table &&
+ cache_mngr->is_stmt_committed() && !thd->in_multi_stmt_transaction()) ||
+ (thd->options & OPTION_KEEP_LOG)))
{
Query_log_event qev(thd, STRING_WITH_LEN("ROLLBACK"), TRUE, TRUE, 0);
error= binlog_flush_trx_cache(thd, cache_mngr, &qev);
@@ -2964,7 +3009,7 @@ static int binlog_rollback(handlerton *h
*/
else if (all || (!all &&
(!thd->transaction.stmt.modified_non_trans_table ||
- !thd->in_multi_stmt_transaction() ||
+ !thd->in_multi_stmt_transaction() ||
thd->variables.binlog_format != BINLOG_FORMAT_STMT)))
error= binlog_truncate_trx_cache(thd, cache_mngr, all);
}
@@ -2973,7 +3018,7 @@ 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);
}
@@ -3058,12 +3103,15 @@ static int binlog_savepoint_rollback(han
{
DBUG_ENTER("binlog_savepoint_rollback");
+ binlog_cache_mngr *const cache_mngr=
+ (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton);
+
/*
Write ROLLBACK TO SAVEPOINT to the binlog cache if we have updated some
non-transactional table. Otherwise, truncate the binlog cache starting
from the SAVEPOINT command.
*/
- if (unlikely(thd->transaction.all.modified_non_trans_table ||
+ if (unlikely(cache_mngr->is_stmt_committed() ||
(thd->options & OPTION_KEEP_LOG)))
{
int errcode= query_error_code(thd, thd->killed == THD::NOT_KILLED);
@@ -6168,6 +6216,9 @@ bool MYSQL_BIN_LOG::write(Log_event *eve
{
file= &cache_mngr->trx_cache.cache_log;
cache_data= &cache_mngr->trx_cache;
+ if (thd->variables.binlog_format == BINLOG_FORMAT_STMT &&
+ thd->transaction.stmt.modified_non_trans_table)
+ cache_mngr->calc_pos_stmt_committed();
}
thd->binlog_start_trans_and_stmt();
Attachment: [text/bzr-bundle]
| Thread |
|---|
| • bzr commit into mysql-pe branch (alfranio.correia:3519) Bug#47327 | Alfranio Correia | 4 Oct |