MDEV-8931: (server part of) session state tracking

Transaction tracker
This commit is contained in:
Oleksandr Byelkin 2016-05-30 21:22:50 +02:00
parent c8948b0d0d
commit 0ee3e64c55
32 changed files with 1173 additions and 270 deletions

View File

@ -94,7 +94,8 @@ enum enum_session_state_type
SESSION_TRACK_STATE_CHANGE,
SESSION_TRACK_GTIDS,
SESSION_TRACK_TRANSACTION_CHARACTERISTICS,
SESSION_TRACK_TRANSACTION_STATE
SESSION_TRACK_TRANSACTION_STATE,
SESSION_TRACK_END
};
my_bool my_net_init(NET *net, Vio* vio, void *thd, unsigned int my_flags);
void my_net_local_init(NET *net);

View File

@ -550,9 +550,6 @@ enum enum_mysql_set_option
/*
Type of state change information that the server can include in the Ok
packet.
Note : 1) session_state_type shouldn't go past 255 (i.e. 1-byte boundary).
2) Modify the definition of SESSION_TRACK_END when a new member is
added.
*/
enum enum_session_state_type
{
@ -561,15 +558,14 @@ enum enum_session_state_type
SESSION_TRACK_STATE_CHANGE, /* track session state changes */
SESSION_TRACK_GTIDS,
SESSION_TRACK_TRANSACTION_CHARACTERISTICS, /* Transaction chistics */
SESSION_TRACK_TRANSACTION_STATE /* Transaction state */
SESSION_TRACK_TRANSACTION_STATE, /* Transaction state */
SESSION_TRACK_END /* must be last */
};
#define SESSION_TRACK_BEGIN SESSION_TRACK_SYSTEM_VARIABLES
#define SESSION_TRACK_END SESSION_TRACK_TRANSACTION_STATE
#define IS_SESSION_STATE_TYPE(T) \
(((int)(T) >= SESSION_TRACK_BEGIN) && ((T) <= SESSION_TRACK_END))
(((int)(T) >= SESSION_TRACK_BEGIN) && ((T) < SESSION_TRACK_END))
#define net_new_transaction(net) ((net)->pkt_nr=0)

View File

@ -1172,8 +1172,8 @@ bool
net_send_ok(THD *thd,
uint server_status, uint statement_warn_count,
ulonglong affected_rows, ulonglong id, const char *message,
bool unused1 __attribute__((unused)),
bool unused2 __attribute__((unused)))
bool unused1,
bool unused2)
{
DBUG_ENTER("emb_net_send_ok");
MYSQL_DATA *data;

View File

@ -904,12 +904,21 @@ The following options may be given as the first argument:
--server-id=# Uniquely identifies the server instance in the community
of replication partners
--session-track-schema
Track changes to the 'default schema'.
Track changes to the default schema.
(Defaults to on; use --skip-session-track-schema to disable.)
--session-track-state-change
Track changes to the 'session state'.
Track changes to the session state.
--session-track-system-variables=name
Track changes in registered system variables.
--session-track-transaction-info=name
Track changes to the transaction attributes. OFF to
disable; STATE to track just transaction state (Is there
an active transaction? Does it have any data? etc.);
CHARACTERISTICS to track transaction state and report all
statements needed to start a transaction withthe same
characteristics (isolation level, read only/read
write,snapshot - but not any work done / data modified
within the transaction).
--show-slave-auth-info
Show user and password in SHOW SLAVE HOSTS on this
master.
@ -1395,6 +1404,7 @@ server-id 1
session-track-schema TRUE
session-track-state-change FALSE
session-track-system-variables autocommit,character_set_client,character_set_connection,character_set_results,time_zone
session-track-transaction-info OFF
show-slave-auth-info FALSE
silent-startup FALSE
skip-grant-tables TRUE

View File

@ -17,12 +17,14 @@ VARIABLE_NAME VARIABLE_VALUE
SESSION_TRACK_SCHEMA ON
SESSION_TRACK_STATE_CHANGE OFF
SESSION_TRACK_SYSTEM_VARIABLES autocommit,character_set_client,character_set_connection,character_set_results,time_zone
SESSION_TRACK_TRANSACTION_INFO OFF
# via INFORMATION_SCHEMA.SESSION_VARIABLES
SELECT * FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE VARIABLE_NAME LIKE 'session_track%' ORDER BY VARIABLE_NAME;
VARIABLE_NAME VARIABLE_VALUE
SESSION_TRACK_SCHEMA ON
SESSION_TRACK_STATE_CHANGE OFF
SESSION_TRACK_SYSTEM_VARIABLES autocommit,character_set_client,character_set_connection,character_set_results,time_zone
SESSION_TRACK_TRANSACTION_INFO OFF
SET @global_saved_tmp = @@global.session_track_system_variables;
# Altering global variable's value

View File

@ -3327,34 +3327,6 @@ NUMERIC_BLOCK_SIZE 1
ENUM_VALUE_LIST NULL
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME SESSION_TRACK_SCHEMA
SESSION_VALUE ON
GLOBAL_VALUE ON
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE ON
VARIABLE_SCOPE SESSION
VARIABLE_TYPE BOOLEAN
VARIABLE_COMMENT Track changes to the 'default schema'.
NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL
ENUM_VALUE_LIST OFF,ON
READ_ONLY NO
COMMAND_LINE_ARGUMENT OPTIONAL
VARIABLE_NAME SESSION_TRACK_STATE_CHANGE
SESSION_VALUE OFF
GLOBAL_VALUE OFF
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE OFF
VARIABLE_SCOPE SESSION
VARIABLE_TYPE BOOLEAN
VARIABLE_COMMENT Track changes to the 'session state'.
NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL
ENUM_VALUE_LIST OFF,ON
READ_ONLY NO
COMMAND_LINE_ARGUMENT OPTIONAL
VARIABLE_NAME SKIP_EXTERNAL_LOCKING
SESSION_VALUE NULL
GLOBAL_VALUE ON

View File

@ -3796,7 +3796,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE ON
VARIABLE_SCOPE SESSION
VARIABLE_TYPE BOOLEAN
VARIABLE_COMMENT Track changes to the 'default schema'.
VARIABLE_COMMENT Track changes to the default schema.
NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL
@ -3810,7 +3810,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE OFF
VARIABLE_SCOPE SESSION
VARIABLE_TYPE BOOLEAN
VARIABLE_COMMENT Track changes to the 'session state'.
VARIABLE_COMMENT Track changes to the session state.
NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL
@ -3831,6 +3831,20 @@ NUMERIC_BLOCK_SIZE NULL
ENUM_VALUE_LIST NULL
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME SESSION_TRACK_TRANSACTION_INFO
SESSION_VALUE OFF
GLOBAL_VALUE OFF
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE OFF
VARIABLE_SCOPE SESSION
VARIABLE_TYPE ENUM
VARIABLE_COMMENT Track changes to the transaction attributes. OFF to disable; STATE to track just transaction state (Is there an active transaction? Does it have any data? etc.); CHARACTERISTICS to track transaction state and report all statements needed to start a transaction withthe same characteristics (isolation level, read only/read write,snapshot - but not any work done / data modified within the transaction).
NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL
ENUM_VALUE_LIST OFF,STATE,CHARACTERISTICS
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME SKIP_EXTERNAL_LOCKING
SESSION_VALUE NULL
GLOBAL_VALUE ON

View File

@ -12,14 +12,10 @@ SELECT @@session.session_track_system_variables;
--echo
--echo # via INFORMATION_SCHEMA.GLOBAL_VARIABLES
--disable_warnings
SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME LIKE 'session_track%' ORDER BY VARIABLE_NAME;
--enable_warnings
--echo # via INFORMATION_SCHEMA.SESSION_VARIABLES
--disable_warnings
SELECT * FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE VARIABLE_NAME LIKE 'session_track%' ORDER BY VARIABLE_NAME;
--enable_warnings
# Save the global value to be used to restore the original value.
SET @global_saved_tmp = @@global.session_track_system_variables;

View File

@ -90,6 +90,7 @@ extern HASH open_cache;
static int lock_external(THD *thd, TABLE **table,uint count);
static int unlock_external(THD *thd, TABLE **table,uint count);
/* Map the return value of thr_lock to an error from errmsg.txt */
static int thr_lock_errno_to_mysql[]=
{ 0, ER_LOCK_ABORTED, ER_LOCK_WAIT_TIMEOUT, ER_LOCK_DEADLOCK };
@ -243,6 +244,39 @@ void reset_lock_data(MYSQL_LOCK *sql_lock, bool unlock)
}
/**
Scan array of tables for access types; update transaction tracker
accordingly.
@param thd The current thread.
@param tables An array of pointers to the tables to lock.
@param count The number of tables to lock.
*/
#ifndef EMBEDDED_LIBRARY
static void track_table_access(THD *thd, TABLE **tables, size_t count)
{
if (thd->variables.session_track_transaction_info > TX_TRACK_NONE)
{
Transaction_state_tracker *tst= (Transaction_state_tracker *)
thd->session_tracker.get_tracker(TRANSACTION_INFO_TRACKER);
while (count--)
{
TABLE *t= tables[count];
if (t)
tst->add_trx_state(thd, t->reginfo.lock_type,
t->file->has_transactions());
}
}
}
#else
#define track_table_access(A,B,C)
#endif //EMBEDDED_LIBRARY
/**
Lock tables.
@ -280,6 +314,9 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **tables, uint count, uint flags)
my_free(sql_lock);
sql_lock= 0;
}
track_table_access(thd, tables, count);
DBUG_RETURN(sql_lock);
}

View File

@ -5285,16 +5285,16 @@ static int init_server_components()
}
plugins_are_initialized= TRUE; /* Don't separate from init function */
#ifndef EMBEDDED_LIBRARY
{
Session_tracker session_track_system_variables_check;
if (session_track_system_variables_check.
server_boot_verify(system_charset_info))
if (Session_tracker::server_boot_verify(system_charset_info))
{
sql_print_error("The variable session_track_system_variables has "
"invalid values.");
unireg_abort(1);
}
}
#endif //EMBEDDED_LIBRARY
/* we do want to exit if there are any other unknown options */
if (remaining_argc > 1)

