#At file:///opt/local/work/trunk-20837-1/ based on revid:kostja@stripped
3010 Konstantin Osipov 2010-05-06
Bug#20837: commit for work in progress to ease a merge.
modified:
include/mysql_com.h
sql/ha_ndbcluster.cc
sql/handler.cc
sql/log.cc
sql/log_event.cc
sql/sql_base.cc
sql/sql_cache.cc
sql/sql_class.cc
sql/sql_class.h
sql/sql_parse.cc
sql/sql_prepare.cc
sql/sql_rename.cc
sql/sql_table.cc
sql/sys_vars.cc
sql/sys_vars.h
sql/transaction.cc
=== modified file 'include/mysql_com.h'
--- a/include/mysql_com.h 2010-02-20 10:07:32 +0000
+++ b/include/mysql_com.h 2010-05-05 22:08:43 +0000
@@ -197,7 +197,14 @@ enum enum_server_command
& ~CLIENT_COMPRESS) \
& ~CLIENT_SSL_VERIFY_SERVER_CERT)
-#define SERVER_STATUS_IN_TRANS 1 /* Transaction has started */
+/**
+ Is raised when a multi-statement transaction
+ has been started, either explicitly, by means
+ of BEGIN/COMMIT AND CHAIN SQL statements, or
+ implicitly, by the first transactional
+ statement, when autocommit=off.
+*/
+#define SERVER_STATUS_IN_TRANS 1
#define SERVER_STATUS_AUTOCOMMIT 2 /* Server in auto_commit mode */
#define SERVER_MORE_RESULTS_EXISTS 8 /* Multi query - next query exists */
#define SERVER_QUERY_NO_GOOD_INDEX_USED 16
=== modified file 'sql/ha_ndbcluster.cc'
--- a/sql/ha_ndbcluster.cc 2010-03-31 14:05:33 +0000
+++ b/sql/ha_ndbcluster.cc 2010-05-05 22:08:43 +0000
@@ -4628,7 +4628,7 @@ int ha_ndbcluster::start_statement(THD *
trans_register_ha(thd, FALSE, ndbcluster_hton);
if (!thd_ndb->trans)
{
- if (thd->in_multi_stmt_transaction())
+ if (thd->in_multi_stmt_transaction_mode())
trans_register_ha(thd, TRUE, ndbcluster_hton);
DBUG_PRINT("trans",("Starting transaction"));
thd_ndb->trans= ndb->startTransaction();
@@ -4698,7 +4698,7 @@ int ha_ndbcluster::init_handler_for_stat
}
#endif
- if (thd->in_multi_stmt_transaction())
+ if (thd->in_multi_stmt_transaction_mode())
{
const void *key= m_table;
HASH_SEARCH_STATE state;
@@ -4782,7 +4782,7 @@ int ha_ndbcluster::external_lock(THD *th
if (opt_ndb_cache_check_time && m_rows_changed)
{
DBUG_PRINT("info", ("Rows has changed and util thread is running"));
- if (thd->in_multi_stmt_transaction())
+ if (thd->in_multi_stmt_transaction_mode())
{
DBUG_PRINT("info", ("Add share to list of tables to be invalidated"));
/* NOTE push_back allocates memory using transactions mem_root! */
@@ -4801,7 +4801,7 @@ int ha_ndbcluster::external_lock(THD *th
DBUG_PRINT("trans", ("Last external_lock"));
PRINT_OPTION_FLAGS(thd);
- if (!thd->in_multi_stmt_transaction())
+ if (!thd->in_multi_stmt_transaction_mode())
{
if (thd_ndb->trans)
{
@@ -4911,7 +4911,7 @@ static int ndbcluster_commit(handlerton
PRINT_OPTION_FLAGS(thd);
DBUG_PRINT("enter", ("Commit %s", (all ? "all" : "stmt")));
thd_ndb->start_stmt_count= 0;
- if (trans == NULL || (!all && thd->in_multi_stmt_transaction()))
+ if (trans == NULL || (!all && thd->in_multi_stmt_transaction_mode()))
{
/*
An odditity in the handler interface is that commit on handlerton
@@ -4981,7 +4981,7 @@ static int ndbcluster_rollback(handlerto
DBUG_ASSERT(ndb);
thd_ndb->start_stmt_count= 0;
if (trans == NULL || (!all &&
- thd->in_multi_stmt_transaction()))
+ thd->in_multi_stmt_transaction_mode()))
{
/* Ignore end-of-statement until real rollback or commit is called */
DBUG_PRINT("info", ("Rollback before start or end-of-statement only"));
@@ -8271,7 +8271,7 @@ ndbcluster_cache_retrieval_allowed(THD *
DBUG_ENTER("ndbcluster_cache_retrieval_allowed");
DBUG_PRINT("enter", ("dbname: %s, tabname: %s", dbname, tabname));
- if (thd->in_multi_stmt_transaction())
+ if (thd->in_multi_stmt_transaction_mode())
{
DBUG_PRINT("exit", ("No, don't use cache in transaction"));
DBUG_RETURN(FALSE);
@@ -8339,7 +8339,7 @@ ha_ndbcluster::register_query_cache_tabl
DBUG_ENTER("ha_ndbcluster::register_query_cache_table");
DBUG_PRINT("enter",("dbname: %s, tabname: %s", m_dbname, m_tabname));
- if (thd->in_multi_stmt_transaction())
+ if (thd->in_multi_stmt_transaction_mode())
{
DBUG_PRINT("exit", ("Can't register table during transaction"));
DBUG_RETURN(FALSE);
=== modified file 'sql/handler.cc'
--- a/sql/handler.cc 2010-04-20 08:51:50 +0000
+++ b/sql/handler.cc 2010-05-05 22:08:43 +0000
@@ -1245,7 +1245,14 @@ end:
/**
@note
This function does not care about global read lock. A caller should.
+
+ @param[in] all Is set in case of explicit commit
+ (BEGIN/COMMIT words), or implicit commit
+ issued by DDL. Is not set when called
+ at the end of statement, i.e. even
+ if autocommit=1.
*/
+
int ha_commit_one_phase(THD *thd, bool all)
{
int error=0;
@@ -1253,9 +1260,15 @@ int ha_commit_one_phase(THD *thd, bool a
/*
"real" is a nick name for a transaction for which a commit will
make persistent changes. E.g. a 'stmt' transaction inside a 'all'
- transation is not 'real': even though it's possible to commit it,
+ transaction is not 'real': even though it's possible to commit it,
the changes are not durable as they might be rolled back if the
enclosing 'all' transaction is rolled back.
+ We establish the value of 'is_real_trans' by checking
+ if it's an explicit COMMIT/BEGIN statement, or implicit
+ commit issued by DDL (all == TRUE), or if we're running
+ in autocommit mode (it's only in the autocommit mode
+ ha_commit_one_phase() can be called with an empty
+ transaction.all.ha_list, see why in trans_register_ha()).
*/
bool is_real_trans=all || thd->transaction.all.ha_list == 0;
Ha_trx_info *ha_info= trans->ha_list, *ha_info_next;
@@ -1284,7 +1297,6 @@ int ha_commit_one_phase(THD *thd, bool a
if (thd->transaction.changed_tables)
query_cache.invalidate(thd->transaction.changed_tables);
#endif
- thd->variables.tx_isolation=thd->session_tx_isolation;
}
}
/* Free resources and perform other cleanup even for 'empty' transactions. */
@@ -1306,6 +1318,12 @@ int ha_rollback_trans(THD *thd, bool all
transation is not 'real': even though it's possible to commit it,
the changes are not durable as they might be rolled back if the
enclosing 'all' transaction is rolled back.
+ We establish the value of 'is_real_trans' by checking
+ if it's an explicit COMMIT/BEGIN statement, or implicit
+ commit issued by DDL (all == TRUE), or if we're running
+ in autocommit mode (it's only in the autocommit mode
+ ha_commit_one_phase() is called with an empty
+ transaction.all.ha_list, see why in trans_register_ha()).
*/
bool is_real_trans=all || thd->transaction.all.ha_list == 0;
DBUG_ENTER("ha_rollback_trans");
@@ -1355,10 +1373,8 @@ int ha_rollback_trans(THD *thd, bool all
if (is_real_trans && thd->transaction_rollback_request &&
thd->transaction.xid_state.xa_state != XA_NOTR)
thd->transaction.xid_state.rm_error= thd->stmt_da->sql_errno();
- if (all)
- thd->variables.tx_isolation=thd->session_tx_isolation;
}
- /* Always cleanup. Even if there nht==0. There may be savepoints. */
+ /* Always cleanup. Even if nht==0. There may be savepoints. */
if (is_real_trans)
thd->transaction.cleanup();
if (all)
=== modified file 'sql/log.cc'
--- a/sql/log.cc 2010-04-20 09:10:43 +0000
+++ b/sql/log.cc 2010-05-05 22:08:43 +0000
@@ -1686,7 +1686,7 @@ static int binlog_commit(handlerton *hto
DBUG_PRINT("debug",
("all: %d, in_transaction: %s, all.modified_non_trans_table: %s, stmt.modified_non_trans_table: %s",
all,
- YESNO(thd->in_multi_stmt_transaction()),
+ YESNO(thd->in_multi_stmt_transaction_mode()),
YESNO(thd->transaction.all.modified_non_trans_table),
YESNO(thd->transaction.stmt.modified_non_trans_table)));
@@ -4267,7 +4267,7 @@ bool use_trans_cache(const THD* thd, boo
*/
bool ending_trans(THD* thd, const bool all)
{
- return (all || (!all && !thd->in_multi_stmt_transaction()));
+ return (all || (!all && !thd->in_multi_stmt_transaction_mode()));
}
/**
@@ -4370,7 +4370,7 @@ THD::binlog_start_trans_and_stmt()
cache_mngr->trx_cache.get_prev_position() == MY_OFF_T_UNDEF)
{
this->binlog_set_stmt_begin();
- if (in_multi_stmt_transaction())
+ if (in_multi_stmt_transaction_mode())
trans_register_ha(this, TRUE, binlog_hton);
trans_register_ha(this, FALSE, binlog_hton);
/*
=== modified file 'sql/log_event.cc'
--- a/sql/log_event.cc 2010-04-28 10:04:11 +0000
+++ b/sql/log_event.cc 2010-05-05 22:08:43 +0000
@@ -2485,13 +2485,13 @@ Query_log_event::Query_log_event(THD* th
implicit_commit= TRUE;
break;
case SQLCOM_DROP_TABLE:
- force_trans= lex->drop_temporary && thd->in_multi_stmt_transaction();
+ force_trans= lex->drop_temporary && thd->in_multi_stmt_transaction_mode();
implicit_commit= !force_trans;
break;
case SQLCOM_ALTER_TABLE:
case SQLCOM_CREATE_TABLE:
force_trans= (lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) &&
- thd->in_multi_stmt_transaction();
+ thd->in_multi_stmt_transaction_mode();
implicit_commit= !force_trans &&
!(lex->select_lex.item_list.elements &&
thd->is_current_stmt_binlog_format_row());
=== modified file 'sql/sql_base.cc'
--- a/sql/sql_base.cc 2010-04-28 10:04:11 +0000
+++ b/sql/sql_base.cc 2010-05-05 22:08:43 +0000
@@ -1558,7 +1558,7 @@ void close_thread_tables(THD *thd)
- If in autocommit mode, or outside a transactional context,
automatically release metadata locks of the current statement.
*/
- if (! thd->in_multi_stmt_transaction() &&
+ if (! thd->in_multi_stmt_transaction_mode() &&
! (thd->state_flags & Open_tables_state::BACKUPS_AVAIL))
{
thd->mdl_context.release_transactional_locks();
@@ -3783,7 +3783,7 @@ end_with_lock_open:
Open_table_context::Open_table_context(THD *thd, ulong timeout)
:m_action(OT_NO_ACTION),
m_start_of_statement_svp(thd->mdl_context.mdl_savepoint()),
- m_has_locks((thd->in_multi_stmt_transaction() &&
+ m_has_locks((thd->in_multi_stmt_transaction_mode() &&
thd->mdl_context.has_locks()) ||
thd->mdl_context.trans_sentinel()),
m_global_mdl_request(NULL),
=== modified file 'sql/sql_cache.cc'
--- a/sql/sql_cache.cc 2010-04-07 11:58:40 +0000
+++ b/sql/sql_cache.cc 2010-05-05 22:08:43 +0000
@@ -1177,7 +1177,7 @@ void Query_cache::store_query(THD *thd,
DBUG_ASSERT(flags.protocol_type != (unsigned int) Protocol::PROTOCOL_LOCAL);
flags.more_results_exists= test(thd->server_status &
SERVER_MORE_RESULTS_EXISTS);
- flags.in_trans= test(thd->server_status & SERVER_STATUS_IN_TRANS);
+ flags.in_trans= thd->in_active_multi_stmt_transaction();
flags.autocommit= test(thd->server_status & SERVER_STATUS_AUTOCOMMIT);
flags.pkt_nr= net->pkt_nr;
flags.character_set_client_num=
@@ -1470,7 +1470,7 @@ Query_cache::send_result_to_client(THD *
flags.protocol_type= (unsigned int) thd->protocol->type();
flags.more_results_exists= test(thd->server_status &
SERVER_MORE_RESULTS_EXISTS);
- flags.in_trans= test(thd->server_status & SERVER_STATUS_IN_TRANS);
+ flags.in_trans= thd->in_active_multi_stmt_transaction();
flags.autocommit= test(thd->server_status & SERVER_STATUS_AUTOCOMMIT);
flags.pkt_nr= thd->net.pkt_nr;
flags.character_set_client_num= thd->variables.character_set_client->number;
@@ -1541,7 +1541,7 @@ def_week_frmt: %lu, in_trans: %d, autoco
}
DBUG_PRINT("qcache", ("Query have result 0x%lx", (ulong) query));
- if (thd->in_multi_stmt_transaction() &&
+ if (thd->in_multi_stmt_transaction_mode() &&
(query->tables_type() & HA_CACHE_TBL_TRANSACT))
{
DBUG_PRINT("qcache",
@@ -1698,7 +1698,7 @@ void Query_cache::invalidate(THD *thd, T
if (is_disabled())
DBUG_VOID_RETURN;
- using_transactions= using_transactions && thd->in_multi_stmt_transaction();
+ using_transactions= using_transactions && thd->in_multi_stmt_transaction_mode();
for (; tables_used; tables_used= tables_used->next_local)
{
DBUG_ASSERT(!using_transactions || tables_used->table!=0);
@@ -1782,7 +1782,7 @@ void Query_cache::invalidate(THD *thd, T
if (is_disabled())
DBUG_VOID_RETURN;
- using_transactions= using_transactions && thd->in_multi_stmt_transaction();
+ using_transactions= using_transactions && thd->in_multi_stmt_transaction_mode();
if (using_transactions &&
(table->file->table_cache_type() == HA_CACHE_TBL_TRANSACT))
thd->add_changed_table(table);
@@ -1800,7 +1800,7 @@ void Query_cache::invalidate(THD *thd, c
if (is_disabled())
DBUG_VOID_RETURN;
- using_transactions= using_transactions && thd->in_multi_stmt_transaction();
+ using_transactions= using_transactions && thd->in_multi_stmt_transaction_mode();
if (using_transactions) // used for innodb => has_transactions() is TRUE
thd->add_changed_table(key, key_length);
else
@@ -3572,7 +3572,7 @@ Query_cache::is_cacheable(THD *thd, size
tables_type)))
DBUG_RETURN(0);
- if (thd->in_multi_stmt_transaction() &&
+ if (thd->in_multi_stmt_transaction_mode() &&
((*tables_type)&HA_CACHE_TBL_TRANSACT))
{
DBUG_PRINT("qcache", ("not in autocommin mode"));
=== modified file 'sql/sql_class.cc'
--- a/sql/sql_class.cc 2010-04-20 09:10:43 +0000
+++ b/sql/sql_class.cc 2010-05-05 22:08:43 +0000
@@ -320,7 +320,7 @@ int thd_sql_command(const THD *thd)
extern "C"
int thd_tx_isolation(const THD *thd)
{
- return (int) thd->variables.tx_isolation;
+ return (int) thd->tx_isolation;
}
extern "C"
@@ -922,7 +922,7 @@ void THD::init(void)
update_lock_default= (variables.low_priority_updates ?
TL_WRITE_LOW_PRIORITY :
TL_WRITE);
- session_tx_isolation= (enum_tx_isolation) variables.tx_isolation;
+ tx_isolation= (enum_tx_isolation) variables.tx_isolation;
update_charset();
reset_current_stmt_binlog_format_row();
bzero((char *) &status_var, sizeof(status_var));
@@ -1440,7 +1440,7 @@ void THD::add_changed_table(TABLE *table
{
DBUG_ENTER("THD::add_changed_table(table)");
- DBUG_ASSERT(in_multi_stmt_transaction() && table->file->has_transactions());
+ DBUG_ASSERT(in_multi_stmt_transaction_mode() && table->file->has_transactions());
add_changed_table(table->s->table_cache_key.str,
(long) table->s->table_cache_key.length);
DBUG_VOID_RETURN;
=== modified file 'sql/sql_class.h'
--- a/sql/sql_class.h 2010-04-20 09:10:43 +0000
+++ b/sql/sql_class.h 2010-05-05 22:08:43 +0000
@@ -2043,8 +2043,31 @@ public:
uint server_status,open_options;
enum enum_thread_type system_thread;
uint select_number; //number of select (used for EXPLAIN)
- /* variables.transaction_isolation is reset to this after each commit */
- enum_tx_isolation session_tx_isolation;
+ /*
+ Current or next transaction isolation level.
+ When a connection is established, the value is taken from
+ @@session.tx_isolation (default transaction isolation for
+ the session), which is in turn taken from @@global.tx_isolation
+ (the global value).
+ If there is no transaction started, this variable
+ holds the value of the next transaction's isolation level.
+ When a transaction starts, the value stored in this variable
+ becomes "actual".
+ At transaction commit or rollback, we assign this variable
+ again from @@session.tx_isolation.
+ The only statement that can otherwise change the value
+ of this variable is SET TRANSACTION ISOLATION LEVEL.
+ Its purpose is to effect the isolation level of the next
+ transaction in this session. When this statement is executed,
+ the value in this variable is changed. However, since
+ this statement is only allowed when there is no active
+ transaction, this assignment (naturally) only affects the
+ upcoming transaction.
+ At the end of the current active transaction the value is
+ be reset again from @@session.tx_isolation, as described
+ above.
+ */
+ enum_tx_isolation tx_isolation;
enum_check_fields count_cuted_fields;
DYNAMIC_ARRAY user_var_events; /* For user variables replication */
@@ -2304,10 +2327,6 @@ public:
{
return limit_found_rows;
}
- inline bool active_transaction()
- {
- return server_status & SERVER_STATUS_IN_TRANS;
- }
/**
Returns TRUE if session is in a multi-statement transaction mode.
@@ -2318,11 +2337,60 @@ public:
OPTION_BEGIN: Regardless of the autocommit status, a multi-statement
transaction can be explicitly started with the statements "START
TRANSACTION", "BEGIN [WORK]", "[COMMIT | ROLLBACK] AND CHAIN", etc.
+
+ Note: this doesn't tell you whether a transaction is active.
+ A session can be in multi-statement transaction mode, and yet
+ have no active transaction, e.g., in case of:
+ set @@autocommit=0;
+ set @a= 3; <-- these statements don't
+ set transaction isolation level serializable; <-- start an active
+ flush tables; <-- transaction
+
+ I.e. for the above scenario this function returns TRUE, even
+ though no active transaction has begun.
+ @sa in_active_multi_stmt_transaction()
*/
- inline bool in_multi_stmt_transaction()
+ inline bool in_multi_stmt_transaction_mode()
{
return variables.option_bits & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN);
}
+ /**
+ TRUE if the session is in a multi-statement transaction mode
+ (@sa in_multi_stmt_transaction_mode()) *and* there is an
+ active transaction, i.e. there is an explicit start of a
+ transaction with BEGIN statement, or implicit with a
+ statement that uses a transactional engine.
+
+ For example, these scenarios don't start an active transaction
+ (even though the server is in multi-statement transaction mode):
+
+ set @@autocommit=0;
+ select * from nontrans_table;
+ set @var=TRUE;
+ flush tables;
+
+ Note, that even for a statement that starts a multi-statement
+ transaction (i.e. select * from trans_table), this
+ flag won't be set until we open the statement's tables
+ and the engines register themselves for the transaction
+ (see trans_register_ha()),
+ hence this method is reliable to use only after
+ open_tables() has completed.
+
+ Why do we need a flag?
+ ---------------------------------
+ We need to maintain a (at first glance redundant)
+ session flag, rather than looking at thd->transaction.all.ha_list
+ because of explicit start of a transaction with BEGIN.
+
+ I.e. in case of
+ BEGIN;
+ select * from nontrans_t1; <-- in_active_multi_stmt_transaction() is true
+ */
+ inline bool in_active_multi_stmt_transaction()
+ {
+ return server_status & SERVER_STATUS_IN_TRANS;
+ }
inline bool fill_derived_tables()
{
return !stmt_arena->is_stmt_prepare() && !lex->only_view_structure();
=== modified file 'sql/sql_parse.cc'
--- a/sql/sql_parse.cc 2010-04-28 10:04:11 +0000
+++ b/sql/sql_parse.cc 2010-05-05 22:08:43 +0000
@@ -2765,7 +2765,7 @@ end_with_restore_list:
client thread has locked tables
*/
if (thd->locked_tables_mode ||
- thd->active_transaction() || thd->global_read_lock.is_acquired())
+ thd->in_active_multi_stmt_transaction() || thd->global_read_lock.is_acquired())
{
my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
@@ -3273,7 +3273,7 @@ end_with_restore_list:
Don't allow this within a transaction because we want to use
re-generate table
*/
- if (thd->active_transaction())
+ if (thd->in_active_multi_stmt_transaction())
{
my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
@@ -4039,8 +4039,13 @@ end_with_restore_list:
goto error;
thd->mdl_context.release_transactional_locks();
/* Begin transaction with the same isolation level. */
- if (lex->tx_chain && trans_begin(thd))
- goto error;
+ if (lex->tx_chain)
+ {
+ if (trans_begin(thd))
+ goto error;
+ }
+ else
+ thd->tx_isolation= (enum_tx_isolation) thd->variables.tx_isolation;
/* Disconnect the current client connection. */
if (lex->tx_release)
thd->killed= THD::KILL_CONNECTION;
@@ -4053,8 +4058,13 @@ end_with_restore_list:
goto error;
thd->mdl_context.release_transactional_locks();
/* Begin transaction with the same isolation level. */
- if (lex->tx_chain && trans_begin(thd))
- goto error;
+ if (lex->tx_chain)
+ {
+ if (trans_begin(thd))
+ goto error;
+ }
+ else
+ thd->tx_isolation= (enum_tx_isolation) thd->variables.tx_isolation;
/* Disconnect the current client connection. */
if (lex->tx_release)
thd->killed= THD::KILL_CONNECTION;
@@ -4561,12 +4571,22 @@ create_sp_error:
if (trans_xa_commit(thd))
goto error;
thd->mdl_context.release_transactional_locks();
+ /*
+ We've just done a commit, reset transaction
+ isolation level to the session default.
+ */
+ thd->tx_isolation= (enum_tx_isolation) thd->variables.tx_isolation;
my_ok(thd);
break;
case SQLCOM_XA_ROLLBACK:
if (trans_xa_rollback(thd))
goto error;
thd->mdl_context.release_transactional_locks();
+ /*
+ We've just done a rollback, reset transaction
+ isolation level to the session default.
+ */
+ thd->tx_isolation= (enum_tx_isolation) thd->variables.tx_isolation;
my_ok(thd);
break;
case SQLCOM_XA_RECOVER:
@@ -4711,6 +4731,9 @@ finish:
thd->global_read_lock.start_waiting_global_read_lock(thd);
}
+ DBUG_ASSERT(!thd->in_active_multi_stmt_transaction() ||
+ thd->in_multi_stmt_transaction_mode());
+
if (stmt_causes_implicit_commit(thd, CF_IMPLICIT_COMMIT_END))
{
/* If commit fails, we should be able to reset the OK status. */
@@ -5524,7 +5547,7 @@ void THD::reset_for_next_command()
OPTION_STATUS_NO_TRANS_UPDATE | OPTION_KEEP_LOG to not get warnings
in ha_rollback_trans() about some tables couldn't be rolled back.
*/
- if (!thd->in_multi_stmt_transaction())
+ if (!thd->in_multi_stmt_transaction_mode())
{
thd->variables.option_bits&= ~OPTION_KEEP_LOG;
thd->transaction.all.modified_non_trans_table= FALSE;
=== modified file 'sql/sql_prepare.cc'
--- a/sql/sql_prepare.cc 2010-04-07 11:58:40 +0000
+++ b/sql/sql_prepare.cc 2010-05-05 22:08:43 +0000
@@ -3246,7 +3246,7 @@ bool Prepared_statement::prepare(const c
locks have already been released and our savepoint points
to ticket which has been released as well.
*/
- if (thd->in_multi_stmt_transaction())
+ if (thd->in_multi_stmt_transaction_mode())
thd->mdl_context.rollback_to_savepoint(mdl_savepoint);
thd->restore_backup_statement(this, &stmt_backup);
thd->stmt_arena= old_stmt_arena;
=== modified file 'sql/sql_rename.cc'
--- a/sql/sql_rename.cc 2010-03-31 14:05:33 +0000
+++ b/sql/sql_rename.cc 2010-05-05 22:08:43 +0000
@@ -54,7 +54,7 @@ bool mysql_rename_tables(THD *thd, TABLE
if the user is trying to to do this in a transcation context
*/
- if (thd->locked_tables_mode || thd->active_transaction())
+ if (thd->locked_tables_mode || thd->in_active_multi_stmt_transaction())
{
my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
=== modified file 'sql/sql_table.cc'
--- a/sql/sql_table.cc 2010-04-28 10:04:11 +0000
+++ b/sql/sql_table.cc 2010-05-05 22:08:43 +0000
@@ -6559,7 +6559,7 @@ bool mysql_alter_table(THD *thd,char *ne
if the user is trying to to do this in a transcation context
*/
- if (thd->locked_tables_mode || thd->active_transaction())
+ if (thd->locked_tables_mode || thd->in_active_multi_stmt_transaction())
{
my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
=== modified file 'sql/sys_vars.cc'
--- a/sql/sys_vars.cc 2010-04-20 08:51:50 +0000
+++ b/sql/sys_vars.cc 2010-05-05 22:08:43 +0000
@@ -295,7 +295,7 @@ static bool binlog_format_check(sys_var
/*
Make the session variable 'binlog_format' read-only inside a transaction.
*/
- if (thd->active_transaction())
+ if (thd->in_active_multi_stmt_transaction())
{
my_error(ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_FORMAT, MYF(0));
return true;
@@ -348,7 +348,7 @@ static bool binlog_direct_check(sys_var
Makes the session variable 'binlog_direct_non_transactional_updates'
read-only inside a transaction.
*/
- if (thd->active_transaction())
+ if (thd->in_active_multi_stmt_transaction())
{
my_error(ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_DIRECT, MYF(0));
return true;
@@ -1428,7 +1428,7 @@ static my_bool read_only;
static bool check_read_only(sys_var *self, THD *thd, set_var *var)
{
/* Prevent self dead-lock */
- if (thd->locked_tables_mode || thd->active_transaction())
+ if (thd->locked_tables_mode || thd->in_active_multi_stmt_transaction())
{
my_error(ER_LOCK_OR_ACTIVE_TRANSACTION, MYF(0));
return true;
@@ -2006,34 +2006,41 @@ static Sys_var_ulong Sys_thread_pool_siz
VALID_RANGE(1, 16384), DEFAULT(20), BLOCK_SIZE(0));
#endif
-// Can't change the 'next' tx_isolation if we are already in a transaction
+/**
+ Can't change the 'next' tx_isolation if we are already in a
+ transaction.
+*/
+
static bool check_tx_isolation(sys_var *self, THD *thd, set_var *var)
{
- if (var->type == OPT_DEFAULT && (thd->server_status & SERVER_STATUS_IN_TRANS))
+ if (var->type == OPT_DEFAULT && thd->in_active_multi_stmt_transaction())
{
+ DBUG_ASSERT(thd->in_multi_stmt_transaction_mode());
my_error(ER_CANT_CHANGE_TX_ISOLATION, MYF(0));
- return true;
+ return TRUE;
}
- return false;
+ return FALSE;
}
-/*
- If one doesn't use the SESSION modifier, the isolation level
- is only active for the next command.
-*/
-static bool fix_tx_isolation(sys_var *self, THD *thd, enum_var_type type)
+
+bool Sys_var_tx_isolation::session_update(THD *thd, set_var *var)
{
- if (type == OPT_SESSION)
- thd->session_tx_isolation= (enum_tx_isolation)thd->variables.tx_isolation;
- return false;
+ if (var->type == OPT_DEFAULT)
+ {
+ thd->tx_isolation= (enum_tx_isolation) var->save_result.ulonglong_value;
+ return FALSE;
+ }
+ else
+ return Sys_var_enum::session_update(thd, var);
}
+
+
// NO_CMD_LINE - different name of the option
-static Sys_var_enum Sys_tx_isolation(
+static Sys_var_tx_isolation Sys_tx_isolation(
"tx_isolation", "Default transaction isolation level",
SESSION_VAR(tx_isolation), NO_CMD_LINE,
tx_isolation_names, DEFAULT(ISO_REPEATABLE_READ),
- NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(check_tx_isolation),
- ON_UPDATE(fix_tx_isolation));
+ NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(check_tx_isolation));
static Sys_var_ulonglong Sys_tmp_table_size(
"tmp_table_size",
=== modified file 'sql/sys_vars.h'
--- a/sql/sys_vars.h 2010-03-31 14:05:33 +0000
+++ b/sql/sys_vars.h 2010-05-05 22:08:43 +0000
@@ -1599,6 +1599,22 @@ public:
{ return type != STRING_RESULT; }
};
+
+class Sys_var_tx_isolation: public Sys_var_enum
+{
+public:
+ Sys_var_tx_isolation(const char *name_arg,
+ const char *comment, int flag_args, ptrdiff_t off, size_t size,
+ CMD_LINE getopt,
+ const char *values[], uint def_val, PolyLock *lock,
+ enum binlog_status_enum binlog_status_arg,
+ on_check_function on_check_func)
+ :Sys_var_enum(name_arg, comment, flag_args, off, size, getopt,
+ values, def_val, lock, binlog_status_arg, on_check_func)
+ {}
+ virtual bool session_update(THD *thd, set_var *var);
+};
+
/****************************************************************************
Used templates
****************************************************************************/
=== modified file 'sql/transaction.cc'
--- a/sql/transaction.cc 2010-03-31 14:05:33 +0000
+++ b/sql/transaction.cc 2010-05-05 22:08:43 +0000
@@ -169,7 +169,7 @@ bool trans_commit_implicit(THD *thd)
if (trans_check(thd))
DBUG_RETURN(TRUE);
- if (thd->in_multi_stmt_transaction() ||
+ if (thd->in_multi_stmt_transaction_mode() ||
(thd->variables.option_bits & OPTION_TABLE_LOCK))
{
/* Safety if one did "drop table" on locked tables */
@@ -182,6 +182,14 @@ bool trans_commit_implicit(THD *thd)
thd->variables.option_bits&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
thd->transaction.all.modified_non_trans_table= FALSE;
+ /*
+ Upon implicit commit, reset the current transaction
+ isolation level. We do not care about
+ @@session.completion_type since it's documented
+ to not have any effect on implicit commit.
+ */
+ thd->tx_isolation= (enum_tx_isolation) thd->variables.tx_isolation;
+
DBUG_RETURN(res);
}
@@ -234,7 +242,11 @@ bool trans_commit_stmt(THD *thd)
DBUG_ENTER("trans_commit_stmt");
int res= FALSE;
if (thd->transaction.stmt.ha_list)
+ {
res= ha_commit_trans(thd, FALSE);
+ if (! thd->in_active_multi_stmt_transaction())
+ thd->tx_isolation= (enum_tx_isolation) thd->variables.tx_isolation;
+ }
if (res)
/*
@@ -265,6 +277,8 @@ bool trans_rollback_stmt(THD *thd)
ha_rollback_trans(thd, FALSE);
if (thd->transaction_rollback_request && !thd->in_sub_stmt)
ha_rollback_trans(thd, TRUE);
+ if (! thd->in_active_multi_stmt_transaction())
+ thd->tx_isolation= (enum_tx_isolation) thd->variables.tx_isolation;
}
RUN_HOOK(transaction, after_rollback, (thd, FALSE));
@@ -305,7 +319,7 @@ bool trans_savepoint(THD *thd, LEX_STRIN
SAVEPOINT **sv, *newsv;
DBUG_ENTER("trans_savepoint");
- if (!(thd->in_multi_stmt_transaction() || thd->in_sub_stmt) ||
+ if (!(thd->in_multi_stmt_transaction_mode() || thd->in_sub_stmt) ||
!opt_using_transactions)
DBUG_RETURN(FALSE);
@@ -467,7 +481,7 @@ bool trans_xa_start(THD *thd)
my_error(ER_XAER_INVAL, MYF(0));
else if (xa_state != XA_NOTR)
my_error(ER_XAER_RMFAIL, MYF(0), xa_state_names[xa_state]);
- else if (thd->locked_tables_mode || thd->active_transaction())
+ else if (thd->locked_tables_mode || thd->in_active_multi_stmt_transaction())
my_error(ER_XAER_OUTSIDE, MYF(0));
else if (xid_cache_search(thd->lex->xid))
my_error(ER_XAER_DUPID, MYF(0));
Attachment: [text/bzr-bundle] bzr/kostja@sun.com-20100505220843-it5n7bhexlpaze0d.bundle
| Thread |
|---|
| • bzr commit into mysql-trunk-runtime branch (kostja:3010) Bug#20837 | Konstantin Osipov | 6 May |