summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorAlfranio Correia <alfranio.correia@sun.com>2010-06-27 18:31:42 +0100
committerAlfranio Correia <alfranio.correia@sun.com>2010-06-27 18:31:42 +0100
commit77854696c4d0cab8ff56ea68e82879e87f30083c (patch)
treeedf7935a7731d766ce435c9b2ae5e40fa7416836 /sql
parent451cea3f62a1b53c441995c8e1f052875c4fb3bd (diff)
parentcdc4e9ebce32aa41cef21d2f821959d6cd08e064 (diff)
downloadmariadb-git-77854696c4d0cab8ff56ea68e82879e87f30083c.tar.gz
merge mysql-5.1-bugteam (local) --> mysql-5.1-bugteam
Diffstat (limited to 'sql')
-rw-r--r--sql/log.cc108
-rw-r--r--sql/log.h5
-rw-r--r--sql/log_event.cc6
-rw-r--r--sql/log_event_old.cc10
-rw-r--r--sql/sql_parse.cc4
5 files changed, 91 insertions, 42 deletions
diff --git a/sql/log.cc b/sql/log.cc
index 7d820b48c43..b3554d2a068 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -1510,27 +1510,23 @@ static int binlog_commit(handlerton *hton, THD *thd, bool all)
}
/*
- We commit the transaction if:
+ We flush the cache if:
- - We are not in a transaction and committing a statement, or
+ - we are committing a transaction or;
+ - no statement was committed before and just non-transactional
+ tables were updated.
- - We are in a transaction and a full transaction is committed
-
- Otherwise, we accumulate the statement
+ Otherwise, we collect the changes.
*/
- ulonglong const in_transaction=
- thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN);
DBUG_PRINT("debug",
- ("all: %d, empty: %s, in_transaction: %s, all.modified_non_trans_table: %s, stmt.modified_non_trans_table: %s",
+ ("all: %d, empty: %s, all.modified_non_trans_table: %s, stmt.modified_non_trans_table: %s",
all,
YESNO(trx_data->empty()),
- YESNO(in_transaction),
YESNO(thd->transaction.all.modified_non_trans_table),
YESNO(thd->transaction.stmt.modified_non_trans_table)));
- if (!in_transaction || all ||
- (!all && !trx_data->at_least_one_stmt_committed &&
- !stmt_has_updated_trans_table(thd) &&
- thd->transaction.stmt.modified_non_trans_table))
+ if (ending_trans(thd, all) ||
+ (trans_has_no_stmt_committed(thd, all) &&
+ !stmt_has_updated_trans_table(thd) && stmt_has_updated_non_trans_table(thd)))
{
Query_log_event qev(thd, STRING_WITH_LEN("COMMIT"), TRUE, TRUE, 0);
error= binlog_end_trans(thd, trx_data, &qev, all);
@@ -1593,7 +1589,7 @@ static int binlog_rollback(handlerton *hton, THD *thd, bool all)
On the other hand, if a statement is transactional, we just safely roll it
back.
*/
- if ((thd->transaction.stmt.modified_non_trans_table ||
+ if ((stmt_has_updated_non_trans_table(thd) ||
(thd->options & OPTION_KEEP_LOG)) &&
mysql_bin_log.check_write_error(thd))
trx_data->set_incident();
@@ -1603,19 +1599,18 @@ static int binlog_rollback(handlerton *hton, THD *thd, bool all)
{
/*
We flush the cache with a rollback, wrapped in a beging/rollback if:
- . aborting a transaction that modified a non-transactional table;
+ . aborting a transaction that modified a non-transactional table or
+ the OPTION_KEEP_LOG is activate.
. aborting a statement that modified both transactional and
non-transactional tables but which is not in the boundaries of any
transaction or there was no early change;
- . the OPTION_KEEP_LOG is activate.
*/
- if ((all && thd->transaction.all.modified_non_trans_table) ||
- (!all && thd->transaction.stmt.modified_non_trans_table &&
- !(thd->options & (OPTION_BEGIN | OPTION_NOT_AUTOCOMMIT))) ||
- (!all && thd->transaction.stmt.modified_non_trans_table &&
- !trx_data->at_least_one_stmt_committed &&
- thd->current_stmt_binlog_row_based) ||
- ((thd->options & OPTION_KEEP_LOG)))
+ if ((ending_trans(thd, all) &&
+ (trans_has_updated_non_trans_table(thd) ||
+ (thd->options & OPTION_KEEP_LOG))) ||
+ (trans_has_no_stmt_committed(thd, all) &&
+ stmt_has_updated_non_trans_table(thd) &&
+ thd->current_stmt_binlog_row_based))
{
Query_log_event qev(thd, STRING_WITH_LEN("ROLLBACK"), TRUE, TRUE, 0);
error= binlog_end_trans(thd, trx_data, &qev, all);
@@ -1624,8 +1619,8 @@ static int binlog_rollback(handlerton *hton, THD *thd, bool all)
Otherwise, we simply truncate the cache as there is no change on
non-transactional tables as follows.
*/
- else if ((all && !thd->transaction.all.modified_non_trans_table) ||
- (!all && !thd->transaction.stmt.modified_non_trans_table))
+ else if (ending_trans(thd, all) ||
+ (!(thd->options & OPTION_KEEP_LOG) && !stmt_has_updated_non_trans_table(thd)))
error= binlog_end_trans(thd, trx_data, 0, all);
}
if (!all)
@@ -1721,7 +1716,7 @@ static int binlog_savepoint_rollback(handlerton *hton, THD *thd, void *sv)
non-transactional table. Otherwise, truncate the binlog cache starting
from the SAVEPOINT command.
*/
- if (unlikely(thd->transaction.all.modified_non_trans_table ||
+ if (unlikely(trans_has_updated_non_trans_table(thd) ||
(thd->options & OPTION_KEEP_LOG)))
{
String log_query;
@@ -3934,6 +3929,67 @@ bool MYSQL_BIN_LOG::is_query_in_union(THD *thd, query_id_t query_id_param)
query_id_param >= thd->binlog_evt_union.first_query_id);
}
+/**
+ This function checks if a transaction, either a multi-statement
+ or a single statement transaction is about to commit or not.
+
+ @param thd The client thread that executed the current statement.
+ @param all Committing a transaction (i.e. TRUE) or a statement
+ (i.e. FALSE).
+ @return
+ @c true if committing a transaction, otherwise @c false.
+*/
+bool ending_trans(const THD* thd, const bool all)
+{
+ return (all || (!all && !(thd->options &
+ (OPTION_BEGIN | OPTION_NOT_AUTOCOMMIT))));
+}
+
+/**
+ This function checks if a non-transactional table was updated by
+ the current transaction.
+
+ @param thd The client thread that executed the current statement.
+ @return
+ @c true if a non-transactional table was updated, @c false
+ otherwise.
+*/
+bool trans_has_updated_non_trans_table(const THD* thd)
+{
+ return (thd->transaction.all.modified_non_trans_table ||
+ thd->transaction.stmt.modified_non_trans_table);
+}
+
+/**
+ This function checks if any statement was committed and cached.
+
+ @param thd The client thread that executed the current statement.
+ @param all Committing a transaction (i.e. TRUE) or a statement
+ (i.e. FALSE).
+ @return
+ @c true if at a statement was committed and cached, @c false
+ otherwise.
+*/
+bool trans_has_no_stmt_committed(const THD* thd, bool all)
+{
+ binlog_trx_data *const trx_data=
+ (binlog_trx_data*) thd_get_ha_data(thd, binlog_hton);
+
+ return (!all && !trx_data->at_least_one_stmt_committed);
+}
+
+/**
+ This function checks if a non-transactional table was updated by the
+ current statement.
+
+ @param thd The client thread that executed the current statement.
+ @return
+ @c true if a non-transactional table was updated, @c false otherwise.
+*/
+bool stmt_has_updated_non_trans_table(const THD* thd)
+{
+ return (thd->transaction.stmt.modified_non_trans_table);
+}
/*
These functions are placed in this file since they need access to
diff --git a/sql/log.h b/sql/log.h
index 5af51e14d80..8d3880d9171 100644
--- a/sql/log.h
+++ b/sql/log.h
@@ -20,6 +20,11 @@ class Relay_log_info;
class Format_description_log_event;
+bool ending_trans(const THD* thd, const bool all);
+bool trans_has_updated_non_trans_table(const THD* thd);
+bool trans_has_no_stmt_committed(const THD* thd, const bool all);
+bool stmt_has_updated_non_trans_table(const THD* thd);
+
/*
Transaction Coordinator log - a base abstract class
for two different implementations
diff --git a/sql/log_event.cc b/sql/log_event.cc
index cdf059b5e1f..c5bbe324ae8 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -7625,12 +7625,6 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli)
clear_all_errors(thd, const_cast<Relay_log_info*>(rli));
error= 0;
}
-
- if (!cache_stmt)
- {
- DBUG_PRINT("info", ("Marked that we need to keep log"));
- thd->options|= OPTION_KEEP_LOG;
- }
} // if (table)
/*
diff --git a/sql/log_event_old.cc b/sql/log_event_old.cc
index 8376eb6c584..202b81989a8 100644
--- a/sql/log_event_old.cc
+++ b/sql/log_event_old.cc
@@ -229,11 +229,6 @@ Old_rows_log_event::do_apply_event(Old_rows_log_event *ev, const Relay_log_info
DBUG_EXECUTE_IF("STOP_SLAVE_after_first_Rows_event",
const_cast<Relay_log_info*>(rli)->abort_slave= 1;);
error= do_after_row_operations(table, error);
- if (!ev->cache_stmt)
- {
- DBUG_PRINT("info", ("Marked that we need to keep log"));
- ev_thd->options|= OPTION_KEEP_LOG;
- }
}
/*
@@ -1775,11 +1770,6 @@ int Old_rows_log_event::do_apply_event(Relay_log_info const *rli)
DBUG_EXECUTE_IF("STOP_SLAVE_after_first_Rows_event",
const_cast<Relay_log_info*>(rli)->abort_slave= 1;);
error= do_after_row_operations(rli, error);
- if (!cache_stmt)
- {
- DBUG_PRINT("info", ("Marked that we need to keep log"));
- thd->options|= OPTION_KEEP_LOG;
- }
} // if (table)
/*
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index ec9199b33a5..1f3d29ffec0 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -2737,6 +2737,10 @@ mysql_execute_command(THD *thd)
}
}
+ /* So that CREATE TEMPORARY TABLE gets to binlog at commit/rollback */
+ if (create_info.options & HA_LEX_CREATE_TMP_TABLE)
+ thd->options|= OPTION_KEEP_LOG;
+
/*
select_create is currently not re-execution friendly and
needs to be created for every execution of a PS/SP.