From 8afeb616ed1d07a3876c6cd3defe33bb4f9228e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Canna=C3=B2?= Date: Wed, 11 Aug 2021 00:14:54 +0200 Subject: [PATCH] Added test for connections timeout Added test that verifies that client connections are dropped because of: - mysql-wait_timeout - mysql-max_transaction_time IT also helped finding a bug in how mysql-max_transaction_time was handled --- lib/MySQL_Thread.cpp | 2 +- test/tap/tap/utils.cpp | 4 +- test/tap/tests/kill_connection2-t.cpp | 187 ++++++++++++++++++++++++++ 3 files changed, 191 insertions(+), 2 deletions(-) create mode 100644 test/tap/tests/kill_connection2-t.cpp diff --git a/lib/MySQL_Thread.cpp b/lib/MySQL_Thread.cpp index 946942294..d662d23ff 100644 --- a/lib/MySQL_Thread.cpp +++ b/lib/MySQL_Thread.cpp @@ -3306,7 +3306,7 @@ void MySQL_Thread::ProcessAllSessions_MaintenanceLoop(MySQL_Session *sess, unsig if (sess->active_transactions == 0) { sess->transaction_started_at = 0; } else { - if (sess_active_transactions == 0) { + if (sess->transaction_started_at == 0) { sess->transaction_started_at = curtime; } } diff --git a/test/tap/tap/utils.cpp b/test/tap/tap/utils.cpp index 2c2a0b97e..b3ec73260 100644 --- a/test/tap/tap/utils.cpp +++ b/test/tap/tap/utils.cpp @@ -169,7 +169,9 @@ int add_more_rows_test_sbtest1(int num_rows, MYSQL *mysql) { q << "INSERT INTO test.sbtest1 (k, c, pad) values "; bool put_comma = false; int i=0; - for (i=0; i num_rows) cnt = num_rows; + for (i=0; i +#include +#include +#include +#include +#include + +#include "tap.h" +#include "command_line.h" +#include "utils.h" + + +/* +This test verifies that client connections are dropped because of: +- mysql-wait_timeout +- mysql-max_transaction_time +*/ + +const int NUM_CONNS = 5; + +int run_q(MYSQL *mysql, const char *q) { + MYSQL_QUERY(mysql,q); + return 0; +} + +MYSQL * conns[NUM_CONNS]; +unsigned long mythreadid[NUM_CONNS]; + +int create_connections(CommandLine& cl) { + for (int i = 0; i < NUM_CONNS ; i++) { + MYSQL * mysql = mysql_init(NULL); + if (!mysql) { + fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(mysql)); + return exit_status(); + } + + if (!mysql_real_connect(mysql, cl.host, cl.username, cl.password, NULL, cl.port, NULL, 0)) { + fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(mysql)); + return exit_status(); + } + conns[i] = mysql; + } + return 0; +} + +int find_tids() { + for (int i = 0; i < NUM_CONNS ; i++) { + MYSQL * mysql = conns[i]; + unsigned long tid; + MYSQL_ROW row; + MYSQL_QUERY(mysql, "SELECT CONNECTION_ID()"); + MYSQL_RES * proxy_res = mysql_store_result(mysql); + while ((row = mysql_fetch_row(proxy_res))) { + tid = atoll(row[0]); + } + mysql_free_result(proxy_res); + ok(tid == mysql_thread_id(mysql), "tid: %lu, mysql_thread_id(): %lu", tid, mysql_thread_id(mysql)); + mythreadid[i] = tid; + } + + return 0; +} + +int main(int argc, char** argv) { + CommandLine cl; + + int np = 0; + np += NUM_CONNS ; // to get connection id + np += NUM_CONNS ; // failed query on killed connection due to timeout + np += NUM_CONNS ; // to get connection id + np += NUM_CONNS ; // to run BEGIN + np += NUM_CONNS ; // to run first DO 1 + np += NUM_CONNS ; // failed query on killed connection due transaction timeout + + plan(np); + + if (cl.getEnv()) { + diag("Failed to get the required environmental variables."); + return -1; + } + + + MYSQL* proxysql_admin = mysql_init(NULL); + // Initialize connections + if (!proxysql_admin) { + fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(proxysql_admin)); + return -1; + } + + if (!mysql_real_connect(proxysql_admin, cl.host, cl.admin_username, cl.admin_password, NULL, cl.admin_port, NULL, 0)) { + fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(proxysql_admin)); + return -1; + } + + MYSQL_QUERY(proxysql_admin, "SET mysql-have_ssl='true'"); + MYSQL_QUERY(proxysql_admin, "SET mysql-have_compress='true'"); + MYSQL_QUERY(proxysql_admin, "SET mysql-auto_increment_delay_multiplex=10"); // to ensure multiplexing stays disabled + MYSQL_QUERY(proxysql_admin, "SET mysql-wait_timeout=6000"); // to force a close + MYSQL_QUERY(proxysql_admin, "LOAD MYSQL VARIABLES TO RUNTIME"); + + int rc = 0; + rc = create_connections(cl); + if (rc != 0) { + return exit_status(); + } + + for (int i = 0; i < NUM_CONNS ; i++) { + MYSQL * mysql = conns[i]; + if (i == 0) { + if (create_table_test_sbtest1(10,mysql)) { + fprintf(stderr, "File %s, line %d, Error: create_table_test_sbtest1() failed\n", __FILE__, __LINE__); + return exit_status(); + } + } else { + if (add_more_rows_test_sbtest1(10,mysql)) { + fprintf(stderr, "File %s, line %d, Error: add_more_rows_sbtest1() failed\n", __FILE__, __LINE__); + return exit_status(); + } + } + } + + rc = find_tids(); + if (rc != 0) { + return exit_status(); + } + + diag("Sleeping for 10 seconds"); + for (int i = 0; i < 10 ; i++) { + fprintf(stderr,"."); + sleep(1); + } + fprintf(stderr,"\n"); + + for (int i = 0; i < NUM_CONNS ; i++) { + MYSQL * mysql = conns[i]; + int rc = run_q(mysql, "DO 1"); + ok(rc != 0, (rc == 0 ? "Connection still alive" : "Connection killed")); + } + + MYSQL_QUERY(proxysql_admin, "SET mysql-wait_timeout=3600000"); // to not force a close on wait + MYSQL_QUERY(proxysql_admin, "SET mysql-max_transaction_time=17000"); // to force a close on transaction + MYSQL_QUERY(proxysql_admin, "LOAD MYSQL VARIABLES TO RUNTIME"); + + rc = create_connections(cl); + if (rc != 0) { + return exit_status(); + } + + rc = find_tids(); + if (rc != 0) { + return exit_status(); + } + + for (int i = 0; i < NUM_CONNS ; i++) { + MYSQL * mysql = conns[i]; + int rc = run_q(mysql, "BEGIN"); + ok(rc == 0, "Running BEGIN on new connection"); + } + + diag("Sleeping for 12 seconds"); + for (int i = 0; i < 12 ; i++) { + fprintf(stderr,"."); + sleep(1); + } + fprintf(stderr,"\n"); + + for (int i = 0; i < NUM_CONNS ; i++) { + MYSQL * mysql = conns[i]; + int rc = run_q(mysql, "DO 1"); + ok(rc == 0, (rc == 0 ? "Connection still alive" : "Connection killed")); + } + + diag("Sleeping for 12 seconds"); + for (int i = 0; i < 12 ; i++) { + fprintf(stderr,"."); + sleep(1); + } + fprintf(stderr,"\n"); + + for (int i = 0; i < NUM_CONNS ; i++) { + MYSQL * mysql = conns[i]; + int rc = run_q(mysql, "DO 1"); + ok(rc != 0, (rc == 0 ? "Connection still alive" : "Connection killed")); + } + + return exit_status(); +}