Commit f5c3ad19 authored by Sergey Vojtovich's avatar Sergey Vojtovich

MDEV-16470 - Session user variables tracker

Based on contribution by Dapeng Huang.
parent ad77e3ac
...@@ -108,6 +108,7 @@ enum enum_session_state_type ...@@ -108,6 +108,7 @@ enum enum_session_state_type
SESSION_TRACK_GTIDS, SESSION_TRACK_GTIDS,
SESSION_TRACK_TRANSACTION_CHARACTERISTICS, SESSION_TRACK_TRANSACTION_CHARACTERISTICS,
SESSION_TRACK_TRANSACTION_STATE, SESSION_TRACK_TRANSACTION_STATE,
SESSION_TRACK_USER_VARIABLES,
SESSION_TRACK_always_at_the_end SESSION_TRACK_always_at_the_end
}; };
extern "C" { extern "C" {
......
...@@ -601,6 +601,7 @@ enum enum_session_state_type ...@@ -601,6 +601,7 @@ enum enum_session_state_type
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_USER_VARIABLES,
SESSION_TRACK_always_at_the_end /* must be last */ 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 ...@@ -1117,6 +1117,8 @@ The following specify which files/extra groups are read (specified before remain
characteristics (isolation level, read only/read characteristics (isolation level, read only/read
write,snapshot - but not any work done / data modified write,snapshot - but not any work done / data modified
within the transaction). within the transaction).
--session-track-user-variables
Track changes to user variables.
--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.
...@@ -1712,6 +1714,7 @@ session-track-schema TRUE ...@@ -1712,6 +1714,7 @@ 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 session-track-transaction-info OFF
session-track-user-variables FALSE
show-slave-auth-info FALSE show-slave-auth-info FALSE
silent-startup FALSE silent-startup FALSE
skip-grant-tables TRUE skip-grant-tables TRUE
......
...@@ -29,3 +29,13 @@ SET NAMES 'utf8'; ...@@ -29,3 +29,13 @@ SET NAMES 'utf8';
# tracking info off once # tracking info off once
SET NAMES 'big5'; SET NAMES 'big5';
SET @@session.session_track_system_variables= default; 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'; ...@@ -23,3 +23,14 @@ SET NAMES 'big5';
--disable_session_track_info --disable_session_track_info
SET @@session.session_track_system_variables= default; 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; ...@@ -12,19 +12,13 @@ SELECT @@session.session_track_system_variables;
autocommit,character_set_client,character_set_connection,character_set_results,time_zone autocommit,character_set_client,character_set_connection,character_set_results,time_zone
# via INFORMATION_SCHEMA.GLOBAL_VARIABLES # 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 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_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_system_variables' ORDER BY VARIABLE_NAME;
VARIABLE_NAME VARIABLE_VALUE 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_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
......
...@@ -3453,6 +3453,16 @@ NUMERIC_BLOCK_SIZE NULL ...@@ -3453,6 +3453,16 @@ NUMERIC_BLOCK_SIZE NULL
ENUM_VALUE_LIST OFF,STATE,CHARACTERISTICS ENUM_VALUE_LIST OFF,STATE,CHARACTERISTICS
READ_ONLY NO READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED 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_NAME SKIP_EXTERNAL_LOCKING
VARIABLE_SCOPE GLOBAL VARIABLE_SCOPE GLOBAL
VARIABLE_TYPE BOOLEAN VARIABLE_TYPE BOOLEAN
......
...@@ -12,10 +12,10 @@ SELECT @@session.session_track_system_variables; ...@@ -12,10 +12,10 @@ SELECT @@session.session_track_system_variables;
--echo --echo
--echo # via INFORMATION_SCHEMA.GLOBAL_VARIABLES --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 --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. # 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;
......
...@@ -4671,6 +4671,10 @@ update_hash(user_var_entry *entry, bool set_null, void *ptr, size_t length, ...@@ -4671,6 +4671,10 @@ update_hash(user_var_entry *entry, bool set_null, void *ptr, size_t length,
entry->unsigned_flag= unsigned_arg; entry->unsigned_flag= unsigned_arg;
} }
entry->type=type; entry->type=type;
#ifndef EMBEDDED_LIBRARY
THD *thd= current_thd;
thd->session_tracker.user_variables.mark_as_changed(thd, entry);
#endif
return 0; return 0;
} }
...@@ -4760,7 +4764,7 @@ longlong user_var_entry::val_int(bool *null_value) const ...@@ -4760,7 +4764,7 @@ longlong user_var_entry::val_int(bool *null_value) const
/** Get the value of a variable as a string. */ /** Get the value of a variable as a string. */
String *user_var_entry::val_str(bool *null_value, String *str, String *user_var_entry::val_str(bool *null_value, String *str,
uint decimals) uint decimals) const
{ {
if ((*null_value= (value == 0))) if ((*null_value= (value == 0)))
return (String*) 0; return (String*) 0;
......
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
#include "sql_plugin.h" #include "sql_plugin.h"
#include "hash.h"
#include "table.h" #include "table.h"
#include "rpl_gtid.h" #include "rpl_gtid.h"
#include "sql_class.h" #include "sql_class.h"
...@@ -1182,6 +1181,38 @@ bool Session_state_change_tracker::store(THD *thd, String *buf) ...@@ -1182,6 +1181,38 @@ bool Session_state_change_tracker::store(THD *thd, String *buf)
return false; 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 @@ ...@@ -19,12 +19,14 @@
#include "m_string.h" #include "m_string.h"
#include "thr_lock.h" #include "thr_lock.h"
#include "sql_hset.h"
#ifndef EMBEDDED_LIBRARY #ifndef EMBEDDED_LIBRARY
/* forward declarations */ /* forward declarations */
class THD; class THD;
class set_var; class set_var;
class String; class String;
class user_var_entry;
enum enum_session_tracker enum enum_session_tracker
...@@ -33,6 +35,7 @@ enum enum_session_tracker ...@@ -33,6 +35,7 @@ enum enum_session_tracker
CURRENT_SCHEMA_TRACKER, /* Current schema */ CURRENT_SCHEMA_TRACKER, /* Current schema */
SESSION_STATE_CHANGE_TRACKER, SESSION_STATE_CHANGE_TRACKER,
TRANSACTION_INFO_TRACKER, /* Transaction state */ TRANSACTION_INFO_TRACKER, /* Transaction state */
USER_VARIABLES_TRACKER,
SESSION_TRACKER_END /* must be the last */ SESSION_TRACKER_END /* must be the last */
}; };
...@@ -387,6 +390,35 @@ class Transaction_state_tracker : public State_tracker ...@@ -387,6 +390,35 @@ class Transaction_state_tracker : public State_tracker
thd->session_tracker.transaction_info.X; } while(0) 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 Session_tracker
...@@ -415,6 +447,7 @@ class Session_tracker ...@@ -415,6 +447,7 @@ class Session_tracker
Session_state_change_tracker state_change; Session_state_change_tracker state_change;
Transaction_state_tracker transaction_info; Transaction_state_tracker transaction_info;
Session_sysvars_tracker sysvars; Session_sysvars_tracker sysvars;
User_variables_tracker user_variables;
Session_tracker() Session_tracker()
{ {
...@@ -422,6 +455,7 @@ class Session_tracker ...@@ -422,6 +455,7 @@ class Session_tracker
m_trackers[CURRENT_SCHEMA_TRACKER]= &current_schema; m_trackers[CURRENT_SCHEMA_TRACKER]= &current_schema;
m_trackers[SESSION_STATE_CHANGE_TRACKER]= &state_change; m_trackers[SESSION_STATE_CHANGE_TRACKER]= &state_change;
m_trackers[TRANSACTION_INFO_TRACKER]= &transaction_info; m_trackers[TRANSACTION_INFO_TRACKER]= &transaction_info;
m_trackers[USER_VARIABLES_TRACKER]= &user_variables;
} }
void enable(THD *thd) void enable(THD *thd)
......
...@@ -56,7 +56,6 @@ ...@@ -56,7 +56,6 @@
#include "rpl_filter.h" #include "rpl_filter.h"
#include "sql_table.h" // build_table_filename #include "sql_table.h" // build_table_filename
#include "datadict.h" // dd_frm_is_view() #include "datadict.h" // dd_frm_is_view()
#include "sql_hset.h" // Hash_set
#include "rpl_rli.h" // rpl_group_info #include "rpl_rli.h" // rpl_group_info
#ifdef __WIN__ #ifdef __WIN__
#include <io.h> #include <io.h>
......
...@@ -1750,6 +1750,7 @@ THD::~THD() ...@@ -1750,6 +1750,7 @@ THD::~THD()
/* trick to make happy memory accounting system */ /* trick to make happy memory accounting system */
#ifndef EMBEDDED_LIBRARY #ifndef EMBEDDED_LIBRARY
session_tracker.sysvars.deinit(); session_tracker.sysvars.deinit();
session_tracker.user_variables.deinit();
#endif //EMBEDDED_LIBRARY #endif //EMBEDDED_LIBRARY
if (status_var.local_memory_used != 0) if (status_var.local_memory_used != 0)
......
...@@ -766,6 +766,7 @@ typedef struct system_variables ...@@ -766,6 +766,7 @@ typedef struct system_variables
ulong session_track_transaction_info; 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;
my_bool session_track_user_variables;
my_bool tcp_nodelay; my_bool tcp_nodelay;
ulong threadpool_priority; ulong threadpool_priority;
...@@ -6319,7 +6320,7 @@ class user_var_entry ...@@ -6319,7 +6320,7 @@ class user_var_entry
double val_real(bool *null_value); double val_real(bool *null_value);
longlong val_int(bool *null_value) const; 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); my_decimal *val_decimal(bool *null_value, my_decimal *result);
CHARSET_INFO *charset() const { return m_charset; } CHARSET_INFO *charset() const { return m_charset; }
void set_charset(CHARSET_INFO *cs) { m_charset= cs; } void set_charset(CHARSET_INFO *cs) { m_charset= cs; }
......
...@@ -38,6 +38,13 @@ class Hash_set ...@@ -38,6 +38,13 @@ class Hash_set
m_hash.get_key= (my_hash_get_key)K; m_hash.get_key= (my_hash_get_key)K;
m_hash.charset= cs; 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 Destroy the hash by freeing the buckets table. Does
not call destructors for the elements. not call destructors for the elements.
...@@ -58,13 +65,8 @@ class Hash_set ...@@ -58,13 +65,8 @@ class Hash_set
bool insert(T *value) bool insert(T *value)
{ {
my_hash_init_opt(&m_hash, m_hash.charset, START_SIZE, 0, 0, my_hash_init_opt(&m_hash, m_hash.charset, START_SIZE, 0, 0,
m_hash.get_key, 0, MYF(0)); m_hash.get_key, 0, HASH_UNIQUE);
size_t key_len; return my_hash_insert(&m_hash, reinterpret_cast<const uchar*>(value));
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;
} }
bool remove(T *value) bool remove(T *value)
{ {
...@@ -78,6 +80,8 @@ class Hash_set ...@@ -78,6 +80,8 @@ class Hash_set
bool is_empty() const { return m_hash.records == 0; } bool is_empty() const { return m_hash.records == 0; }
/** Returns the number of unique elements. */ /** Returns the number of unique elements. */
size_t size() const { return static_cast<size_t>(m_hash.records); } 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 const T* at(size_t i) const
{ {
return reinterpret_cast<T*>(my_hash_element(const_cast<HASH*>(&m_hash), i)); 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( ...@@ -6378,6 +6378,22 @@ static Sys_var_mybool Sys_session_track_state_change(
ON_CHECK(0), ON_CHECK(0),
ON_UPDATE(update_session_track_state_change)); 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 #endif //EMBEDDED_LIBRARY
static Sys_var_uint Sys_in_subquery_conversion_threshold( static Sys_var_uint Sys_in_subquery_conversion_threshold(
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment