From 6156125905e2ac1c830c58e7b560e3ae110fd721 Mon Sep 17 00:00:00 2001 From: Rahim Kanji Date: Wed, 10 Jan 2024 16:53:39 +0500 Subject: [PATCH 1/2] Fixed ProxySQL crash on querying stats_mysql_query_digest and stats_mysql_query_digest_rest --- lib/Query_Processor.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/Query_Processor.cpp b/lib/Query_Processor.cpp index 768dcc45d9..85f1b499db 100644 --- a/lib/Query_Processor.cpp +++ b/lib/Query_Processor.cpp @@ -1154,9 +1154,6 @@ unsigned long long Query_Processor::purge_query_digests(bool async_purge, bool p unsigned long long Query_Processor::purge_query_digests_async(char **msg) { unsigned long long ret = 0; - pthread_rwlock_wrlock(&digest_rwlock); - - umap_query_digest digest_umap_aux; umap_query_digest_text digest_text_umap_aux; pthread_rwlock_wrlock(&digest_rwlock); @@ -1399,7 +1396,7 @@ std::pair Query_Processor::get_query_digests_v2(const boo digest_umap_aux.insert(element); } } - digest_text_umap.insert(digest_text_umap_aux.begin(), digest_text_umap_aux.end()); + digest_text_umap_aux.insert(digest_text_umap_aux_2.begin(), digest_text_umap_aux_2.end()); digest_umap_aux_2.clear(); digest_text_umap_aux_2.clear(); @@ -1409,7 +1406,6 @@ std::pair Query_Processor::get_query_digests_v2(const boo // content of the auxiliary maps. pthread_rwlock_wrlock(&digest_rwlock); digest_umap_aux.swap(digest_umap); - digest_text_umap_aux.swap(digest_text_umap); for (const auto& element : digest_umap_aux) { uint64_t digest = element.first; QP_query_digest_stats *qds = (QP_query_digest_stats *)element.second; From 5e321a979813968460f95c0fbbf810cbc57cb6a3 Mon Sep 17 00:00:00 2001 From: Rahim Kanji Date: Thu, 11 Jan 2024 11:18:34 +0500 Subject: [PATCH 2/2] Added regression test --- ...g_test_4399-stats_mysql_query_digest-t.cpp | 93 +++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 test/tap/tests/reg_test_4399-stats_mysql_query_digest-t.cpp diff --git a/test/tap/tests/reg_test_4399-stats_mysql_query_digest-t.cpp b/test/tap/tests/reg_test_4399-stats_mysql_query_digest-t.cpp new file mode 100644 index 0000000000..4dbba2cb85 --- /dev/null +++ b/test/tap/tests/reg_test_4399-stats_mysql_query_digest-t.cpp @@ -0,0 +1,93 @@ +/** + * @file reg_test_4399-stats_mysql_query_digest-t.cpp + * @brief This test verifies stability of ProxySQL by checking if it remains operational when + * stats_mysql_query_digest table is queried frequently while actively serving traffic. + */ + +#include +#include +#include +#include "mysql.h" +#include "mysqld_error.h" +#include "tap.h" +#include "command_line.h" +#include "utils.h" + +CommandLine cl; + +const unsigned int QUERY_COUNT = 1000; + +int main(int argc, char** argv) { + if (cl.getEnv()) { + diag("Failed to get the required environmental variables."); + return -1; + } + + plan(2); + + // Initialize Admin connection + MYSQL* proxysql_admin = mysql_init(NULL); + if (!proxysql_admin) { + fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(proxysql_admin)); + return -1; + } + // Connnect to ProxySQL Admin + 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-query_digests='true'"); + MYSQL_QUERY(proxysql_admin, "SET mysql-query_digests_keep_comment='true'"); + MYSQL_QUERY(proxysql_admin, "SET mysql-query_digests_normalize_digest_text='true'"); + MYSQL_QUERY(proxysql_admin, "SET mysql-query_digests_max_digest_length=2048"); + MYSQL_QUERY(proxysql_admin, "LOAD MYSQL VARIABLES TO RUNTIME"); + + // clearing previously stored digests + MYSQL_QUERY(proxysql_admin, "SELECT COUNT(*) FROM stats_mysql_query_digest_reset"); + mysql_free_result(mysql_store_result(proxysql_admin)); + + // Initialize ProxySQL connection + MYSQL* proxysql = mysql_init(NULL); + if (!proxysql) { + fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(proxysql)); + return -1; + } + + // Connect to ProxySQL + if (!mysql_real_connect(proxysql, cl.host, cl.username, cl.password, NULL, cl.port, NULL, 0)) { + fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(proxysql)); + return exit_status(); + } + + auto handle = std::async(std::launch::async, [&]() -> int { + char query[128]{}; + diag("Generating simulated traffic..."); + for (unsigned int i=0; i < QUERY_COUNT; i++) { + sprintf(query, "DO /*#%d#*/ %d", i, i); + MYSQL_QUERY(proxysql, query); + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } + return EXIT_SUCCESS; + } + ); + + bool result = true; + diag("Querying stats_mysql_query_digest table..."); + for (unsigned int i=0; i < QUERY_COUNT; i++) { + if (mysql_query(proxysql_admin, "SELECT COUNT(*) FROM stats_mysql_query_digest")) { + fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(proxysql_admin)); + result = false; + break; + } + mysql_free_result(mysql_store_result(proxysql_admin)); + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } + ok(result == true, "All queries on stats_mysql_query_digest table were executed successfully"); + ok(handle.get() == EXIT_SUCCESS, "Successfully ran a set of dummy queries to simulate traffic"); + + mysql_close(proxysql); + mysql_close(proxysql_admin); + + return exit_status(); +}