MDEV-8931: (server part of) session state tracking
Transaction tracker
This commit is contained in:
parent
c8948b0d0d
commit
0ee3e64c55
@ -94,7 +94,8 @@ enum enum_session_state_type
|
|||||||
SESSION_TRACK_STATE_CHANGE,
|
SESSION_TRACK_STATE_CHANGE,
|
||||||
SESSION_TRACK_GTIDS,
|
SESSION_TRACK_GTIDS,
|
||||||
SESSION_TRACK_TRANSACTION_CHARACTERISTICS,
|
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);
|
my_bool my_net_init(NET *net, Vio* vio, void *thd, unsigned int my_flags);
|
||||||
void my_net_local_init(NET *net);
|
void my_net_local_init(NET *net);
|
||||||
|
@ -550,9 +550,6 @@ enum enum_mysql_set_option
|
|||||||
/*
|
/*
|
||||||
Type of state change information that the server can include in the Ok
|
Type of state change information that the server can include in the Ok
|
||||||
packet.
|
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
|
enum enum_session_state_type
|
||||||
{
|
{
|
||||||
@ -561,15 +558,14 @@ enum enum_session_state_type
|
|||||||
SESSION_TRACK_STATE_CHANGE, /* track session state changes */
|
SESSION_TRACK_STATE_CHANGE, /* track session state changes */
|
||||||
SESSION_TRACK_GTIDS,
|
SESSION_TRACK_GTIDS,
|
||||||
SESSION_TRACK_TRANSACTION_CHARACTERISTICS, /* Transaction chistics */
|
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_BEGIN SESSION_TRACK_SYSTEM_VARIABLES
|
||||||
|
|
||||||
#define SESSION_TRACK_END SESSION_TRACK_TRANSACTION_STATE
|
|
||||||
|
|
||||||
#define IS_SESSION_STATE_TYPE(T) \
|
#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)
|
#define net_new_transaction(net) ((net)->pkt_nr=0)
|
||||||
|
|
||||||
|
@ -1172,8 +1172,8 @@ bool
|
|||||||
net_send_ok(THD *thd,
|
net_send_ok(THD *thd,
|
||||||
uint server_status, uint statement_warn_count,
|
uint server_status, uint statement_warn_count,
|
||||||
ulonglong affected_rows, ulonglong id, const char *message,
|
ulonglong affected_rows, ulonglong id, const char *message,
|
||||||
bool unused1 __attribute__((unused)),
|
bool unused1,
|
||||||
bool unused2 __attribute__((unused)))
|
bool unused2)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("emb_net_send_ok");
|
DBUG_ENTER("emb_net_send_ok");
|
||||||
MYSQL_DATA *data;
|
MYSQL_DATA *data;
|
||||||
|
@ -904,12 +904,21 @@ The following options may be given as the first argument:
|
|||||||
--server-id=# Uniquely identifies the server instance in the community
|
--server-id=# Uniquely identifies the server instance in the community
|
||||||
of replication partners
|
of replication partners
|
||||||
--session-track-schema
|
--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.)
|
(Defaults to on; use --skip-session-track-schema to disable.)
|
||||||
--session-track-state-change
|
--session-track-state-change
|
||||||
Track changes to the 'session state'.
|
Track changes to the session state.
|
||||||
--session-track-system-variables=name
|
--session-track-system-variables=name
|
||||||
Track changes in registered system variables.
|
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-slave-auth-info
|
||||||
Show user and password in SHOW SLAVE HOSTS on this
|
Show user and password in SHOW SLAVE HOSTS on this
|
||||||
master.
|
master.
|
||||||
@ -1395,6 +1404,7 @@ server-id 1
|
|||||||
session-track-schema TRUE
|
session-track-schema TRUE
|
||||||
session-track-state-change FALSE
|
session-track-state-change FALSE
|
||||||
session-track-system-variables autocommit,character_set_client,character_set_connection,character_set_results,time_zone
|
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
|
show-slave-auth-info FALSE
|
||||||
silent-startup FALSE
|
silent-startup FALSE
|
||||||
skip-grant-tables TRUE
|
skip-grant-tables TRUE
|
||||||
|
@ -17,12 +17,14 @@ VARIABLE_NAME VARIABLE_VALUE
|
|||||||
SESSION_TRACK_SCHEMA ON
|
SESSION_TRACK_SCHEMA ON
|
||||||
SESSION_TRACK_STATE_CHANGE OFF
|
SESSION_TRACK_STATE_CHANGE OFF
|
||||||
SESSION_TRACK_SYSTEM_VARIABLES autocommit,character_set_client,character_set_connection,character_set_results,time_zone
|
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
|
# via INFORMATION_SCHEMA.SESSION_VARIABLES
|
||||||
SELECT * FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE VARIABLE_NAME LIKE 'session_track%' ORDER BY VARIABLE_NAME;
|
SELECT * FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE VARIABLE_NAME LIKE 'session_track%' ORDER BY VARIABLE_NAME;
|
||||||
VARIABLE_NAME VARIABLE_VALUE
|
VARIABLE_NAME VARIABLE_VALUE
|
||||||
SESSION_TRACK_SCHEMA ON
|
SESSION_TRACK_SCHEMA ON
|
||||||
SESSION_TRACK_STATE_CHANGE OFF
|
SESSION_TRACK_STATE_CHANGE OFF
|
||||||
SESSION_TRACK_SYSTEM_VARIABLES autocommit,character_set_client,character_set_connection,character_set_results,time_zone
|
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;
|
SET @global_saved_tmp = @@global.session_track_system_variables;
|
||||||
|
|
||||||
# Altering global variable's value
|
# Altering global variable's value
|
||||||
|
@ -3327,34 +3327,6 @@ NUMERIC_BLOCK_SIZE 1
|
|||||||
ENUM_VALUE_LIST NULL
|
ENUM_VALUE_LIST NULL
|
||||||
READ_ONLY NO
|
READ_ONLY NO
|
||||||
COMMAND_LINE_ARGUMENT REQUIRED
|
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
|
VARIABLE_NAME SKIP_EXTERNAL_LOCKING
|
||||||
SESSION_VALUE NULL
|
SESSION_VALUE NULL
|
||||||
GLOBAL_VALUE ON
|
GLOBAL_VALUE ON
|
||||||
|
@ -3796,7 +3796,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME
|
|||||||
DEFAULT_VALUE ON
|
DEFAULT_VALUE ON
|
||||||
VARIABLE_SCOPE SESSION
|
VARIABLE_SCOPE SESSION
|
||||||
VARIABLE_TYPE BOOLEAN
|
VARIABLE_TYPE BOOLEAN
|
||||||
VARIABLE_COMMENT Track changes to the 'default schema'.
|
VARIABLE_COMMENT Track changes to the default schema.
|
||||||
NUMERIC_MIN_VALUE NULL
|
NUMERIC_MIN_VALUE NULL
|
||||||
NUMERIC_MAX_VALUE NULL
|
NUMERIC_MAX_VALUE NULL
|
||||||
NUMERIC_BLOCK_SIZE NULL
|
NUMERIC_BLOCK_SIZE NULL
|
||||||
@ -3810,7 +3810,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME
|
|||||||
DEFAULT_VALUE OFF
|
DEFAULT_VALUE OFF
|
||||||
VARIABLE_SCOPE SESSION
|
VARIABLE_SCOPE SESSION
|
||||||
VARIABLE_TYPE BOOLEAN
|
VARIABLE_TYPE BOOLEAN
|
||||||
VARIABLE_COMMENT Track changes to the 'session state'.
|
VARIABLE_COMMENT Track changes to the session state.
|
||||||
NUMERIC_MIN_VALUE NULL
|
NUMERIC_MIN_VALUE NULL
|
||||||
NUMERIC_MAX_VALUE NULL
|
NUMERIC_MAX_VALUE NULL
|
||||||
NUMERIC_BLOCK_SIZE NULL
|
NUMERIC_BLOCK_SIZE NULL
|
||||||
@ -3831,6 +3831,20 @@ NUMERIC_BLOCK_SIZE NULL
|
|||||||
ENUM_VALUE_LIST NULL
|
ENUM_VALUE_LIST NULL
|
||||||
READ_ONLY NO
|
READ_ONLY NO
|
||||||
COMMAND_LINE_ARGUMENT REQUIRED
|
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
|
VARIABLE_NAME SKIP_EXTERNAL_LOCKING
|
||||||
SESSION_VALUE NULL
|
SESSION_VALUE NULL
|
||||||
GLOBAL_VALUE ON
|
GLOBAL_VALUE ON
|
||||||
|
@ -12,14 +12,10 @@ SELECT @@session.session_track_system_variables;
|
|||||||
--echo
|
--echo
|
||||||
|
|
||||||
--echo # via INFORMATION_SCHEMA.GLOBAL_VARIABLES
|
--echo # via INFORMATION_SCHEMA.GLOBAL_VARIABLES
|
||||||
--disable_warnings
|
|
||||||
SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME LIKE 'session_track%' ORDER BY VARIABLE_NAME;
|
SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME LIKE 'session_track%' ORDER BY VARIABLE_NAME;
|
||||||
--enable_warnings
|
|
||||||
|
|
||||||
--echo # via INFORMATION_SCHEMA.SESSION_VARIABLES
|
--echo # via INFORMATION_SCHEMA.SESSION_VARIABLES
|
||||||
--disable_warnings
|
|
||||||
SELECT * FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE VARIABLE_NAME LIKE 'session_track%' ORDER BY VARIABLE_NAME;
|
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.
|
# Save the global value to be used to restore the original value.
|
||||||
SET @global_saved_tmp = @@global.session_track_system_variables;
|
SET @global_saved_tmp = @@global.session_track_system_variables;
|
||||||
|
37
sql/lock.cc
37
sql/lock.cc
@ -90,6 +90,7 @@ extern HASH open_cache;
|
|||||||
static int lock_external(THD *thd, TABLE **table,uint count);
|
static int lock_external(THD *thd, TABLE **table,uint count);
|
||||||
static int unlock_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 */
|
/* Map the return value of thr_lock to an error from errmsg.txt */
|
||||||
static int thr_lock_errno_to_mysql[]=
|
static int thr_lock_errno_to_mysql[]=
|
||||||
{ 0, ER_LOCK_ABORTED, ER_LOCK_WAIT_TIMEOUT, ER_LOCK_DEADLOCK };
|
{ 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.
|
Lock tables.
|
||||||
|
|
||||||
@ -280,6 +314,9 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **tables, uint count, uint flags)
|
|||||||
my_free(sql_lock);
|
my_free(sql_lock);
|
||||||
sql_lock= 0;
|
sql_lock= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
track_table_access(thd, tables, count);
|
||||||
|
|
||||||
DBUG_RETURN(sql_lock);
|
DBUG_RETURN(sql_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5285,16 +5285,16 @@ static int init_server_components()
|
|||||||
}
|
}
|
||||||
plugins_are_initialized= TRUE; /* Don't separate from init function */
|
plugins_are_initialized= TRUE; /* Don't separate from init function */
|
||||||
|
|
||||||
|
#ifndef EMBEDDED_LIBRARY
|
||||||
{
|
{
|
||||||
Session_tracker session_track_system_variables_check;
|
if (Session_tracker::server_boot_verify(system_charset_info))
|
||||||
if (session_track_system_variables_check.
|
|
||||||
server_boot_verify(system_charset_info))
|
|
||||||
{
|
{
|
||||||
sql_print_error("The variable session_track_system_variables has "
|
sql_print_error("The variable session_track_system_variables has "
|
||||||
"invalid values.");
|
"invalid values.");
|
||||||
unireg_abort(1);
|
unireg_abort(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif //EMBEDDED_LIBRARY
|
||||||
|
|
||||||
/* we do want to exit if there are any other unknown options */
|
/* we do want to exit if there are any other unknown options */
|
||||||
if (remaining_argc > 1)
|
if (remaining_argc > 1)
|
||||||
|
@ -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_enable_named_pipe, opt_sync_frm, opt_allow_suspicious_udfs;
|
||||||
extern my_bool opt_secure_auth;
|
extern my_bool opt_secure_auth;
|
||||||
extern const char *current_dbug_option;
|
extern const char *current_dbug_option;
|
||||||
extern const char *current_session_track_system_variables;
|
|
||||||
extern char* opt_secure_file_priv;
|
extern char* opt_secure_file_priv;
|
||||||
extern char* opt_secure_backup_file_priv;
|
extern char* opt_secure_backup_file_priv;
|
||||||
extern size_t opt_secure_backup_file_priv_len;
|
extern size_t opt_secure_backup_file_priv_len;
|
||||||
|
@ -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 affected_rows Number of rows changed by statement
|
||||||
@param id Auto_increment id for first row (if used)
|
@param id Auto_increment id for first row (if used)
|
||||||
@param message Message to send to the client (Used by mysql_status)
|
@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
|
@return
|
||||||
@retval FALSE The message was successfully sent
|
@retval FALSE The message was successfully sent
|
||||||
@ -217,10 +217,6 @@ net_send_ok(THD *thd,
|
|||||||
NET *net= &thd->net;
|
NET *net= &thd->net;
|
||||||
StringBuffer<MYSQL_ERRMSG_SIZE + 10> store;
|
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 state_changed= false;
|
||||||
|
|
||||||
bool error= FALSE;
|
bool error= FALSE;
|
||||||
@ -269,39 +265,25 @@ net_send_ok(THD *thd,
|
|||||||
}
|
}
|
||||||
thd->get_stmt_da()->set_overwrite_status(true);
|
thd->get_stmt_da()->set_overwrite_status(true);
|
||||||
|
|
||||||
if ((thd->client_capabilities & CLIENT_SESSION_TRACK))
|
state_changed=
|
||||||
{
|
(thd->client_capabilities & CLIENT_SESSION_TRACK) &&
|
||||||
if (server_status & SERVER_SESSION_STATE_CHANGED)
|
(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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* session state change information */
|
if (state_changed || (message && message[0]))
|
||||||
if (unlikely(state_changed))
|
|
||||||
{
|
|
||||||
store.set_charset(thd->variables.collation_database);
|
|
||||||
|
|
||||||
thd->session_tracker.store(thd, &store);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (message && message[0])
|
|
||||||
{
|
{
|
||||||
/* the info field, if there is a message to store */
|
DBUG_ASSERT(safe_strlen(message) <= MYSQL_ERRMSG_SIZE);
|
||||||
DBUG_ASSERT(strlen(message) <= MYSQL_ERRMSG_SIZE);
|
store.q_net_store_data((uchar*) safe_str(message), safe_strlen(message));
|
||||||
store.q_net_store_data((uchar*) message, strlen(message));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (store.length() > MAX_PACKET_LENGTH)
|
if (unlikely(state_changed))
|
||||||
{
|
{
|
||||||
net->error= 1;
|
store.set_charset(thd->variables.collation_database);
|
||||||
net->last_errno= ER_NET_OK_PACKET_TOO_LARGE;
|
|
||||||
my_error(ER_NET_OK_PACKET_TOO_LARGE, MYF(0));
|
thd->session_tracker.store(thd, &store);
|
||||||
DBUG_PRINT("info", ("OK packet too large"));
|
|
||||||
DBUG_RETURN(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DBUG_ASSERT(store.length() <= MAX_PACKET_LENGTH);
|
||||||
|
|
||||||
error= my_net_write(net, (const unsigned char*)store.ptr(), store.length());
|
error= my_net_write(net, (const unsigned char*)store.ptr(), store.length());
|
||||||
if (!error && (!skip_flush || is_eof))
|
if (!error && (!skip_flush || is_eof))
|
||||||
error= net_flush(net);
|
error= net_flush(net);
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -20,6 +20,7 @@
|
|||||||
#include "m_string.h"
|
#include "m_string.h"
|
||||||
#include "thr_lock.h"
|
#include "thr_lock.h"
|
||||||
|
|
||||||
|
#ifndef EMBEDDED_LIBRARY
|
||||||
/* forward declarations */
|
/* forward declarations */
|
||||||
class THD;
|
class THD;
|
||||||
class set_var;
|
class set_var;
|
||||||
@ -32,12 +33,10 @@ enum enum_session_tracker
|
|||||||
CURRENT_SCHEMA_TRACKER, /* Current schema */
|
CURRENT_SCHEMA_TRACKER, /* Current schema */
|
||||||
SESSION_STATE_CHANGE_TRACKER,
|
SESSION_STATE_CHANGE_TRACKER,
|
||||||
SESSION_GTIDS_TRACKER, /* Tracks GTIDs */
|
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
|
State_tracker
|
||||||
|
|
||||||
@ -54,8 +53,7 @@ enum enum_session_tracker
|
|||||||
the respective system variable either through SET command or via command
|
the respective system variable either through SET command or via command
|
||||||
line option. As required in system variable handling, this interface also
|
line option. As required in system variable handling, this interface also
|
||||||
includes two functions to help in the verification of the supplied value
|
includes two functions to help in the verification of the supplied value
|
||||||
(ON_CHECK) and the updation (ON_UPDATE) of the tracker system variable,
|
(ON_UPDATE) of the tracker system variable, namely - update().
|
||||||
namely - check() and update().
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class State_tracker
|
class State_tracker
|
||||||
@ -91,22 +89,19 @@ public:
|
|||||||
/** Called in the constructor of THD*/
|
/** Called in the constructor of THD*/
|
||||||
virtual bool enable(THD *thd)= 0;
|
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).*/
|
/** 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. */
|
/** Store changed data into the given buffer. */
|
||||||
virtual bool store(THD *thd, String *buf)= 0;
|
virtual bool store(THD *thd, String *buf)= 0;
|
||||||
|
|
||||||
/** Mark the entity as changed. */
|
/** 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_validate_value(THD *thd, const char *str, size_t len);
|
||||||
bool sysvartrack_reprint_value(THD *thd, 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);
|
size_t sysvartrack_value_len(THD *thd);
|
||||||
bool sysvartrack_value_construct(THD *thd, char *val, size_t len);
|
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
|
class Session_tracker
|
||||||
{
|
{
|
||||||
private:
|
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. */
|
/* The following two functions are private to disable copying. */
|
||||||
Session_tracker(Session_tracker const &other)
|
Session_tracker(Session_tracker const &other)
|
||||||
@ -146,7 +141,7 @@ public:
|
|||||||
/* trick to make happy memory accounting system */
|
/* trick to make happy memory accounting system */
|
||||||
void deinit()
|
void deinit()
|
||||||
{
|
{
|
||||||
for (int i= 0; i <= SESSION_TRACKER_END; i ++)
|
for (int i= 0; i < SESSION_TRACKER_END; i++)
|
||||||
{
|
{
|
||||||
if (m_trackers[i])
|
if (m_trackers[i])
|
||||||
delete m_trackers[i];
|
delete m_trackers[i];
|
||||||
@ -155,7 +150,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void enable(THD *thd);
|
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. */
|
/** Returns the pointer to the tracker object for the specified tracker. */
|
||||||
inline State_tracker *get_tracker(enum_session_tracker tracker) const
|
inline State_tracker *get_tracker(enum_session_tracker tracker) const
|
||||||
@ -174,4 +169,136 @@ public:
|
|||||||
void store(THD *thd, String *main_buf);
|
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 */
|
#endif /* SESSION_TRACKER_INCLUDED */
|
||||||
|
@ -220,14 +220,13 @@ bool sys_var::update(THD *thd, set_var *var)
|
|||||||
*/
|
*/
|
||||||
if ((var->type == OPT_SESSION) && (!ret))
|
if ((var->type == OPT_SESSION) && (!ret))
|
||||||
{
|
{
|
||||||
thd->session_tracker.mark_as_changed(thd, SESSION_SYSVARS_TRACKER,
|
SESSION_TRACKER_CHANGED(thd, SESSION_SYSVARS_TRACKER,
|
||||||
(LEX_CSTRING*)var->var);
|
(LEX_CSTRING*)var->var);
|
||||||
/*
|
/*
|
||||||
Here MySQL sends variable name to avoid reporting change of
|
Here MySQL sends variable name to avoid reporting change of
|
||||||
the tracker itself, but we decided that it is not needed
|
the tracker itself, but we decided that it is not needed
|
||||||
*/
|
*/
|
||||||
thd->session_tracker.mark_as_changed(thd, SESSION_STATE_CHANGE_TRACKER,
|
SESSION_TRACKER_CHANGED(thd, SESSION_STATE_CHANGE_TRACKER, NULL);
|
||||||
NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@ -894,7 +893,7 @@ int set_var_user::update(THD *thd)
|
|||||||
return -1;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1002,6 +1001,7 @@ int set_var_collation_client::update(THD *thd)
|
|||||||
character_set_results);
|
character_set_results);
|
||||||
|
|
||||||
/* Mark client collation variables as changed */
|
/* Mark client collation variables as changed */
|
||||||
|
#ifndef EMBEDDED_LIBRARY
|
||||||
if (thd->session_tracker.get_tracker(SESSION_SYSVARS_TRACKER)->is_enabled())
|
if (thd->session_tracker.get_tracker(SESSION_SYSVARS_TRACKER)->is_enabled())
|
||||||
{
|
{
|
||||||
sys_var *svar;
|
sys_var *svar;
|
||||||
@ -1024,6 +1024,7 @@ int set_var_collation_client::update(THD *thd)
|
|||||||
mysql_mutex_unlock(&LOCK_plugin);
|
mysql_mutex_unlock(&LOCK_plugin);
|
||||||
}
|
}
|
||||||
thd->session_tracker.mark_as_changed(thd, SESSION_STATE_CHANGE_TRACKER, NULL);
|
thd->session_tracker.mark_as_changed(thd, SESSION_STATE_CHANGE_TRACKER, NULL);
|
||||||
|
#endif //EMBEDDED_LIBRARY
|
||||||
|
|
||||||
thd->protocol_text.init(thd);
|
thd->protocol_text.init(thd);
|
||||||
thd->protocol_binary.init(thd);
|
thd->protocol_binary.init(thd);
|
||||||
|
@ -49,8 +49,6 @@ int mysql_add_sys_var_chain(sys_var *chain);
|
|||||||
int mysql_del_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
|
A class representing one system variable - that is something
|
||||||
that can be accessed as @@global.variable_name or @@session.variable_name,
|
that can be accessed as @@global.variable_name or @@session.variable_name,
|
||||||
|
@ -7150,10 +7150,6 @@ skip-to-error-number 3000
|
|||||||
ER_MYSQL_57_TEST
|
ER_MYSQL_57_TEST
|
||||||
eng "5.7 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
|
# MariaDB extra error numbers starts from 4000
|
||||||
skip-to-error-number 4000
|
skip-to-error-number 4000
|
||||||
|
|
||||||
|
@ -2048,6 +2048,8 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
|
|||||||
break;
|
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
|
what is needed from the substatement gained
|
||||||
*/
|
*/
|
||||||
thd->transaction.stmt.modified_non_trans_table |= parent_modified_non_trans_table;
|
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
|
Unlike for PS we should not call Item's destructors for newly created
|
||||||
items after execution of each instruction in stored routine. This is
|
items after execution of each instruction in stored routine. This is
|
||||||
|
@ -2093,6 +2093,9 @@ Locked_tables_list::init_locked_tables(THD *thd)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TRANSACT_TRACKER(add_trx_state(thd, TX_LOCKED_TABLES));
|
||||||
|
|
||||||
thd->enter_locked_tables_mode(LTM_LOCK_TABLES);
|
thd->enter_locked_tables_mode(LTM_LOCK_TABLES);
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@ -2133,6 +2136,8 @@ Locked_tables_list::unlock_locked_tables(THD *thd)
|
|||||||
}
|
}
|
||||||
thd->leave_locked_tables_mode();
|
thd->leave_locked_tables_mode();
|
||||||
|
|
||||||
|
TRANSACT_TRACKER(clear_trx_state(thd, TX_LOCKED_TABLES));
|
||||||
|
|
||||||
DBUG_ASSERT(thd->transaction.stmt.is_empty());
|
DBUG_ASSERT(thd->transaction.stmt.is_empty());
|
||||||
close_thread_tables(thd);
|
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));
|
table_list->table->file->print_error(error, MYF(0));
|
||||||
DBUG_RETURN(1);
|
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);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1381,6 +1381,21 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used)
|
|||||||
DBUG_VOID_RETURN;
|
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 */
|
/* The following assert fails if we haven't called send_result_to_client */
|
||||||
DBUG_ASSERT(thd->base_query.is_alloced() ||
|
DBUG_ASSERT(thd->base_query.is_alloced() ||
|
||||||
thd->base_query.ptr() == thd->query());
|
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;
|
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;
|
thd->query_cache_is_applicable= 1;
|
||||||
sql= org_sql; sql_end= sql + query_length;
|
sql= org_sql; sql_end= sql + query_length;
|
||||||
|
|
||||||
|
@ -1466,7 +1466,9 @@ void THD::init(void)
|
|||||||
debug_sync_init_thread(this);
|
debug_sync_init_thread(this);
|
||||||
#endif /* defined(ENABLED_DEBUG_SYNC) */
|
#endif /* defined(ENABLED_DEBUG_SYNC) */
|
||||||
|
|
||||||
|
#ifndef EMBEDDED_LIBRARY
|
||||||
session_tracker.enable(this);
|
session_tracker.enable(this);
|
||||||
|
#endif //EMBEDDED_LIBRARY
|
||||||
|
|
||||||
apc_target.init(&LOCK_thd_data);
|
apc_target.init(&LOCK_thd_data);
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
@ -1768,7 +1770,9 @@ THD::~THD()
|
|||||||
status_var.local_memory_used-= sizeof(THD);
|
status_var.local_memory_used-= sizeof(THD);
|
||||||
|
|
||||||
/* trick to make happy memory accounting system */
|
/* trick to make happy memory accounting system */
|
||||||
|
#ifndef EMBEDDED_LIBRARY
|
||||||
session_tracker.deinit();
|
session_tracker.deinit();
|
||||||
|
#endif //EMBEDDED_LIBRARY
|
||||||
|
|
||||||
if (status_var.local_memory_used != 0)
|
if (status_var.local_memory_used != 0)
|
||||||
{
|
{
|
||||||
|
@ -689,10 +689,11 @@ typedef struct system_variables
|
|||||||
|
|
||||||
my_bool pseudo_slave_mode;
|
my_bool pseudo_slave_mode;
|
||||||
|
|
||||||
|
char *session_track_system_variables;
|
||||||
|
ulong session_track_transaction_info;
|
||||||
my_bool session_track_schema;
|
my_bool session_track_schema;
|
||||||
my_bool session_track_state_change;
|
my_bool session_track_state_change;
|
||||||
|
|
||||||
char *session_track_system_variables;
|
|
||||||
} SV;
|
} SV;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -4059,7 +4060,9 @@ private:
|
|||||||
LEX_STRING invoker_host;
|
LEX_STRING invoker_host;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
#ifndef EMBEDDED_LIBRARY
|
||||||
Session_tracker session_tracker;
|
Session_tracker session_tracker;
|
||||||
|
#endif //EMBEDDED_LIBRARY
|
||||||
/*
|
/*
|
||||||
Flag, mutex and condition for a thread to wait for a signal from another
|
Flag, mutex and condition for a thread to wait for a signal from another
|
||||||
thread.
|
thread.
|
||||||
@ -4293,6 +4296,8 @@ my_eof(THD *thd)
|
|||||||
{
|
{
|
||||||
thd->set_row_count_func(-1);
|
thd->set_row_count_func(-1);
|
||||||
thd->get_stmt_da()->set_eof_status(thd);
|
thd->get_stmt_da()->set_eof_status(thd);
|
||||||
|
|
||||||
|
TRANSACT_TRACKER(add_trx_state(thd, TX_RESULT_SET));
|
||||||
}
|
}
|
||||||
|
|
||||||
#define tmp_disable_binlog(A) \
|
#define tmp_disable_binlog(A) \
|
||||||
|
@ -1037,7 +1037,7 @@ exit:
|
|||||||
if (thd->db && cmp_db_names(thd->db, db) && !error)
|
if (thd->db && cmp_db_names(thd->db, db) && !error)
|
||||||
{
|
{
|
||||||
mysql_change_db_impl(thd, NULL, 0, thd->variables.collation_server);
|
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);
|
my_dirend(dirp);
|
||||||
DBUG_RETURN(error);
|
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);
|
mysql_change_db_impl(thd, &new_db_file_name, db_access, db_default_cl);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
thd->session_tracker.mark_as_changed(thd, CURRENT_SCHEMA_TRACKER, NULL);
|
SESSION_TRACKER_CHANGED(thd, CURRENT_SCHEMA_TRACKER, NULL);
|
||||||
thd->session_tracker.mark_as_changed(thd, SESSION_STATE_CHANGE_TRACKER, NULL);
|
SESSION_TRACKER_CHANGED(thd, SESSION_STATE_CHANGE_TRACKER, NULL);
|
||||||
DBUG_RETURN(FALSE);
|
DBUG_RETURN(FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3855,9 +3855,9 @@ mysql_execute_command(THD *thd)
|
|||||||
/* in case of create temp tables if @@session_track_state_change is
|
/* in case of create temp tables if @@session_track_state_change is
|
||||||
ON then send session state notification in OK packet */
|
ON then send session state notification in OK packet */
|
||||||
if(create_info.options & HA_LEX_CREATE_TMP_TABLE)
|
if(create_info.options & HA_LEX_CREATE_TMP_TABLE)
|
||||||
thd->session_tracker.mark_as_changed(thd,
|
{
|
||||||
SESSION_STATE_CHANGE_TRACKER,
|
SESSION_TRACKER_CHANGED(thd, SESSION_STATE_CHANGE_TRACKER, NULL);
|
||||||
NULL);
|
}
|
||||||
my_ok(thd);
|
my_ok(thd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4619,8 +4619,7 @@ end_with_restore_list:
|
|||||||
send the boolean tracker in the OK packet */
|
send the boolean tracker in the OK packet */
|
||||||
if(!res && (lex->create_info.options & HA_LEX_CREATE_TMP_TABLE))
|
if(!res && (lex->create_info.options & HA_LEX_CREATE_TMP_TABLE))
|
||||||
{
|
{
|
||||||
thd->session_tracker.mark_as_changed(thd, SESSION_STATE_CHANGE_TRACKER,
|
SESSION_TRACKER_CHANGED(thd, SESSION_STATE_CHANGE_TRACKER, NULL);
|
||||||
NULL);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -5433,8 +5432,7 @@ end_with_restore_list:
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Reset the isolation level and access mode if no chaining transaction.*/
|
/* Reset the isolation level and access mode if no chaining transaction.*/
|
||||||
thd->tx_isolation= (enum_tx_isolation) thd->variables.tx_isolation;
|
trans_reset_one_shot_chistics(thd);
|
||||||
thd->tx_read_only= thd->variables.tx_read_only;
|
|
||||||
}
|
}
|
||||||
/* Disconnect the current client connection. */
|
/* Disconnect the current client connection. */
|
||||||
if (tx_release)
|
if (tx_release)
|
||||||
@ -5481,8 +5479,7 @@ end_with_restore_list:
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Reset the isolation level and access mode if no chaining transaction.*/
|
/* Reset the isolation level and access mode if no chaining transaction.*/
|
||||||
thd->tx_isolation= (enum_tx_isolation) thd->variables.tx_isolation;
|
trans_reset_one_shot_chistics(thd);
|
||||||
thd->tx_read_only= thd->variables.tx_read_only;
|
|
||||||
}
|
}
|
||||||
/* Disconnect the current client connection. */
|
/* Disconnect the current client connection. */
|
||||||
if (tx_release)
|
if (tx_release)
|
||||||
@ -5967,8 +5964,7 @@ end_with_restore_list:
|
|||||||
We've just done a commit, reset transaction
|
We've just done a commit, reset transaction
|
||||||
isolation level and access mode to the session default.
|
isolation level and access mode to the session default.
|
||||||
*/
|
*/
|
||||||
thd->tx_isolation= (enum_tx_isolation) thd->variables.tx_isolation;
|
trans_reset_one_shot_chistics(thd);
|
||||||
thd->tx_read_only= thd->variables.tx_read_only;
|
|
||||||
my_ok(thd);
|
my_ok(thd);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -5986,8 +5982,7 @@ end_with_restore_list:
|
|||||||
We've just done a rollback, reset transaction
|
We've just done a rollback, reset transaction
|
||||||
isolation level and access mode to the session default.
|
isolation level and access mode to the session default.
|
||||||
*/
|
*/
|
||||||
thd->tx_isolation= (enum_tx_isolation) thd->variables.tx_isolation;
|
trans_reset_one_shot_chistics(thd);
|
||||||
thd->tx_read_only= thd->variables.tx_read_only;
|
|
||||||
my_ok(thd);
|
my_ok(thd);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -6205,6 +6200,9 @@ finish:
|
|||||||
{
|
{
|
||||||
thd->mdl_context.release_statement_locks();
|
thd->mdl_context.release_statement_locks();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TRANSACT_TRACKER(add_trx_state_from_thd(thd));
|
||||||
|
|
||||||
WSREP_TO_ISOLATION_END;
|
WSREP_TO_ISOLATION_END;
|
||||||
|
|
||||||
#ifdef WITH_WSREP
|
#ifdef WITH_WSREP
|
||||||
|
@ -323,8 +323,6 @@ static void unlock_variables(THD *thd, struct system_variables *vars);
|
|||||||
static void cleanup_variables(struct system_variables *vars);
|
static void cleanup_variables(struct system_variables *vars);
|
||||||
static void plugin_vars_free_values(sys_var *vars);
|
static void plugin_vars_free_values(sys_var *vars);
|
||||||
static void restore_ptr_backup(uint n, st_ptr_backup *backup);
|
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 plugin_ref intern_plugin_lock(LEX *lex, plugin_ref plugin);
|
||||||
static void intern_plugin_unlock(LEX *lex, plugin_ref plugin);
|
static void intern_plugin_unlock(LEX *lex, plugin_ref plugin);
|
||||||
static void reap_plugins(void);
|
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);
|
mysql_rwlock_unlock(&LOCK_system_variables_hash);
|
||||||
LEX *lex= thd ? thd->lex : 0;
|
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 */
|
var= NULL; /* failed to lock it, it must be uninstalling */
|
||||||
else
|
else
|
||||||
if (!(plugin_state(plugin) & PLUGIN_IS_READY))
|
if (!(plugin_state(plugin) & PLUGIN_IS_READY))
|
||||||
|
@ -2759,8 +2759,7 @@ void mysql_sql_stmt_prepare(THD *thd)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
thd->session_tracker.mark_as_changed(thd, SESSION_STATE_CHANGE_TRACKER,
|
SESSION_TRACKER_CHANGED(thd, SESSION_STATE_CHANGE_TRACKER, NULL);
|
||||||
NULL);
|
|
||||||
my_ok(thd, 0L, 0L, "Statement prepared");
|
my_ok(thd, 0L, 0L, "Statement prepared");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3212,8 +3211,7 @@ void mysql_sql_stmt_close(THD *thd)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
stmt->deallocate();
|
stmt->deallocate();
|
||||||
thd->session_tracker.mark_as_changed(thd, SESSION_STATE_CHANGE_TRACKER,
|
SESSION_TRACKER_CHANGED(thd, SESSION_STATE_CHANGE_TRACKER, NULL);
|
||||||
NULL);
|
|
||||||
my_ok(thd);
|
my_ok(thd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1161,13 +1161,15 @@ uint convert_to_printable(char *to, size_t to_len,
|
|||||||
|
|
||||||
void String::q_net_store_length(ulonglong length)
|
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);
|
char *pos= (char *) net_store_length((uchar *)(Ptr + str_length), length);
|
||||||
str_length= pos - Ptr;
|
str_length= pos - Ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void String::q_net_store_data(const uchar *from, size_t length)
|
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);
|
q_net_store_length(length);
|
||||||
bool res= append((const char *)from, length);
|
q_append((const char *)from, length);
|
||||||
DBUG_ASSERT(!res);
|
|
||||||
}
|
}
|
||||||
|
@ -9230,8 +9230,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
|||||||
goto err_new_table_cleanup;
|
goto err_new_table_cleanup;
|
||||||
}
|
}
|
||||||
/* in case of alter temp table send the tracker in OK packet */
|
/* in case of alter temp table send the tracker in OK packet */
|
||||||
thd->session_tracker.mark_as_changed(thd, SESSION_STATE_CHANGE_TRACKER,
|
SESSION_TRACKER_CHANGED(thd, SESSION_STATE_CHANGE_TRACKER, NULL);
|
||||||
NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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.
|
// @see Sys_var_tx_isolation::session_update() above for the rules.
|
||||||
thd->tx_read_only= var->save_result.ulonglong_value;
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
@ -5375,11 +5389,10 @@ static Sys_var_ulong Sys_log_tc_size(
|
|||||||
BLOCK_SIZE(my_getpagesize()));
|
BLOCK_SIZE(my_getpagesize()));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const LEX_CSTRING SESSION_TRACK_SYSTEM_VARIABLES_NAME=
|
#ifndef EMBEDDED_LIBRARY
|
||||||
{STRING_WITH_LEN("session_track_system_variables")};
|
|
||||||
|
|
||||||
static Sys_var_sesvartrack Sys_track_session_sys_vars(
|
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.",
|
"Track changes in registered system variables.",
|
||||||
CMD_LINE(REQUIRED_ARG), IN_SYSTEM_CHARSET,
|
CMD_LINE(REQUIRED_ARG), IN_SYSTEM_CHARSET,
|
||||||
DEFAULT("autocommit,character_set_client,character_set_connection,"
|
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)
|
enum_var_type type)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("update_session_track_schema");
|
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(
|
static Sys_var_mybool Sys_session_track_schema(
|
||||||
"session_track_schema",
|
"session_track_schema",
|
||||||
"Track changes to the 'default schema'.",
|
"Track changes to the default schema.",
|
||||||
SESSION_VAR(session_track_schema),
|
SESSION_VAR(session_track_schema),
|
||||||
CMD_LINE(OPT_ARG), DEFAULT(TRUE),
|
CMD_LINE(OPT_ARG), DEFAULT(TRUE),
|
||||||
NO_MUTEX_GUARD, NOT_IN_BINLOG,
|
NO_MUTEX_GUARD, NOT_IN_BINLOG,
|
||||||
ON_CHECK(0),
|
ON_CHECK(0),
|
||||||
ON_UPDATE(update_session_track_schema));
|
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,
|
static bool update_session_track_state_change(sys_var *self, THD *thd,
|
||||||
enum_var_type type)
|
enum_var_type type)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("update_session_track_state_change");
|
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(
|
static Sys_var_mybool Sys_session_track_state_change(
|
||||||
"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),
|
SESSION_VAR(session_track_state_change),
|
||||||
CMD_LINE(OPT_ARG), DEFAULT(FALSE),
|
CMD_LINE(OPT_ARG), DEFAULT(FALSE),
|
||||||
NO_MUTEX_GUARD, NOT_IN_BINLOG,
|
NO_MUTEX_GUARD, NOT_IN_BINLOG,
|
||||||
ON_CHECK(0),
|
ON_CHECK(0),
|
||||||
ON_UPDATE(update_session_track_state_change));
|
ON_UPDATE(update_session_track_state_change));
|
||||||
|
|
||||||
|
#endif //EMBEDDED_LIBRARY
|
||||||
|
@ -567,6 +567,7 @@ public:
|
|||||||
{ DBUG_ASSERT(FALSE); }
|
{ DBUG_ASSERT(FALSE); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifndef EMBEDDED_LIBRARY
|
||||||
class Sys_var_sesvartrack: public Sys_var_charptr_base
|
class Sys_var_sesvartrack: public Sys_var_charptr_base
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -602,7 +603,7 @@ public:
|
|||||||
}
|
}
|
||||||
bool session_update(THD *thd, set_var *var)
|
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)
|
void session_save_default(THD *thd, set_var *var)
|
||||||
{
|
{
|
||||||
@ -623,19 +624,17 @@ public:
|
|||||||
{
|
{
|
||||||
DBUG_ASSERT(thd != NULL);
|
DBUG_ASSERT(thd != NULL);
|
||||||
size_t len= sysvartrack_value_len(thd);
|
size_t len= sysvartrack_value_len(thd);
|
||||||
char *res= 0;
|
char *res= (char *)thd->alloc(len + sizeof(char *));
|
||||||
char *buf= (char *)my_safe_alloca(len);
|
if (res)
|
||||||
if (buf && !sysvartrack_value_construct(thd, buf, len))
|
|
||||||
{
|
{
|
||||||
size_t len= strlen(buf) + 1;
|
char *buf= res + sizeof(char *);
|
||||||
res= (char*) thd->alloc(len + sizeof(char *));
|
*((char**) res)= buf;
|
||||||
if (res)
|
sysvartrack_value_construct(thd, buf, len);
|
||||||
memcpy((*((char**) res)= res + sizeof(char *)), buf, len);
|
|
||||||
my_safe_afree(buf, len);
|
|
||||||
}
|
}
|
||||||
return (uchar *)res;
|
return (uchar *)res;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
#endif //EMBEDDED_LIBRARY
|
||||||
|
|
||||||
|
|
||||||
class Sys_var_proxy_user: public sys_var
|
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))
|
if (var->type == OPT_SESSION && Sys_var_enum::session_update(thd, var))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
if (var->type == OPT_DEFAULT || !thd->in_active_multi_stmt_transaction())
|
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;
|
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;
|
return FALSE;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -25,6 +25,43 @@
|
|||||||
#include "debug_sync.h" // DEBUG_SYNC
|
#include "debug_sync.h" // DEBUG_SYNC
|
||||||
#include "sql_acl.h"
|
#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. */
|
/* Conditions under which the transaction state must not change. */
|
||||||
static bool trans_check(THD *thd)
|
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)
|
bool trans_begin(THD *thd, uint flags)
|
||||||
{
|
{
|
||||||
int res= FALSE;
|
int res= FALSE;
|
||||||
|
#ifndef EMBEDDED_LIBRARY
|
||||||
|
Transaction_state_tracker *tst= NULL;
|
||||||
|
#endif //EMBEDDED_LIBRARY
|
||||||
DBUG_ENTER("trans_begin");
|
DBUG_ENTER("trans_begin");
|
||||||
|
|
||||||
if (trans_check(thd))
|
if (trans_check(thd))
|
||||||
DBUG_RETURN(TRUE);
|
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);
|
thd->locked_tables_list.unlock_locked_tables(thd);
|
||||||
|
|
||||||
DBUG_ASSERT(!thd->locked_tables_mode);
|
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) &&
|
DBUG_ASSERT(!((flags & MYSQL_START_TRANS_OPT_READ_ONLY) &&
|
||||||
(flags & MYSQL_START_TRANS_OPT_READ_WRITE)));
|
(flags & MYSQL_START_TRANS_OPT_READ_WRITE)));
|
||||||
if (flags & MYSQL_START_TRANS_OPT_READ_ONLY)
|
if (flags & MYSQL_START_TRANS_OPT_READ_ONLY)
|
||||||
|
{
|
||||||
thd->tx_read_only= true;
|
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)
|
else if (flags & MYSQL_START_TRANS_OPT_READ_WRITE)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -189,6 +241,14 @@ bool trans_begin(THD *thd, uint flags)
|
|||||||
DBUG_RETURN(true);
|
DBUG_RETURN(true);
|
||||||
}
|
}
|
||||||
thd->tx_read_only= false;
|
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
|
#ifdef WITH_WSREP
|
||||||
@ -203,9 +263,20 @@ bool trans_begin(THD *thd, uint flags)
|
|||||||
thd->server_status|= SERVER_STATUS_IN_TRANS_READONLY;
|
thd->server_status|= SERVER_STATUS_IN_TRANS_READONLY;
|
||||||
DBUG_PRINT("info", ("setting SERVER_STATUS_IN_TRANS"));
|
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. */
|
/* ha_start_consistent_snapshot() relies on OPTION_BEGIN flag set. */
|
||||||
if (flags & MYSQL_START_TRANS_OPT_WITH_CONS_SNAPSHOT)
|
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);
|
res= ha_start_consistent_snapshot(thd);
|
||||||
|
}
|
||||||
|
|
||||||
DBUG_RETURN(MY_TEST(res));
|
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->transaction.all.m_unsafe_rollback_flags&= ~THD_TRANS::DID_WAIT;
|
||||||
thd->lex->start_transaction_opt= 0;
|
thd->lex->start_transaction_opt= 0;
|
||||||
|
|
||||||
|
trans_track_end_trx(thd);
|
||||||
|
|
||||||
DBUG_RETURN(MY_TEST(res));
|
DBUG_RETURN(MY_TEST(res));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -308,8 +381,9 @@ bool trans_commit_implicit(THD *thd)
|
|||||||
@@session.completion_type since it's documented
|
@@session.completion_type since it's documented
|
||||||
to not have any effect on implicit commit.
|
to not have any effect on implicit commit.
|
||||||
*/
|
*/
|
||||||
thd->tx_isolation= (enum_tx_isolation) thd->variables.tx_isolation;
|
trans_reset_one_shot_chistics(thd);
|
||||||
thd->tx_read_only= thd->variables.tx_read_only;
|
|
||||||
|
trans_track_end_trx(thd);
|
||||||
|
|
||||||
DBUG_RETURN(res);
|
DBUG_RETURN(res);
|
||||||
}
|
}
|
||||||
@ -349,6 +423,8 @@ bool trans_rollback(THD *thd)
|
|||||||
thd->transaction.all.m_unsafe_rollback_flags&= ~THD_TRANS::DID_WAIT;
|
thd->transaction.all.m_unsafe_rollback_flags&= ~THD_TRANS::DID_WAIT;
|
||||||
thd->lex->start_transaction_opt= 0;
|
thd->lex->start_transaction_opt= 0;
|
||||||
|
|
||||||
|
trans_track_end_trx(thd);
|
||||||
|
|
||||||
DBUG_RETURN(MY_TEST(res));
|
DBUG_RETURN(MY_TEST(res));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -396,6 +472,8 @@ bool trans_rollback_implicit(THD *thd)
|
|||||||
/* Rollback should clear transaction_rollback_request flag. */
|
/* Rollback should clear transaction_rollback_request flag. */
|
||||||
DBUG_ASSERT(! thd->transaction_rollback_request);
|
DBUG_ASSERT(! thd->transaction_rollback_request);
|
||||||
|
|
||||||
|
trans_track_end_trx(thd);
|
||||||
|
|
||||||
DBUG_RETURN(MY_TEST(res));
|
DBUG_RETURN(MY_TEST(res));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -434,8 +512,7 @@ bool trans_commit_stmt(THD *thd)
|
|||||||
res= ha_commit_trans(thd, FALSE);
|
res= ha_commit_trans(thd, FALSE);
|
||||||
if (! thd->in_active_multi_stmt_transaction())
|
if (! thd->in_active_multi_stmt_transaction())
|
||||||
{
|
{
|
||||||
thd->tx_isolation= (enum_tx_isolation) thd->variables.tx_isolation;
|
trans_reset_one_shot_chistics(thd);
|
||||||
thd->tx_read_only= thd->variables.tx_read_only;
|
|
||||||
if (WSREP_ON)
|
if (WSREP_ON)
|
||||||
wsrep_post_commit(thd, FALSE);
|
wsrep_post_commit(thd, FALSE);
|
||||||
}
|
}
|
||||||
@ -487,10 +564,7 @@ bool trans_rollback_stmt(THD *thd)
|
|||||||
wsrep_register_hton(thd, FALSE);
|
wsrep_register_hton(thd, FALSE);
|
||||||
ha_rollback_trans(thd, FALSE);
|
ha_rollback_trans(thd, FALSE);
|
||||||
if (! thd->in_active_multi_stmt_transaction())
|
if (! thd->in_active_multi_stmt_transaction())
|
||||||
{
|
trans_reset_one_shot_chistics(thd);
|
||||||
thd->tx_isolation= (enum_tx_isolation) thd->variables.tx_isolation;
|
|
||||||
thd->tx_read_only= thd->variables.tx_read_only;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
(void) RUN_HOOK(transaction, after_rollback, (thd, FALSE));
|
(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);
|
xid_cache_delete(thd, &thd->transaction.xid_state);
|
||||||
thd->transaction.xid_state.xa_state= XA_NOTR;
|
thd->transaction.xid_state.xa_state= XA_NOTR;
|
||||||
|
|
||||||
|
trans_track_end_trx(thd);
|
||||||
|
|
||||||
DBUG_RETURN(res);
|
DBUG_RETURN(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -968,5 +1044,7 @@ bool trans_xa_rollback(THD *thd)
|
|||||||
xid_cache_delete(thd, &thd->transaction.xid_state);
|
xid_cache_delete(thd, &thd->transaction.xid_state);
|
||||||
thd->transaction.xid_state.xa_state= XA_NOTR;
|
thd->transaction.xid_state.xa_state= XA_NOTR;
|
||||||
|
|
||||||
|
trans_track_end_trx(thd);
|
||||||
|
|
||||||
DBUG_RETURN(res);
|
DBUG_RETURN(res);
|
||||||
}
|
}
|
||||||
|
@ -44,4 +44,10 @@ bool trans_xa_prepare(THD *thd);
|
|||||||
bool trans_xa_commit(THD *thd);
|
bool trans_xa_commit(THD *thd);
|
||||||
bool trans_xa_rollback(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 */
|
#endif /* TRANSACTION_H */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user