MDEV-16470 - Session user variables tracker
Based on contribution by Dapeng Huang.
This commit is contained in:
parent
ad77e3ac09
commit
f5c3ad1913
@ -108,6 +108,7 @@ enum enum_session_state_type
|
||||
SESSION_TRACK_GTIDS,
|
||||
SESSION_TRACK_TRANSACTION_CHARACTERISTICS,
|
||||
SESSION_TRACK_TRANSACTION_STATE,
|
||||
SESSION_TRACK_USER_VARIABLES,
|
||||
SESSION_TRACK_always_at_the_end
|
||||
};
|
||||
extern "C" {
|
||||
|
@ -601,6 +601,7 @@ enum enum_session_state_type
|
||||
SESSION_TRACK_GTIDS,
|
||||
SESSION_TRACK_TRANSACTION_CHARACTERISTICS, /* Transaction chistics */
|
||||
SESSION_TRACK_TRANSACTION_STATE, /* Transaction state */
|
||||
SESSION_TRACK_USER_VARIABLES,
|
||||
SESSION_TRACK_always_at_the_end /* must be last */
|
||||
};
|
||||
|
||||
|
@ -1117,6 +1117,8 @@ The following specify which files/extra groups are read (specified before remain
|
||||
characteristics (isolation level, read only/read
|
||||
write,snapshot - but not any work done / data modified
|
||||
within the transaction).
|
||||
--session-track-user-variables
|
||||
Track changes to user variables.
|
||||
--show-slave-auth-info
|
||||
Show user and password in SHOW SLAVE HOSTS on this
|
||||
master.
|
||||
@ -1712,6 +1714,7 @@ 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
|
||||
session-track-user-variables FALSE
|
||||
show-slave-auth-info FALSE
|
||||
silent-startup FALSE
|
||||
skip-grant-tables TRUE
|
||||
|
@ -29,3 +29,13 @@ SET NAMES 'utf8';
|
||||
# tracking info off once
|
||||
SET NAMES 'big5';
|
||||
SET @@session.session_track_system_variables= default;
|
||||
#
|
||||
# MDEV-16470 - Session user variables tracker
|
||||
#
|
||||
SET @@session.session_track_user_variables=1;
|
||||
SET @a=1;
|
||||
SET @b=NULL;
|
||||
SELECT @c:=10;
|
||||
@c:=10
|
||||
10
|
||||
SET @@session.session_track_user_variables=0;
|
||||
|
@ -23,3 +23,14 @@ SET NAMES 'big5';
|
||||
--disable_session_track_info
|
||||
|
||||
SET @@session.session_track_system_variables= default;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-16470 - Session user variables tracker
|
||||
--echo #
|
||||
SET @@session.session_track_user_variables=1;
|
||||
--enable_session_track_info
|
||||
SET @a=1;
|
||||
SET @b=NULL;
|
||||
SELECT @c:=10;
|
||||
--disable_session_track_info
|
||||
SET @@session.session_track_user_variables=0;
|
||||
|
@ -12,19 +12,13 @@ SELECT @@session.session_track_system_variables;
|
||||
autocommit,character_set_client,character_set_connection,character_set_results,time_zone
|
||||
|
||||
# via INFORMATION_SCHEMA.GLOBAL_VARIABLES
|
||||
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_system_variables' 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
|
||||
# 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_system_variables' 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
|
||||
|
@ -3453,6 +3453,16 @@ NUMERIC_BLOCK_SIZE NULL
|
||||
ENUM_VALUE_LIST OFF,STATE,CHARACTERISTICS
|
||||
READ_ONLY NO
|
||||
COMMAND_LINE_ARGUMENT REQUIRED
|
||||
VARIABLE_NAME SESSION_TRACK_USER_VARIABLES
|
||||
VARIABLE_SCOPE SESSION
|
||||
VARIABLE_TYPE BOOLEAN
|
||||
VARIABLE_COMMENT Track changes to user variables.
|
||||
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_SCOPE GLOBAL
|
||||
VARIABLE_TYPE BOOLEAN
|
||||
|
@ -12,10 +12,10 @@ SELECT @@session.session_track_system_variables;
|
||||
--echo
|
||||
|
||||
--echo # via INFORMATION_SCHEMA.GLOBAL_VARIABLES
|
||||
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_system_variables' ORDER BY VARIABLE_NAME;
|
||||
|
||||
--echo # 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_system_variables' ORDER BY VARIABLE_NAME;
|
||||
|
||||
# Save the global value to be used to restore the original value.
|
||||
SET @global_saved_tmp = @@global.session_track_system_variables;
|
||||
|
@ -4671,6 +4671,10 @@ update_hash(user_var_entry *entry, bool set_null, void *ptr, size_t length,
|
||||
entry->unsigned_flag= unsigned_arg;
|
||||
}
|
||||
entry->type=type;
|
||||
#ifndef EMBEDDED_LIBRARY
|
||||
THD *thd= current_thd;
|
||||
thd->session_tracker.user_variables.mark_as_changed(thd, entry);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -4760,7 +4764,7 @@ longlong user_var_entry::val_int(bool *null_value) const
|
||||
/** Get the value of a variable as a string. */
|
||||
|
||||
String *user_var_entry::val_str(bool *null_value, String *str,
|
||||
uint decimals)
|
||||
uint decimals) const
|
||||
{
|
||||
if ((*null_value= (value == 0)))
|
||||
return (String*) 0;
|
||||
|
@ -16,7 +16,6 @@
|
||||
|
||||
|
||||
#include "sql_plugin.h"
|
||||
#include "hash.h"
|
||||
#include "table.h"
|
||||
#include "rpl_gtid.h"
|
||||
#include "sql_class.h"
|
||||
@ -1182,6 +1181,38 @@ bool Session_state_change_tracker::store(THD *thd, String *buf)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool User_variables_tracker::update(THD *thd, set_var *)
|
||||
{
|
||||
m_enabled= thd->variables.session_track_user_variables;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool User_variables_tracker::store(THD *thd, String *buf)
|
||||
{
|
||||
for (ulong i= 0; i < m_changed_user_variables.size(); i++)
|
||||
{
|
||||
auto var= m_changed_user_variables.at(i);
|
||||
String value_str;
|
||||
bool null_value;
|
||||
|
||||
var->val_str(&null_value, &value_str, DECIMAL_MAX_SCALE);
|
||||
buf->q_append(static_cast<char>(SESSION_TRACK_USER_VARIABLES));
|
||||
ulonglong length= net_length_size(var->name.length) + var->name.length;
|
||||
if (!null_value)
|
||||
length+= net_length_size(value_str.length()) + value_str.length();
|
||||
buf->q_net_store_length(length);
|
||||
buf->q_net_store_data(reinterpret_cast<const uchar*>(var->name.str),
|
||||
var->name.length);
|
||||
if (!null_value)
|
||||
buf->q_net_store_data(reinterpret_cast<const uchar*>(value_str.ptr()),
|
||||
value_str.length());
|
||||
}
|
||||
m_changed_user_variables.clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
|
@ -19,12 +19,14 @@
|
||||
|
||||
#include "m_string.h"
|
||||
#include "thr_lock.h"
|
||||
#include "sql_hset.h"
|
||||
|
||||
#ifndef EMBEDDED_LIBRARY
|
||||
/* forward declarations */
|
||||
class THD;
|
||||
class set_var;
|
||||
class String;
|
||||
class user_var_entry;
|
||||
|
||||
|
||||
enum enum_session_tracker
|
||||
@ -33,6 +35,7 @@ enum enum_session_tracker
|
||||
CURRENT_SCHEMA_TRACKER, /* Current schema */
|
||||
SESSION_STATE_CHANGE_TRACKER,
|
||||
TRANSACTION_INFO_TRACKER, /* Transaction state */
|
||||
USER_VARIABLES_TRACKER,
|
||||
SESSION_TRACKER_END /* must be the last */
|
||||
};
|
||||
|
||||
@ -387,6 +390,35 @@ private:
|
||||
thd->session_tracker.transaction_info.X; } while(0)
|
||||
|
||||
|
||||
/**
|
||||
User_variables_tracker
|
||||
|
||||
This is a tracker class that enables & manages the tracking of user variables.
|
||||
*/
|
||||
|
||||
class User_variables_tracker: public State_tracker
|
||||
{
|
||||
Hash_set<const user_var_entry> m_changed_user_variables;
|
||||
public:
|
||||
User_variables_tracker():
|
||||
m_changed_user_variables(&my_charset_bin, 0, 0,
|
||||
sizeof(const user_var_entry*), 0, 0,
|
||||
HASH_UNIQUE | (mysqld_server_initialized ?
|
||||
HASH_THREAD_SPECIFIC : 0)) {}
|
||||
bool update(THD *thd, set_var *var);
|
||||
bool store(THD *thd, String *buf);
|
||||
void mark_as_changed(THD *thd, const user_var_entry *var)
|
||||
{
|
||||
if (is_enabled())
|
||||
{
|
||||
m_changed_user_variables.insert(var);
|
||||
set_changed(thd);
|
||||
}
|
||||
}
|
||||
void deinit() { m_changed_user_variables.~Hash_set(); }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Session_tracker
|
||||
|
||||
@ -415,6 +447,7 @@ public:
|
||||
Session_state_change_tracker state_change;
|
||||
Transaction_state_tracker transaction_info;
|
||||
Session_sysvars_tracker sysvars;
|
||||
User_variables_tracker user_variables;
|
||||
|
||||
Session_tracker()
|
||||
{
|
||||
@ -422,6 +455,7 @@ public:
|
||||
m_trackers[CURRENT_SCHEMA_TRACKER]= ¤t_schema;
|
||||
m_trackers[SESSION_STATE_CHANGE_TRACKER]= &state_change;
|
||||
m_trackers[TRANSACTION_INFO_TRACKER]= &transaction_info;
|
||||
m_trackers[USER_VARIABLES_TRACKER]= &user_variables;
|
||||
}
|
||||
|
||||
void enable(THD *thd)
|
||||
|
@ -56,7 +56,6 @@
|
||||
#include "rpl_filter.h"
|
||||
#include "sql_table.h" // build_table_filename
|
||||
#include "datadict.h" // dd_frm_is_view()
|
||||
#include "sql_hset.h" // Hash_set
|
||||
#include "rpl_rli.h" // rpl_group_info
|
||||
#ifdef __WIN__
|
||||
#include <io.h>
|
||||
|
@ -1750,6 +1750,7 @@ THD::~THD()
|
||||
/* trick to make happy memory accounting system */
|
||||
#ifndef EMBEDDED_LIBRARY
|
||||
session_tracker.sysvars.deinit();
|
||||
session_tracker.user_variables.deinit();
|
||||
#endif //EMBEDDED_LIBRARY
|
||||
|
||||
if (status_var.local_memory_used != 0)
|
||||
|
@ -766,6 +766,7 @@ typedef struct system_variables
|
||||
ulong session_track_transaction_info;
|
||||
my_bool session_track_schema;
|
||||
my_bool session_track_state_change;
|
||||
my_bool session_track_user_variables;
|
||||
my_bool tcp_nodelay;
|
||||
|
||||
ulong threadpool_priority;
|
||||
@ -6319,7 +6320,7 @@ class user_var_entry
|
||||
|
||||
double val_real(bool *null_value);
|
||||
longlong val_int(bool *null_value) const;
|
||||
String *val_str(bool *null_value, String *str, uint decimals);
|
||||
String *val_str(bool *null_value, String *str, uint decimals) const;
|
||||
my_decimal *val_decimal(bool *null_value, my_decimal *result);
|
||||
CHARSET_INFO *charset() const { return m_charset; }
|
||||
void set_charset(CHARSET_INFO *cs) { m_charset= cs; }
|
||||
|
@ -38,6 +38,13 @@ public:
|
||||
m_hash.get_key= (my_hash_get_key)K;
|
||||
m_hash.charset= cs;
|
||||
}
|
||||
Hash_set(CHARSET_INFO *charset, ulong default_array_elements,
|
||||
size_t key_offset, size_t key_length, my_hash_get_key get_key,
|
||||
void (*free_element)(void*), uint flags)
|
||||
{
|
||||
my_hash_init(&m_hash, charset, default_array_elements, key_offset,
|
||||
key_length, get_key, free_element, flags);
|
||||
}
|
||||
/**
|
||||
Destroy the hash by freeing the buckets table. Does
|
||||
not call destructors for the elements.
|
||||
@ -58,13 +65,8 @@ public:
|
||||
bool insert(T *value)
|
||||
{
|
||||
my_hash_init_opt(&m_hash, m_hash.charset, START_SIZE, 0, 0,
|
||||
m_hash.get_key, 0, MYF(0));
|
||||
size_t key_len;
|
||||
uchar *v= reinterpret_cast<uchar *>(value);
|
||||
const uchar *key= m_hash.get_key(v, &key_len, FALSE);
|
||||
if (find(key, key_len) == NULL)
|
||||
return my_hash_insert(&m_hash, v);
|
||||
return FALSE;
|
||||
m_hash.get_key, 0, HASH_UNIQUE);
|
||||
return my_hash_insert(&m_hash, reinterpret_cast<const uchar*>(value));
|
||||
}
|
||||
bool remove(T *value)
|
||||
{
|
||||
@ -78,6 +80,8 @@ public:
|
||||
bool is_empty() const { return m_hash.records == 0; }
|
||||
/** Returns the number of unique elements. */
|
||||
size_t size() const { return static_cast<size_t>(m_hash.records); }
|
||||
/** Erases all elements from the container */
|
||||
void clear() { my_hash_reset(&m_hash); }
|
||||
const T* at(size_t i) const
|
||||
{
|
||||
return reinterpret_cast<T*>(my_hash_element(const_cast<HASH*>(&m_hash), i));
|
||||
|
@ -6378,6 +6378,22 @@ static Sys_var_mybool Sys_session_track_state_change(
|
||||
ON_CHECK(0),
|
||||
ON_UPDATE(update_session_track_state_change));
|
||||
|
||||
|
||||
static bool update_session_track_user_variables(sys_var *self, THD *thd,
|
||||
enum_var_type type)
|
||||
{
|
||||
return thd->session_tracker.user_variables.update(thd, 0);
|
||||
}
|
||||
|
||||
static Sys_var_mybool Sys_session_track_user_variables(
|
||||
"session_track_user_variables",
|
||||
"Track changes to user variables.",
|
||||
SESSION_VAR(session_track_user_variables),
|
||||
CMD_LINE(OPT_ARG), DEFAULT(FALSE),
|
||||
NO_MUTEX_GUARD, NOT_IN_BINLOG,
|
||||
ON_CHECK(0),
|
||||
ON_UPDATE(update_session_track_user_variables));
|
||||
|
||||
#endif //EMBEDDED_LIBRARY
|
||||
|
||||
static Sys_var_uint Sys_in_subquery_conversion_threshold(
|
||||
|
Loading…
x
Reference in New Issue
Block a user