View File

@ -135,7 +135,6 @@ extern my_bool lower_case_file_system;
extern my_bool opt_enable_named_pipe, opt_sync_frm, opt_allow_suspicious_udfs;
extern my_bool opt_secure_auth;
extern const char *current_dbug_option;
extern const char *current_session_track_system_variables;
extern char* opt_secure_file_priv;
extern char* opt_secure_backup_file_priv;
extern size_t opt_secure_backup_file_priv_len;

View File

@ -198,7 +198,7 @@ bool net_send_error(THD *thd, uint sql_errno, const char *err,
@param affected_rows Number of rows changed by statement
@param id Auto_increment id for first row (if used)
@param message Message to send to the client (Used by mysql_status)
@param is_eof this called inted of old EOF packet
@param is_eof this called instead of old EOF packet
@return
@retval FALSE The message was successfully sent
@ -217,10 +217,6 @@ net_send_ok(THD *thd,
NET *net= &thd->net;
StringBuffer<MYSQL_ERRMSG_SIZE + 10> store;
/*
To be used to manage the data storage in case session state change
information is present.
*/
bool state_changed= false;
bool error= FALSE;
@ -269,39 +265,25 @@ net_send_ok(THD *thd,
}
thd->get_stmt_da()->set_overwrite_status(true);
if ((thd->client_capabilities & CLIENT_SESSION_TRACK))
{
if (server_status & SERVER_SESSION_STATE_CHANGED)
state_changed= true;
/* the info field */
if (state_changed || (message && message[0]))
{
store.q_net_store_data((uchar*) message, message ? strlen(message) : 0);
}
state_changed=
(thd->client_capabilities & CLIENT_SESSION_TRACK) &&
(server_status & SERVER_SESSION_STATE_CHANGED);
/* session state change information */
if (unlikely(state_changed))
{
store.set_charset(thd->variables.collation_database);
thd->session_tracker.store(thd, &store);
}
}
else if (message && message[0])
if (state_changed || (message && message[0]))
{
/* the info field, if there is a message to store */
DBUG_ASSERT(strlen(message) <= MYSQL_ERRMSG_SIZE);
store.q_net_store_data((uchar*) message, strlen(message));
DBUG_ASSERT(safe_strlen(message) <= MYSQL_ERRMSG_SIZE);
store.q_net_store_data((uchar*) safe_str(message), safe_strlen(message));
}
if (store.length() > MAX_PACKET_LENGTH)
if (unlikely(state_changed))
{
net->error= 1;
net->last_errno= ER_NET_OK_PACKET_TOO_LARGE;
my_error(ER_NET_OK_PACKET_TOO_LARGE, MYF(0));
DBUG_PRINT("info", ("OK packet too large"));
DBUG_RETURN(1);
store.set_charset(thd->variables.collation_database);
thd->session_tracker.store(thd, &store);
}
DBUG_ASSERT(store.length() <= MAX_PACKET_LENGTH);
error= my_net_write(net, (const unsigned char*)store.ptr(), store.length());
if (!error && (!skip_flush || is_eof))
error= net_flush(net);

File diff suppressed because it is too large Load Diff

View File

@ -20,6 +20,7 @@
#include "m_string.h"
#include "thr_lock.h"
#ifndef EMBEDDED_LIBRARY
/* forward declarations */
class THD;
class set_var;
@ -32,12 +33,10 @@ enum enum_session_tracker
CURRENT_SCHEMA_TRACKER, /* Current schema */
SESSION_STATE_CHANGE_TRACKER,
SESSION_GTIDS_TRACKER, /* Tracks GTIDs */
TRANSACTION_INFO_TRACKER /* Transaction state */
TRANSACTION_INFO_TRACKER, /* Transaction state */
SESSION_TRACKER_END /* must be the last */
};
#define SESSION_TRACKER_END TRANSACTION_INFO_TRACKER
/**
State_tracker
@ -54,8 +53,7 @@ enum enum_session_tracker
the respective system variable either through SET command or via command
line option. As required in system variable handling, this interface also
includes two functions to help in the verification of the supplied value
(ON_CHECK) and the updation (ON_UPDATE) of the tracker system variable,
namely - check() and update().
(ON_UPDATE) of the tracker system variable, namely - update().
*/
class State_tracker
@ -91,22 +89,19 @@ public:
/** Called in the constructor of THD*/
virtual bool enable(THD *thd)= 0;
/** To be invoked when the tracker's system variable is checked (ON_CHECK). */
virtual bool check(THD *thd, set_var *var)= 0;
/** To be invoked when the tracker's system variable is updated (ON_UPDATE).*/
virtual bool update(THD *thd)= 0;
virtual bool update(THD *thd, set_var *var)= 0;
/** Store changed data into the given buffer. */
virtual bool store(THD *thd, String *buf)= 0;
/** Mark the entity as changed. */
virtual void mark_as_changed(THD *thd, LEX_CSTRING *name)= 0;
virtual void mark_as_changed(THD *thd, LEX_CSTRING *name);
};
bool sysvartrack_validate_value(THD *thd, const char *str, size_t len);
bool sysvartrack_reprint_value(THD *thd, char *str, size_t len);
bool sysvartrack_update(THD *thd);
bool sysvartrack_update(THD *thd, set_var *var);
size_t sysvartrack_value_len(THD *thd);
bool sysvartrack_value_construct(THD *thd, char *val, size_t len);
@ -122,7 +117,7 @@ bool sysvartrack_value_construct(THD *thd, char *val, size_t len);
class Session_tracker
{
private:
State_tracker *m_trackers[SESSION_TRACKER_END + 1];
State_tracker *m_trackers[SESSION_TRACKER_END];
/* The following two functions are private to disable copying. */
Session_tracker(Session_tracker const &other)
@ -146,7 +141,7 @@ public:
/* trick to make happy memory accounting system */
void deinit()
{
for (int i= 0; i <= SESSION_TRACKER_END; i ++)
for (int i= 0; i < SESSION_TRACKER_END; i++)
{
if (m_trackers[i])
delete m_trackers[i];
@ -155,7 +150,7 @@ public:
}
void enable(THD *thd);
bool server_boot_verify(const CHARSET_INFO *char_set);
static bool server_boot_verify(CHARSET_INFO *char_set);
/** Returns the pointer to the tracker object for the specified tracker. */
inline State_tracker *get_tracker(enum_session_tracker tracker) const
@ -174,4 +169,136 @@ public:
void store(THD *thd, String *main_buf);
};
/*
Transaction_state_tracker
*/
/**
Transaction state (no transaction, transaction active, work attached, etc.)
*/
enum enum_tx_state {
TX_EMPTY = 0, ///< "none of the below"
TX_EXPLICIT = 1, ///< an explicit transaction is active
TX_IMPLICIT = 2, ///< an implicit transaction is active
TX_READ_TRX = 4, ///< transactional reads were done
TX_READ_UNSAFE = 8, ///< non-transaction reads were done
TX_WRITE_TRX = 16, ///< transactional writes were done
TX_WRITE_UNSAFE = 32, ///< non-transactional writes were done
TX_STMT_UNSAFE = 64, ///< "unsafe" (non-deterministic like UUID()) stmts
TX_RESULT_SET = 128, ///< result set was sent
TX_WITH_SNAPSHOT= 256, ///< WITH CONSISTENT SNAPSHOT was used
TX_LOCKED_TABLES= 512 ///< LOCK TABLES is active
};
/**
Transaction access mode
*/
enum enum_tx_read_flags {
TX_READ_INHERIT = 0, ///< not explicitly set, inherit session.tx_read_only
TX_READ_ONLY = 1, ///< START TRANSACTION READ ONLY, or tx_read_only=1
TX_READ_WRITE = 2, ///< START TRANSACTION READ WRITE, or tx_read_only=0
};
/**
Transaction isolation level
*/
enum enum_tx_isol_level {
TX_ISOL_INHERIT = 0, ///< not explicitly set, inherit session.tx_isolation
TX_ISOL_UNCOMMITTED = 1,
TX_ISOL_COMMITTED = 2,
TX_ISOL_REPEATABLE = 3,
TX_ISOL_SERIALIZABLE= 4
};
/**
Transaction tracking level
*/
enum enum_session_track_transaction_info {
TX_TRACK_NONE = 0, ///< do not send tracker items on transaction info
TX_TRACK_STATE = 1, ///< track transaction status
TX_TRACK_CHISTICS = 2 ///< track status and characteristics
};
/**
This is a tracker class that enables & manages the tracking of
current transaction info for a particular connection.
*/
class Transaction_state_tracker : public State_tracker
{
private:
/** Helper function: turn table info into table access flag */
enum_tx_state calc_trx_state(THD *thd, thr_lock_type l, bool has_trx);
public:
/** Constructor */
Transaction_state_tracker();
bool enable(THD *thd)
{ return update(thd, NULL); }
bool update(THD *thd, set_var *var);
bool store(THD *thd, String *buf);
/** Change transaction characteristics */
void set_read_flags(THD *thd, enum enum_tx_read_flags flags);
void set_isol_level(THD *thd, enum enum_tx_isol_level level);
/** Change transaction state */
void clear_trx_state(THD *thd, uint clear);
void add_trx_state(THD *thd, uint add);
void inline add_trx_state(THD *thd, thr_lock_type l, bool has_trx)
{
add_trx_state(thd, calc_trx_state(thd, l, has_trx));
}
void add_trx_state_from_thd(THD *thd);
void end_trx(THD *thd);
private:
enum enum_tx_changed {
TX_CHG_NONE = 0, ///< no changes from previous stmt
TX_CHG_STATE = 1, ///< state has changed from previous stmt
TX_CHG_CHISTICS = 2 ///< characteristics have changed from previous stmt
};
/** any trackable changes caused by this statement? */
uint tx_changed;
/** transaction state */
uint tx_curr_state, tx_reported_state;
/** r/w or r/o set? session default? */
enum enum_tx_read_flags tx_read_flags;
/** isolation level */
enum enum_tx_isol_level tx_isol_level;
void reset();
inline void update_change_flags(THD *thd)
{
tx_changed &= ~TX_CHG_STATE;
tx_changed |= (tx_curr_state != tx_reported_state) ? TX_CHG_STATE : 0;
if (tx_changed != TX_CHG_NONE)
mark_as_changed(thd, NULL);
}
};
#define TRANSACT_TRACKER(X) \
do { if (thd->variables.session_track_transaction_info > TX_TRACK_NONE) \
{((Transaction_state_tracker *) \
thd->session_tracker.get_tracker(TRANSACTION_INFO_TRACKER)) \
->X; } } while(0)
#define SESSION_TRACKER_CHANGED(A,B,C) \
thd->session_tracker.mark_as_changed(A,B,C)
#else
#define TRANSACT_TRACKER(X) do{}while(0)
#define SESSION_TRACKER_CHANGED(A,B,C) do{}while(0)
#endif //EMBEDDED_LIBRARY
#endif /* SESSION_TRACKER_INCLUDED */

View File

@ -220,14 +220,13 @@ bool sys_var::update(THD *thd, set_var *var)
*/
if ((var->type == OPT_SESSION) && (!ret))
{
thd->session_tracker.mark_as_changed(thd, SESSION_SYSVARS_TRACKER,
(LEX_CSTRING*)var->var);
SESSION_TRACKER_CHANGED(thd, SESSION_SYSVARS_TRACKER,
(LEX_CSTRING*)var->var);
/*
Here MySQL sends variable name to avoid reporting change of
the tracker itself, but we decided that it is not needed
*/
thd->session_tracker.mark_as_changed(thd, SESSION_STATE_CHANGE_TRACKER,
NULL);
SESSION_TRACKER_CHANGED(thd, SESSION_STATE_CHANGE_TRACKER, NULL);
}
return ret;
@ -894,7 +893,7 @@ int set_var_user::update(THD *thd)
return -1;
}
thd->session_tracker.mark_as_changed(thd, SESSION_STATE_CHANGE_TRACKER, NULL);
SESSION_TRACKER_CHANGED(thd, SESSION_STATE_CHANGE_TRACKER, NULL);
return 0;
}
@ -1002,6 +1001,7 @@ int set_var_collation_client::update(THD *thd)
character_set_results);
/* Mark client collation variables as changed */
#ifndef EMBEDDED_LIBRARY
if (thd->session_tracker.get_tracker(SESSION_SYSVARS_TRACKER)->is_enabled())
{
sys_var *svar;
@ -1024,6 +1024,7 @@ int set_var_collation_client::update(THD *thd)
mysql_mutex_unlock(&LOCK_plugin);
}
thd->session_tracker.mark_as_changed(thd, SESSION_STATE_CHANGE_TRACKER, NULL);
#endif //EMBEDDED_LIBRARY
thd->protocol_text.init(thd);
thd->protocol_binary.init(thd);

