Skip to content

[WIP] Setting client side wait_timeout #4901

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

Open
wants to merge 3 commits into
base: v3.0
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions include/Base_Session.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ class Base_Session {
int pending_connect;
enum proxysql_session_type session_type;
int warning_in_hg;
unsigned long long wait_timeout; //in milliseconds

// bool
bool autocommit;
Expand Down
32 changes: 32 additions & 0 deletions lib/MySQL_Session.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -681,6 +681,7 @@ MySQL_Session::MySQL_Session() {
last_HG_affected_rows = -1; // #1421 : advanced support for LAST_INSERT_ID()
proxysql_node_address = NULL;
use_ldap_auth = false;
wait_timeout = mysql_thread___wait_timeout;
}

/**
Expand Down Expand Up @@ -6414,6 +6415,37 @@ bool MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C
proxy_debug(PROXY_DEBUG_MYSQL_COM, 8, "Changing connection charset to %d\n", c->nr);
client_myds->myconn->set_charset(c->nr, NAMES);
}
} else if (var == "wait_timeout") {
std::string value = *values++;
proxy_debug(PROXY_DEBUG_MYSQL_COM, 5, "Client requested SET wait_timeout = %s\n", value.c_str());

unsigned long long client_timeout = 0;
try {
client_timeout = std::stoull(value) * 1000;
} catch (const std::exception& e) {
char errmsg[128];
snprintf(errmsg, sizeof(errmsg),
"Incorrect argument type wait_timeout value: %s", value.c_str());
client_myds->DSS = STATE_QUERY_SENT_NET;
client_myds->myprot.generate_pkt_ERR(true, nullptr, nullptr, 1, 1231, (char *)"42000", errmsg, true);
client_myds->DSS = STATE_SLEEP;
status = WAITING_CLIENT_DATA;
return true;
}

// Warn if client's value exceeds current global timeout
if (client_timeout > static_cast<unsigned long long>(mysql_thread___wait_timeout)) {
proxy_warning("Client [%s] (user: %s) requested wait_timeout = %llu ms, exceeds the global mysql-wait_timeout = %d ms. Global timeout will still be enforced.",
client_myds->myconn->connected_host_details.ip,
client_myds->myconn->userinfo->username,
client_timeout,
mysql_thread___wait_timeout);
}

if (wait_timeout != client_timeout) {
wait_timeout = client_timeout;
proxy_debug(PROXY_DEBUG_MYSQL_COM, 8, "Changing connection wait_timeout to %llu ms\n", client_timeout);
}
} else if (var == "tx_isolation") {
std::string value1 = *values;
proxy_debug(PROXY_DEBUG_MYSQL_COM, 5, "Processing SET tx_isolation value %s\n", value1.c_str());
Expand Down
9 changes: 7 additions & 2 deletions lib/MySQL_Thread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3790,7 +3790,12 @@ void MySQL_Thread::ProcessAllSessions_MaintenanceLoop(MySQL_Session *sess, unsig
* @param curtime The current time, in milliseconds.
* @param sess The MySQL session to handle.
*/
if ( (sess_time/1000 > (unsigned long long)mysql_thread___max_transaction_idle_time) || (sess_time/1000 > (unsigned long long)mysql_thread___wait_timeout) ) {
unsigned long long effective_wait_timeout = std::min(
static_cast<unsigned long long>(mysql_thread___wait_timeout),
static_cast<unsigned long long>(sess->wait_timeout)
);
if ((sess_time/1000 > static_cast<unsigned long long>(mysql_thread___max_transaction_idle_time)) ||
(sess_time/1000 > effective_wait_timeout)) {
//numTrx = sess->NumActiveTransactions();
numTrx = sess->active_transactions;
if (numTrx) {
Expand All @@ -3803,7 +3808,7 @@ void MySQL_Thread::ProcessAllSessions_MaintenanceLoop(MySQL_Session *sess, unsig
}
} else {
// the session is idle, kill it
if (sess_time/1000 > (unsigned long long)mysql_thread___wait_timeout) {
if (sess_time/1000 > (unsigned long long)sess->wait_timeout) {
sess->killed=true;
if (sess->client_myds) {
proxy_warning("Killing client connection %s:%d because inactive for %llums\n",sess->client_myds->addr.addr,sess->client_myds->addr.port, sess_time/1000);
Expand Down