Clean-up, give better names, add comments to

thd->in_multi_stmt_transaction() and thd->active_transaction().
This commit is contained in:
Konstantin Osipov 2010-05-06 02:02:08 +04:00
parent 24a14875bc
commit cca59e83d7
15 changed files with 128 additions and 48 deletions

View file

@ -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 or COMMIT AND CHAIN, 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

View file

@ -4628,7 +4628,7 @@ int ha_ndbcluster::start_statement(THD *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_statement(THD *thd, Thd_ndb *thd_ndb)
}
#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 *thd, int lock_type)
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 *thd, int lock_type)
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 *hton, THD *thd, bool all)
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(handlerton *hton, THD *thd, bool all)
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 *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_table(THD *thd,
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);

View file

@ -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
(COMMIT statement), or implicit commit
issued by DDL. Is not set when called
at the end of statement, 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 all)
/*
"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;
@ -1303,9 +1316,15 @@ int ha_rollback_trans(THD *thd, bool all)
/*
"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 or BEGIN statement, or implicit
commit issued by DDL (in these cases 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");
@ -1358,7 +1377,7 @@ int ha_rollback_trans(THD *thd, bool all)
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)

View file

@ -1686,7 +1686,7 @@ static int binlog_commit(handlerton *hton, THD *thd, bool all)
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, bool is_transactional)
*/
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);
/*

View file

@ -2485,13 +2485,13 @@ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg,
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());

View file

@ -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),

View file

@ -1177,7 +1177,7 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used)
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 *thd, char *sql, uint query_length)
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, autocommit: %d",
}
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, TABLE_LIST *tables_used,
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, TABLE *table,
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, const char *key, uint32 key_length,
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_t query_len, const char *query,
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"));

View file

@ -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;

View file

@ -2309,10 +2309,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.
@ -2323,11 +2319,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();

View file

@ -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));
@ -4711,6 +4711,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 +5527,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;

View file

@ -3246,7 +3246,7 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len)
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;

View file

@ -54,7 +54,7 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent)
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));

View file

@ -6559,7 +6559,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
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));

View file

@ -295,7 +295,7 @@ static bool binlog_format_check(sys_var *self, THD *thd, set_var *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 *self, THD *thd, set_var *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,15 +2006,20 @@ static Sys_var_ulong Sys_thread_pool_size(
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;
}
/*
@ -2027,6 +2032,7 @@ static bool fix_tx_isolation(sys_var *self, THD *thd, enum_var_type type)
thd->session_tx_isolation= (enum_tx_isolation)thd->variables.tx_isolation;
return false;
}
// NO_CMD_LINE - different name of the option
static Sys_var_enum Sys_tx_isolation(
"tx_isolation", "Default transaction isolation level",

View file

@ -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 */
@ -305,7 +305,7 @@ bool trans_savepoint(THD *thd, LEX_STRING name)
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 +467,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));