View File

@ -49,8 +49,6 @@ int mysql_add_sys_var_chain(sys_var *chain);
int mysql_del_sys_var_chain(sys_var *chain);
extern const LEX_CSTRING SESSION_TRACK_SYSTEM_VARIABLES_NAME;
/**
A class representing one system variable - that is something
that can be accessed as @@global.variable_name or @@session.variable_name,

View File

@ -7150,10 +7150,6 @@ skip-to-error-number 3000
ER_MYSQL_57_TEST
eng "5.7 test"
ER_NET_OK_PACKET_TOO_LARGE 08S01
eng "OK packet too large"
ukr "Пакет OK надто великий"
# MariaDB extra error numbers starts from 4000
skip-to-error-number 4000

View File

@ -2048,6 +2048,8 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
break;
}
}
TRANSACT_TRACKER(add_trx_state_from_thd(thd));
}
/*
@ -3063,6 +3065,9 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp,
what is needed from the substatement gained
*/
thd->transaction.stmt.modified_non_trans_table |= parent_modified_non_trans_table;
TRANSACT_TRACKER(add_trx_state_from_thd(thd));
/*
Unlike for PS we should not call Item's destructors for newly created
items after execution of each instruction in stored routine. This is

View File

@ -2093,6 +2093,9 @@ Locked_tables_list::init_locked_tables(THD *thd)
return TRUE;
}
}
TRANSACT_TRACKER(add_trx_state(thd, TX_LOCKED_TABLES));
thd->enter_locked_tables_mode(LTM_LOCK_TABLES);
return FALSE;
@ -2133,6 +2136,8 @@ Locked_tables_list::unlock_locked_tables(THD *thd)
}
thd->leave_locked_tables_mode();
TRANSACT_TRACKER(clear_trx_state(thd, TX_LOCKED_TABLES));
DBUG_ASSERT(thd->transaction.stmt.is_empty());
close_thread_tables(thd);
@ -4354,6 +4359,13 @@ static bool check_lock_and_start_stmt(THD *thd,
table_list->table->file->print_error(error, MYF(0));
DBUG_RETURN(1);
}
/*
Record in transaction state tracking
*/
TRANSACT_TRACKER(add_trx_state(thd, lock_type,
table_list->table->file->has_transactions()));
DBUG_RETURN(0);
}

