-
Notifications
You must be signed in to change notification settings - Fork 1.1k
MySQL: Track session-specific system variables changes #5166
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: v3.0
Are you sure you want to change the base?
Changes from all commits
4b9c083
36442e4
f0ac86c
b2f201e
6e6a9bb
f82bcdf
0bb9d0a
cd63254
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -336,6 +336,49 @@ struct th_metrics_map_idx { | |||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||
| * @brief Configuration structure for session variable tracking functionality. | ||||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||||
| * === PR 5166: Session Variable Tracking Architecture === | ||||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||||
| * This PR introduces comprehensive tracking of session-specific system variables | ||||||||||||||||||||||||||||||||||||||||||||||||
| * by leveraging MySQL's native session tracking capabilities. The overall workflow | ||||||||||||||||||||||||||||||||||||||||||||||||
| * consists of three main phases: | ||||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||||
| * 1. CONFIGURATION PHASE: | ||||||||||||||||||||||||||||||||||||||||||||||||
| * - Global enable/disable via mysql-session_track_variables variable | ||||||||||||||||||||||||||||||||||||||||||||||||
| * - Per-connection tracking state managed via flags in MySQL_Connection | ||||||||||||||||||||||||||||||||||||||||||||||||
| * - New session states handle configuration of tracking on backends | ||||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||||
| * 2. BACKEND SETUP PHASE: | ||||||||||||||||||||||||||||||||||||||||||||||||
| * - When enabled, configure session_track_system_variables="*" | ||||||||||||||||||||||||||||||||||||||||||||||||
| * - Configure session_track_state_change=ON | ||||||||||||||||||||||||||||||||||||||||||||||||
| * - MySQL server then automatically tracks all system variable changes | ||||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||||
| * 3. PROCESSING PHASE: | ||||||||||||||||||||||||||||||||||||||||||||||||
| * - After each query, check SERVER_SESSION_STATE_CHANGED flag | ||||||||||||||||||||||||||||||||||||||||||||||||
| * - Extract variable changes via MySQL's session tracking protocol | ||||||||||||||||||||||||||||||||||||||||||||||||
| * - Update both client and server variable maps for state consistency | ||||||||||||||||||||||||||||||||||||||||||||||||
| * - Special handling for character set variables (name → ID conversion) | ||||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||||
| * BENEFITS: | ||||||||||||||||||||||||||||||||||||||||||||||||
| * - Captures changes that SQL parsing alone cannot detect (stored procedures, etc.) | ||||||||||||||||||||||||||||||||||||||||||||||||
| * - Redundant tracking ensures accurate client/backend state synchronization | ||||||||||||||||||||||||||||||||||||||||||||||||
| * - Leverages MySQL server's native capabilities for reliability | ||||||||||||||||||||||||||||||||||||||||||||||||
| * - Performance optimized: only processes when session state actually changes | ||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||
| struct session_track_variables { | ||||||||||||||||||||||||||||||||||||||||||||||||
| enum mode { | ||||||||||||||||||||||||||||||||||||||||||||||||
| // Disabled; default mode | ||||||||||||||||||||||||||||||||||||||||||||||||
| DISABLED = 0, | ||||||||||||||||||||||||||||||||||||||||||||||||
| // Enable session tracking if backend supports it | ||||||||||||||||||||||||||||||||||||||||||||||||
| OPTIONAL, | ||||||||||||||||||||||||||||||||||||||||||||||||
| // Enforce session tracking; connection fails if backend does | ||||||||||||||||||||||||||||||||||||||||||||||||
| // not support CLIENT_DEPRECATE_EOF and CLIENT_SESSION_TRACKING | ||||||||||||||||||||||||||||||||||||||||||||||||
| ENFORCED | ||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||
| * @brief Structure holding the data for a Client_Host_Cache entry. | ||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -591,6 +634,16 @@ class MySQL_Threads_Handler | |||||||||||||||||||||||||||||||||||||||||||||||
| int processlist_max_query_length; | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| bool ignore_min_gtid_annotations; | ||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||
| * @brief Configuration flag to enable/disable session variable tracking. | ||||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||||
| * When set to session_track_variables::ENABLED (1), ProxySQL will configure | ||||||||||||||||||||||||||||||||||||||||||||||||
| * backend connections to track system variable changes using MySQL's | ||||||||||||||||||||||||||||||||||||||||||||||||
| * session_track_system_variables and session_track_state_change capabilities. | ||||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||||
| * Default: session_track_variables::DISABLED (0) | ||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||
| int session_track_variables; | ||||||||||||||||||||||||||||||||||||||||||||||||
| } variables; | ||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+637
to
647
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix docs: The comment on Proposed fix- * When set to session_track_variables::ENABLED (1), ProxySQL will configure
+ * When set to session_track_variables::OPTIONAL (1) or
+ * session_track_variables::ENFORCED (2), ProxySQL will configure
* backend connections to track system variable changes using MySQL's
* session_track_system_variables and session_track_state_change capabilities.📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||
| struct { | ||||||||||||||||||||||||||||||||||||||||||||||||
| unsigned int mirror_sessions_current; | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -38,6 +38,10 @@ MySrvC *MyHGC::get_random_MySrvC(char * gtid_uuid, uint64_t gtid_trxid, int max_ | |
| for (j=0; j<l; j++) { | ||
| mysrvc=mysrvs->idx(j); | ||
| if (mysrvc->get_status() == MYSQL_SERVER_STATUS_ONLINE) { // consider this server only if ONLINE | ||
| // skip servers that are in backoff period | ||
| if (mysrvc->server_backoff_time > sess->thread->curtime) | ||
| continue; | ||
|
|
||
|
Comment on lines
40
to
+44
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: git ls-files | head -20Repository: sysown/proxysql Length of output: 799 🏁 Script executed: find . -name "*.h" -o -name "*.hpp" | grep -i "mysql\|hgc" | head -20Repository: sysown/proxysql Length of output: 612 🏁 Script executed: ls -la lib/MyHGC.cpp 2>/dev/null && echo "File exists" || echo "Checking structure..."Repository: sysown/proxysql Length of output: 134 🏁 Script executed: # Get codebase structure
fd --type f --name "*.cpp" --name "*.h" | grep -E "(MyHGC|mysql)" | head -30Repository: sysown/proxysql Length of output: 309 🏁 Script executed: cat -n lib/MyHGC.cpp | head -60Repository: sysown/proxysql Length of output: 2925 🏁 Script executed: # Search for server_backoff_time definition
rg "server_backoff_time" --type-list | head -5
rg "server_backoff_time" -B 2 -A 2 | head -100Repository: sysown/proxysql Length of output: 2462 🏁 Script executed: # Find all writes to server_backoff_time
rg "server_backoff_time\s*=" -B 3 -A 3Repository: sysown/proxysql Length of output: 859 🏁 Script executed: # Find the header definition with context
rg -A 5 -B 5 "unsigned long long server_backoff_time"Repository: sysown/proxysql Length of output: 919 🏁 Script executed: # Check for any mutex/synchronization related to MySrvC
rg "MySrvC" include/MySQL_HostGroups_Manager.h | head -20Repository: sysown/proxysql Length of output: 915 🏁 Script executed: # Search for mutex or lock context around MySrvC or server_backoff_time
rg -B 10 "server_backoff_time = " lib/MySQL_Session.cpp | head -40Repository: sysown/proxysql Length of output: 792 🏁 Script executed: # Look for threading/locks in relation to MySrvC
rg "pthread_mutex\|lock\|rwlock" include/MySQL_HostGroups_Manager.h -A 2 -B 2Repository: sysown/proxysql Length of output: 41 🏁 Script executed: # Check MyHGC context - who calls get_random_MySrvC
rg "get_random_MySrvC" -B 5 | head -50Repository: sysown/proxysql Length of output: 3145 🏁 Script executed: # Check if there's a lock protecting MySrvC or mysrvs
rg -B 5 -A 5 "class MySrvC" include/MySQL_HostGroups_Manager.h | head -80Repository: sysown/proxysql Length of output: 800 🏁 Script executed: # Look for locks in the hostgroup management
rg "pthread_rwlock\|pthread_mutex\|rwlock_write\|wrlock\|rdlock" include/MySQL_HostGroups_Manager.h | head -20Repository: sysown/proxysql Length of output: 41 🏁 Script executed: # Check the broader context of MySQL_Session write
rg -B 20 "server_backoff_time = thread->curtime" lib/MySQL_Session.cpp | head -60Repository: sysown/proxysql Length of output: 1115 🏁 Script executed: # Check if there are thread contexts for writes vs reads
rg "MySQL_Session\|MySQL_Thread" lib/MyHGC.cpp | head -20Repository: sysown/proxysql Length of output: 41 🏁 Script executed: # Check BaseHGC for any locking mechanism
rg "class BaseHGC" -A 30 include/Base_HostGroups_Manager.h | head -60Repository: sysown/proxysql Length of output: 1817 🏁 Script executed: # Look for rwlock or mutex protecting server lists
rg "rwlock\|pthread_mutex" include/MySQL_HostGroups_Manager.h -B 5 -A 5Repository: sysown/proxysql Length of output: 41 🏁 Script executed: # Check MySQL_Thread structure and curtime
rg "class MySQL_Thread" -A 50 include/MySQL_Thread.h | head -80Repository: sysown/proxysql Length of output: 1908 🏁 Script executed: # Check if there's synchronization around get_random_MySrvC calls
rg -B 10 "myhgc->get_random_MySrvC" lib/Base_HostGroups_Manager.cpp | head -50Repository: sysown/proxysql Length of output: 456 🏁 Script executed: # Check MySrvList structure for any locks
rg "class MySrvList\|class BaseSrvList" -A 40 include/MySQL_HostGroups_Manager.h | head -80Repository: sysown/proxysql Length of output: 41 🏁 Script executed: # Examine the actual threading - is get_random_MySrvC protected by any lock?
rg "MyHGM\|myhgc\|get_random_MySrvC" lib/MySQL_Session.cpp -B 3 -A 3 | head -80Repository: sysown/proxysql Length of output: 41 🏁 Script executed: # Search more broadly for MySrvList
fd "MySQL_HostGroups_Manager" --type fRepository: sysown/proxysql Length of output: 126 🏁 Script executed: # Try to find MySrvList definition
rg "class MySrvList" -A 50Repository: sysown/proxysql Length of output: 26083 🏁 Script executed: # Check if there's a global lock protecting MyHGM or MyHGC access
rg "MyHGM\|MyHGC_lookup" include/*.h -B 2 -A 2 | head -100Repository: sysown/proxysql Length of output: 41 🏁 Script executed: # Look for synchronization in get_random_MySrvC itself
cat -n lib/MyHGC.cpp | sed -n '14,120p'Repository: sysown/proxysql Length of output: 6052 🏁 Script executed: # Final check: confirm multiple threads can access same MySrvC by searching for thread pool/worker threads
rg "worker.*thread\|pthread_create" include/MySQL_Thread.h -A 3 -B 3 | head -40Repository: sysown/proxysql Length of output: 41 Use atomic load to prevent data races in backoff check.
Proposed fix- if (mysrvc->server_backoff_time > sess->thread->curtime)
+ if (mysrvc->server_backoff_time.load(std::memory_order_relaxed) > sess->thread->curtime)
continue;Also update the field declaration in include/MySQL_HostGroups_Manager.h from 🤖 Prompt for AI Agents |
||
| if (mysrvc->myhgc->num_online_servers.load(std::memory_order_relaxed) <= mysrvc->myhgc->attributes.max_num_online_servers) { // number of online servers in HG is within configured range | ||
| if (mysrvc->ConnectionsUsed->conns_length() < mysrvc->max_connections) { // consider this server only if didn't reach max_connections | ||
| if (mysrvc->current_latency_us < (mysrvc->max_latency_us ? mysrvc->max_latency_us : mysql_thread___default_max_latency_ms*1000)) { // consider the host only if not too far | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -1111,9 +1111,13 @@ bool MySQL_Protocol::generate_pkt_initial_handshake(bool send, void **ptr, unsig | |||||||||||||||||||||||||
| // variable. This is the first step of ensuring that client connections doesn't | ||||||||||||||||||||||||||
| // enable 'CLIENT_DEPRECATE_EOF' unless explicitly stated by 'mysql-enable_client_deprecate_eof'. | ||||||||||||||||||||||||||
| // Second step occurs during client handshake response (process_pkt_handshake_response). | ||||||||||||||||||||||||||
| if (deprecate_eof_active && mysql_thread___enable_client_deprecate_eof) { | ||||||||||||||||||||||||||
| extended_capabilities |= CLIENT_DEPRECATE_EOF; | ||||||||||||||||||||||||||
| if (deprecate_eof_active) { | ||||||||||||||||||||||||||
| if (mysql_thread___enable_client_deprecate_eof | ||||||||||||||||||||||||||
| || mysql_thread___session_track_variables == session_track_variables::ENFORCED) { | ||||||||||||||||||||||||||
| extended_capabilities |= CLIENT_DEPRECATE_EOF; | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
|
Comment on lines
+1114
to
+1120
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: find . -name "MySQL_Protocol.cpp" -type fRepository: sysown/proxysql Length of output: 83 🏁 Script executed: # Get context around the lines mentioned in the review
grep -n "deprecate_eof_active" . -r --include="*.cpp" | head -20Repository: sysown/proxysql Length of output: 2205 🏁 Script executed: # Search for PPHR_2 and the strip logic mentioned
grep -n "PPHR_2" . -r --include="*.cpp" | head -10Repository: sysown/proxysql Length of output: 309 🏁 Script executed: # Find the full function context around line 1114-1120
sed -n '1100,1130p' lib/MySQL_Protocol.cppRepository: sysown/proxysql Length of output: 1899 🏁 Script executed: # Search for the CLIENT_DEPRECATE_EOF strip logic mentioned
grep -n "CLIENT_DEPRECATE_EOF" lib/MySQL_Protocol.cppRepository: sysown/proxysql Length of output: 967 🌐 Web query:
💡 Result: Summary of CLIENT_DEPRECATE_EOF semantics (protocol-level)
Sources
🌐 Web query:
💡 Result: Do you mean the server/session-tracking "ENFORCED" SQL mode or something else? (I ask because I can’t find an authoritative MySQL doc that uses the exact phrase "session tracking ENFORCED mode".) Meanwhile: brief summary of how CLIENT_DEPRECATE_EOF interacts with session-state tracking
Sources
If you want, I can: (a) show the exact packet layout examples, (b) point to where connectors (e.g., libmysqlclient, Connector/J, Connector/C) handle CLIENT_DEPRECATE_EOF, or (c) help debug a specific client/connector problem you’re seeing. 🏁 Script executed: sed -n '1595,1615p' lib/MySQL_Protocol.cppRepository: sysown/proxysql Length of output: 1225 🏁 Script executed: # Get more context to understand the full condition
sed -n '1580,1620p' lib/MySQL_Protocol.cppRepository: sysown/proxysql Length of output: 2270 ENFORCED mode advertises In This causes a protocol violation: the handshake advertises support for OK packets (not EOF packets) as result terminators, but the client handshake response processing removes that flag regardless. Since session-state tracking (ENFORCED mode) requires OK packets to carry state data, this inconsistency breaks the negotiated capability set. The strip logic in PPHR_2 should mirror the advertise logic: Proposed fix (in PPHR_2, around line 1606)- if (!mysql_thread___enable_client_deprecate_eof) {
+ if (
+ !mysql_thread___enable_client_deprecate_eof
+ && mysql_thread___session_track_variables != session_track_variables::ENFORCED
+ ) {
vars1.capabilities &= ~CLIENT_DEPRECATE_EOF;
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||
| // Copy the 'capability_flags_2' | ||||||||||||||||||||||||||
| uint16_t upper_word = static_cast<uint16_t>(extended_capabilities >> 16); | ||||||||||||||||||||||||||
| memcpy(_ptr+l, static_cast<void*>(&upper_word), sizeof(upper_word)); l += sizeof(upper_word); | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: sysown/proxysql
Length of output: 704
🏁 Script executed:
Repository: sysown/proxysql
Length of output: 10049
🏁 Script executed:
Repository: sysown/proxysql
Length of output: 93
🏁 Script executed:
Repository: sysown/proxysql
Length of output: 1180
🏁 Script executed:
Repository: sysown/proxysql
Length of output: 985
🏁 Script executed:
Repository: sysown/proxysql
Length of output: 886
🏁 Script executed:
Repository: sysown/proxysql
Length of output: 1413
🏁 Script executed:
Repository: sysown/proxysql
Length of output: 1411
Make
server_backoff_timethread-safe (atomic or lock-protected).server_backoff_timeis written without synchronization inMySQL_Session::handle_session_track_capabilities()(line 8595) and read without locking inMyHGC::get_random_MySrvC()(line 42) andMySQL_Thread.cpp(line 5746) from different threads. This creates a data race that could cause torn reads on some platforms.The timebase is microseconds (confirmed by the write:
thread->curtime + (30 * 1000000)for 30 seconds), which is consistent withcurtime. The comment in the code adequately documents this, but the field itself needs synchronization.Proposed fix