View File

@ -1381,6 +1381,21 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used)
DBUG_VOID_RETURN;
}
/*
Do not store queries while tracking transaction state.
The tracker already flags queries that actually have
transaction tracker items, but this will make behavior
more straight forward.
*/
#ifndef EMBEDDED_LIBRARY
if (thd->variables.session_track_transaction_info != TX_TRACK_NONE)
{
DBUG_PRINT("qcache", ("Do not work with transaction tracking"));
DBUG_VOID_RETURN;
}
#endif //EMBEDDED_LIBRARY
/* The following assert fails if we haven't called send_result_to_client */
DBUG_ASSERT(thd->base_query.is_alloced() ||
thd->base_query.ptr() == thd->query());
@ -1719,6 +1734,20 @@ Query_cache::send_result_to_client(THD *thd, char *org_sql, uint query_length)
goto err;
}
/*
Don't allow serving from Query_cache while tracking transaction
state. This is a safeguard in case an otherwise matching query
was added to the cache before tracking was turned on.
*/
#ifndef EMBEDDED_LIBRARY
if (thd->variables.session_track_transaction_info != TX_TRACK_NONE)
{
DBUG_PRINT("qcache", ("Do not work with transaction tracking"));
goto err;
}
#endif //EMBEDDED_LIBRARY
thd->query_cache_is_applicable= 1;
sql= org_sql; sql_end= sql + query_length;

View File

@ -1466,7 +1466,9 @@ void THD::init(void)
debug_sync_init_thread(this);
#endif /* defined(ENABLED_DEBUG_SYNC) */
#ifndef EMBEDDED_LIBRARY
session_tracker.enable(this);
#endif //EMBEDDED_LIBRARY
apc_target.init(&LOCK_thd_data);
DBUG_VOID_RETURN;
@ -1768,7 +1770,9 @@ THD::~THD()
status_var.local_memory_used-= sizeof(THD);
/* trick to make happy memory accounting system */
#ifndef EMBEDDED_LIBRARY
session_tracker.deinit();
#endif //EMBEDDED_LIBRARY
if (status_var.local_memory_used != 0)
{

View File

@ -689,10 +689,11 @@ typedef struct system_variables
my_bool pseudo_slave_mode;
char *session_track_system_variables;
ulong session_track_transaction_info;
my_bool session_track_schema;
my_bool session_track_state_change;
char *session_track_system_variables;
} SV;
/**
@ -4059,7 +4060,9 @@ private:
LEX_STRING invoker_host;
public:
#ifndef EMBEDDED_LIBRARY
Session_tracker session_tracker;
#endif //EMBEDDED_LIBRARY
/*
Flag, mutex and condition for a thread to wait for a signal from another
thread.
@ -4293,6 +4296,8 @@ my_eof(THD *thd)
{
thd->set_row_count_func(-1);
thd->get_stmt_da()->set_eof_status(thd);
TRANSACT_TRACKER(add_trx_state(thd, TX_RESULT_SET));
}
#define tmp_disable_binlog(A) \

View File

@ -1037,7 +1037,7 @@ exit:
if (thd->db && cmp_db_names(thd->db, db) && !error)
{
mysql_change_db_impl(thd, NULL, 0, thd->variables.collation_server);
thd->session_tracker.mark_as_changed(thd, CURRENT_SCHEMA_TRACKER, NULL);
SESSION_TRACKER_CHANGED(thd, CURRENT_SCHEMA_TRACKER, NULL);
}
my_dirend(dirp);
DBUG_RETURN(error);
@ -1591,8 +1591,8 @@ bool mysql_change_db(THD *thd, const LEX_STRING *new_db_name, bool force_switch)
mysql_change_db_impl(thd, &new_db_file_name, db_access, db_default_cl);
done:
thd->session_tracker.mark_as_changed(thd, CURRENT_SCHEMA_TRACKER, NULL);
thd->session_tracker.mark_as_changed(thd, SESSION_STATE_CHANGE_TRACKER, NULL);
SESSION_TRACKER_CHANGED(thd, CURRENT_SCHEMA_TRACKER, NULL);
SESSION_TRACKER_CHANGED(thd, SESSION_STATE_CHANGE_TRACKER, NULL);
DBUG_RETURN(FALSE);
}

View File

@ -3855,9 +3855,9 @@ mysql_execute_command(THD *thd)
/* in case of create temp tables if @@session_track_state_change is
ON then send session state notification in OK packet */
if(create_info.options & HA_LEX_CREATE_TMP_TABLE)
thd->session_tracker.mark_as_changed(thd,
SESSION_STATE_CHANGE_TRACKER,
NULL);
{
SESSION_TRACKER_CHANGED(thd, SESSION_STATE_CHANGE_TRACKER, NULL);
}
my_ok(thd);
}
}
@ -4619,8 +4619,7 @@ end_with_restore_list:
send the boolean tracker in the OK packet */
if(!res && (lex->create_info.options & HA_LEX_CREATE_TMP_TABLE))
{
thd->session_tracker.mark_as_changed(thd, SESSION_STATE_CHANGE_TRACKER,
NULL);
SESSION_TRACKER_CHANGED(thd, SESSION_STATE_CHANGE_TRACKER, NULL);
}
break;
}
@ -5433,8 +5432,7 @@ end_with_restore_list:
else
{
/* Reset the isolation level and access mode if no chaining transaction.*/
thd->tx_isolation= (enum_tx_isolation) thd->variables.tx_isolation;
thd->tx_read_only= thd->variables.tx_read_only;
trans_reset_one_shot_chistics(thd);
}
/* Disconnect the current client connection. */
if (tx_release)
@ -5481,8 +5479,7 @@ end_with_restore_list:
else
{
/* Reset the isolation level and access mode if no chaining transaction.*/
thd->tx_isolation= (enum_tx_isolation) thd->variables.tx_isolation;
thd->tx_read_only= thd->variables.tx_read_only;
trans_reset_one_shot_chistics(thd);
}
/* Disconnect the current client connection. */
if (tx_release)
@ -5967,8 +5964,7 @@ end_with_restore_list:
We've just done a commit, reset transaction
isolation level and access mode to the session default.
*/
thd->tx_isolation= (enum_tx_isolation) thd->variables.tx_isolation;
thd->tx_read_only= thd->variables.tx_read_only;
trans_reset_one_shot_chistics(thd);
my_ok(thd);
break;
}
@ -5986,8 +5982,7 @@ end_with_restore_list:
We've just done a rollback, reset transaction
isolation level and access mode to the session default.
*/
thd->tx_isolation= (enum_tx_isolation) thd->variables.tx_isolation;
thd->tx_read_only= thd->variables.tx_read_only;
trans_reset_one_shot_chistics(thd);
my_ok(thd);
break;
}
@ -6205,6 +6200,9 @@ finish:
{
thd->mdl_context.release_statement_locks();
}
TRANSACT_TRACKER(add_trx_state_from_thd(thd));
WSREP_TO_ISOLATION_END;
#ifdef WITH_WSREP

View File

@ -323,8 +323,6 @@ static void unlock_variables(THD *thd, struct system_variables *vars);
static void cleanup_variables(struct system_variables *vars);
static void plugin_vars_free_values(sys_var *vars);
static void restore_ptr_backup(uint n, st_ptr_backup *backup);
#define my_intern_plugin_lock(A,B) intern_plugin_lock(A,B)
#define my_intern_plugin_lock_ci(A,B) intern_plugin_lock(A,B)
static plugin_ref intern_plugin_lock(LEX *lex, plugin_ref plugin);
static void intern_plugin_unlock(LEX *lex, plugin_ref plugin);
static void reap_plugins(void);
@ -2806,7 +2804,7 @@ sys_var *find_sys_var_ex(THD *thd, const char *str, size_t length,
{
mysql_rwlock_unlock(&LOCK_system_variables_hash);
LEX *lex= thd ? thd->lex : 0;
if (!(plugin= my_intern_plugin_lock(lex, plugin_int_to_ref(pi->plugin))))
if (!(plugin= intern_plugin_lock(lex, plugin_int_to_ref(pi->plugin))))
var= NULL; /* failed to lock it, it must be uninstalling */
else
if (!(plugin_state(plugin) & PLUGIN_IS_READY))

View File

@ -2759,8 +2759,7 @@ void mysql_sql_stmt_prepare(THD *thd)
}
else
{
thd->session_tracker.mark_as_changed(thd, SESSION_STATE_CHANGE_TRACKER,
NULL);
SESSION_TRACKER_CHANGED(thd, SESSION_STATE_CHANGE_TRACKER, NULL);
my_ok(thd, 0L, 0L, "Statement prepared");
}
@ -3212,8 +3211,7 @@ void mysql_sql_stmt_close(THD *thd)
else
{
stmt->deallocate();
thd->session_tracker.mark_as_changed(thd, SESSION_STATE_CHANGE_TRACKER,
NULL);
SESSION_TRACKER_CHANGED(thd, SESSION_STATE_CHANGE_TRACKER, NULL);
my_ok(thd);
}
}

View File

@ -1161,13 +1161,15 @@ uint convert_to_printable(char *to, size_t to_len,
void String::q_net_store_length(ulonglong length)
{
DBUG_ASSERT(Alloced_length >= (str_length + net_length_size(length)));
char *pos= (char *) net_store_length((uchar *)(Ptr + str_length), length);
str_length= pos - Ptr;
}
void String::q_net_store_data(const uchar *from, size_t length)
{
DBUG_ASSERT(Alloced_length >= (str_length + length +
net_length_size(length)));
q_net_store_length(length);
bool res= append((const char *)from, length);
DBUG_ASSERT(!res);
q_append((const char *)from, length);
}

View File

@ -9230,8 +9230,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
goto err_new_table_cleanup;
}
/* in case of alter temp table send the tracker in OK packet */
thd->session_tracker.mark_as_changed(thd, SESSION_STATE_CHANGE_TRACKER,
NULL);
SESSION_TRACKER_CHANGED(thd, SESSION_STATE_CHANGE_TRACKER, NULL);
}

View File

@ -3363,6 +3363,20 @@ bool Sys_var_tx_read_only::session_update(THD *thd, set_var *var)
{
// @see Sys_var_tx_isolation::session_update() above for the rules.
thd->tx_read_only= var->save_result.ulonglong_value;
#ifndef EMBEDDED_LIBRARY
if (thd->variables.session_track_transaction_info > TX_TRACK_NONE)
{
Transaction_state_tracker *tst= (Transaction_state_tracker *)
thd->session_tracker.get_tracker(TRANSACTION_INFO_TRACKER);
if (var->type == OPT_DEFAULT)
tst->set_read_flags(thd,
thd->tx_read_only ? TX_READ_ONLY : TX_READ_WRITE);
else
tst->set_read_flags(thd, TX_READ_INHERIT);
}
#endif //EMBEDDED_LIBRARY
}
return false;
}
@ -5375,11 +5389,10 @@ static Sys_var_ulong Sys_log_tc_size(
BLOCK_SIZE(my_getpagesize()));
#endif
const LEX_CSTRING SESSION_TRACK_SYSTEM_VARIABLES_NAME=
{STRING_WITH_LEN("session_track_system_variables")};
#ifndef EMBEDDED_LIBRARY
static Sys_var_sesvartrack Sys_track_session_sys_vars(
SESSION_TRACK_SYSTEM_VARIABLES_NAME.str,
"session_track_system_variables",
"Track changes in registered system variables.",
CMD_LINE(REQUIRED_ARG), IN_SYSTEM_CHARSET,
DEFAULT("autocommit,character_set_client,character_set_connection,"
@ -5390,30 +5403,61 @@ static bool update_session_track_schema(sys_var *self, THD *thd,
enum_var_type type)
{
DBUG_ENTER("update_session_track_schema");
DBUG_RETURN(thd->session_tracker.get_tracker(CURRENT_SCHEMA_TRACKER)->update(thd));
DBUG_RETURN(thd->session_tracker.get_tracker(CURRENT_SCHEMA_TRACKER)->
update(thd, NULL));
}
static Sys_var_mybool Sys_session_track_schema(
"session_track_schema",
"Track changes to the 'default schema'.",
"Track changes to the default schema.",
SESSION_VAR(session_track_schema),
CMD_LINE(OPT_ARG), DEFAULT(TRUE),
NO_MUTEX_GUARD, NOT_IN_BINLOG,
ON_CHECK(0),
ON_UPDATE(update_session_track_schema));
static bool update_session_track_tx_info(sys_var *self, THD *thd,
enum_var_type type)
{
DBUG_ENTER("update_session_track_tx_info");
DBUG_RETURN(thd->session_tracker.get_tracker(TRANSACTION_INFO_TRACKER)->
update(thd, NULL));
}
static const char *session_track_transaction_info_names[]=
{ "OFF", "STATE", "CHARACTERISTICS", NullS };
static Sys_var_enum Sys_session_track_transaction_info(
"session_track_transaction_info",
"Track changes to the transaction attributes. OFF to disable; "
"STATE to track just transaction state (Is there an active transaction? "
"Does it have any data? etc.); CHARACTERISTICS to track transaction "
"state and report all statements needed to start a transaction with"
"the same characteristics (isolation level, read only/read write,"
"snapshot - but not any work done / data modified within the "
"transaction).",
SESSION_VAR(session_track_transaction_info),
CMD_LINE(REQUIRED_ARG), session_track_transaction_info_names,
DEFAULT(0), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0),
ON_UPDATE(update_session_track_tx_info));
static bool update_session_track_state_change(sys_var *self, THD *thd,
enum_var_type type)
{
DBUG_ENTER("update_session_track_state_change");
DBUG_RETURN(thd->session_tracker.get_tracker(SESSION_STATE_CHANGE_TRACKER)->update(thd));
DBUG_RETURN(thd->session_tracker.get_tracker(SESSION_STATE_CHANGE_TRACKER)->
update(thd, NULL));
}
static Sys_var_mybool Sys_session_track_state_change(
"session_track_state_change",
"Track changes to the 'session state'.",
"Track changes to the session state.",
SESSION_VAR(session_track_state_change),
CMD_LINE(OPT_ARG), DEFAULT(FALSE),
NO_MUTEX_GUARD, NOT_IN_BINLOG,
ON_CHECK(0),
ON_UPDATE(update_session_track_state_change));
#endif //EMBEDDED_LIBRARY

View File

@ -567,6 +567,7 @@ public:
{ DBUG_ASSERT(FALSE); }
};
#ifndef EMBEDDED_LIBRARY
class Sys_var_sesvartrack: public Sys_var_charptr_base
{
public:
@ -602,7 +603,7 @@ public:
}
bool session_update(THD *thd, set_var *var)
{
return sysvartrack_update(thd);
return sysvartrack_update(thd, var);
}
void session_save_default(THD *thd, set_var *var)
{
@ -623,19 +624,17 @@ public:
{
DBUG_ASSERT(thd != NULL);
size_t len= sysvartrack_value_len(thd);
char *res= 0;
char *buf= (char *)my_safe_alloca(len);
if (buf && !sysvartrack_value_construct(thd, buf, len))
char *res= (char *)thd->alloc(len + sizeof(char *));
if (res)
{
size_t len= strlen(buf) + 1;
res= (char*) thd->alloc(len + sizeof(char *));
if (res)
memcpy((*((char**) res)= res + sizeof(char *)), buf, len);
my_safe_afree(buf, len);
char *buf= res + sizeof(char *);
*((char**) res)= buf;
sysvartrack_value_construct(thd, buf, len);
}
return (uchar *)res;
}
};
#endif //EMBEDDED_LIBRARY
class Sys_var_proxy_user: public sys_var
@ -2079,7 +2078,47 @@ public:
if (var->type == OPT_SESSION && Sys_var_enum::session_update(thd, var))
return TRUE;
if (var->type == OPT_DEFAULT || !thd->in_active_multi_stmt_transaction())
{
#ifndef EMBEDDED_LIBRARY
Transaction_state_tracker *tst= NULL;
if (thd->variables.session_track_transaction_info > TX_TRACK_NONE)
tst= (Transaction_state_tracker *)
thd->session_tracker.get_tracker(TRANSACTION_INFO_TRACKER);
#endif //EMBEDDED_LIBRARY
thd->tx_isolation= (enum_tx_isolation) var->save_result.ulonglong_value;
#ifndef EMBEDDED_LIBRARY
if (var->type == OPT_DEFAULT)
{
enum enum_tx_isol_level l;
switch (thd->tx_isolation) {
case ISO_READ_UNCOMMITTED:
l= TX_ISOL_UNCOMMITTED;
break;
case ISO_READ_COMMITTED:
l= TX_ISOL_COMMITTED;
break;
case ISO_REPEATABLE_READ:
l= TX_ISOL_REPEATABLE;
break;
case ISO_SERIALIZABLE:
l= TX_ISOL_SERIALIZABLE;
break;
default:
DBUG_ASSERT(0);
return TRUE;
}
if (tst)
tst->set_isol_level(thd, l);
}
else if (tst)
{
tst->set_isol_level(thd, TX_ISOL_INHERIT);
}
#endif //EMBEDDED_LIBRARY
}
return FALSE;
}
};

View File

@ -25,6 +25,43 @@
#include "debug_sync.h" // DEBUG_SYNC
#include "sql_acl.h"
#ifndef EMBEDDED_LIBRARY
/**
Helper: Tell tracker (if any) that transaction ended.
*/
static void trans_track_end_trx(THD *thd)
{
if (thd->variables.session_track_transaction_info > TX_TRACK_NONE)
{
((Transaction_state_tracker *)
thd->session_tracker.get_tracker(TRANSACTION_INFO_TRACKER))->end_trx(thd);
}
}
/**
Helper: transaction ended, SET TRANSACTION one-shot variables
revert to session values. Let the transaction state tracker know.
*/
void trans_reset_one_shot_chistics(THD *thd)
{
if (thd->variables.session_track_transaction_info > TX_TRACK_NONE)
{
Transaction_state_tracker *tst= (Transaction_state_tracker *)
thd->session_tracker.get_tracker(TRANSACTION_INFO_TRACKER);
tst->set_read_flags(thd, TX_READ_INHERIT);
tst->set_isol_level(thd, TX_ISOL_INHERIT);
}
thd->tx_isolation= (enum_tx_isolation) thd->variables.tx_isolation;
thd->tx_read_only= thd->variables.tx_read_only;
}
#else
#define trans_track_end_trx(A) do{}while(0)
#endif //EMBEDDED_LIBRARY
/* Conditions under which the transaction state must not change. */
static bool trans_check(THD *thd)
{
@ -125,11 +162,20 @@ static bool xa_trans_force_rollback(THD *thd)
bool trans_begin(THD *thd, uint flags)
{
int res= FALSE;
#ifndef EMBEDDED_LIBRARY
Transaction_state_tracker *tst= NULL;
#endif //EMBEDDED_LIBRARY
DBUG_ENTER("trans_begin");
if (trans_check(thd))
DBUG_RETURN(TRUE);
#ifndef EMBEDDED_LIBRARY
if (thd->variables.session_track_transaction_info > TX_TRACK_NONE)
tst= (Transaction_state_tracker *)
thd->session_tracker.get_tracker(TRANSACTION_INFO_TRACKER);
#endif //EMBEDDED_LIBRARY
thd->locked_tables_list.unlock_locked_tables(thd);
DBUG_ASSERT(!thd->locked_tables_mode);
@ -172,7 +218,13 @@ bool trans_begin(THD *thd, uint flags)
DBUG_ASSERT(!((flags & MYSQL_START_TRANS_OPT_READ_ONLY) &&
(flags & MYSQL_START_TRANS_OPT_READ_WRITE)));
if (flags & MYSQL_START_TRANS_OPT_READ_ONLY)
{
thd->tx_read_only= true;
#ifndef EMBEDDED_LIBRARY
if (tst)
tst->set_read_flags(thd, TX_READ_ONLY);
#endif //EMBEDDED_LIBRARY
}
else if (flags & MYSQL_START_TRANS_OPT_READ_WRITE)
{
/*
@ -189,6 +241,14 @@ bool trans_begin(THD *thd, uint flags)
DBUG_RETURN(true);
}
thd->tx_read_only= false;
/*
This flags that tx_read_only was set explicitly, rather than
just from the session's default.
*/
#ifndef EMBEDDED_LIBRARY
if (tst)
tst->set_read_flags(thd, TX_READ_WRITE);
#endif //EMBEDDED_LIBRARY
}
#ifdef WITH_WSREP
@ -203,9 +263,20 @@ bool trans_begin(THD *thd, uint flags)
thd->server_status|= SERVER_STATUS_IN_TRANS_READONLY;
DBUG_PRINT("info", ("setting SERVER_STATUS_IN_TRANS"));
#ifndef EMBEDDED_LIBRARY
if (tst)
tst->add_trx_state(thd, TX_EXPLICIT);
#endif //EMBEDDED_LIBRARY
/* ha_start_consistent_snapshot() relies on OPTION_BEGIN flag set. */
if (flags & MYSQL_START_TRANS_OPT_WITH_CONS_SNAPSHOT)
{
#ifndef EMBEDDED_LIBRARY
if (tst)
tst->add_trx_state(thd, TX_WITH_SNAPSHOT);
#endif //EMBEDDED_LIBRARY
res= ha_start_consistent_snapshot(thd);
}
DBUG_RETURN(MY_TEST(res));
}
@ -255,6 +326,8 @@ bool trans_commit(THD *thd)
thd->transaction.all.m_unsafe_rollback_flags&= ~THD_TRANS::DID_WAIT;
thd->lex->start_transaction_opt= 0;
trans_track_end_trx(thd);
DBUG_RETURN(MY_TEST(res));
}
@ -308,8 +381,9 @@ bool trans_commit_implicit(THD *thd)
@@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;
thd->tx_read_only= thd->variables.tx_read_only;
trans_reset_one_shot_chistics(thd);
trans_track_end_trx(thd);
DBUG_RETURN(res);
}
@ -349,6 +423,8 @@ bool trans_rollback(THD *thd)
thd->transaction.all.m_unsafe_rollback_flags&= ~THD_TRANS::DID_WAIT;
thd->lex->start_transaction_opt= 0;
trans_track_end_trx(thd);
DBUG_RETURN(MY_TEST(res));
}
@ -396,6 +472,8 @@ bool trans_rollback_implicit(THD *thd)
/* Rollback should clear transaction_rollback_request flag. */
DBUG_ASSERT(! thd->transaction_rollback_request);
trans_track_end_trx(thd);
DBUG_RETURN(MY_TEST(res));
}
@ -434,8 +512,7 @@ bool trans_commit_stmt(THD *thd)
res= ha_commit_trans(thd, FALSE);
if (! thd->in_active_multi_stmt_transaction())
{
thd->tx_isolation= (enum_tx_isolation) thd->variables.tx_isolation;
thd->tx_read_only= thd->variables.tx_read_only;
trans_reset_one_shot_chistics(thd);
if (WSREP_ON)
wsrep_post_commit(thd, FALSE);
}
@ -487,10 +564,7 @@ bool trans_rollback_stmt(THD *thd)
wsrep_register_hton(thd, FALSE);
ha_rollback_trans(thd, FALSE);
if (! thd->in_active_multi_stmt_transaction())
{
thd->tx_isolation= (enum_tx_isolation) thd->variables.tx_isolation;
thd->tx_read_only= thd->variables.tx_read_only;
}
trans_reset_one_shot_chistics(thd);
}
(void) RUN_HOOK(transaction, after_rollback, (thd, FALSE));
@ -912,6 +986,8 @@ bool trans_xa_commit(THD *thd)
xid_cache_delete(thd, &thd->transaction.xid_state);
thd->transaction.xid_state.xa_state= XA_NOTR;
trans_track_end_trx(thd);
DBUG_RETURN(res);
}
@ -968,5 +1044,7 @@ bool trans_xa_rollback(THD *thd)
xid_cache_delete(thd, &thd->transaction.xid_state);
thd->transaction.xid_state.xa_state= XA_NOTR;
trans_track_end_trx(thd);
DBUG_RETURN(res);
}

View File

@ -44,4 +44,10 @@ bool trans_xa_prepare(THD *thd);
bool trans_xa_commit(THD *thd);
bool trans_xa_rollback(THD *thd);
#ifndef EMBEDDED_LIBRARY
void trans_reset_one_shot_chistics(THD *thd);
#else
#define trans_reset_one_shot_chistics(A) do{}while(0)
#endif //EMBEDDED_LIBRARY
#endif /* TRANSACTION_H */