Skip to content
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

Fixed crash on frequently querying stats_mysql_query_digest* tables #4414

Merged
merged 2 commits into from
Jan 11, 2024
Merged
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
6 changes: 1 addition & 5 deletions lib/Query_Processor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -1399,7 +1396,7 @@ std::pair<SQLite3_result *, int> 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();

Expand All @@ -1409,7 +1406,6 @@ std::pair<SQLite3_result *, int> 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;
Expand Down
93 changes: 93 additions & 0 deletions test/tap/tests/reg_test_4399-stats_mysql_query_digest-t.cpp
Original file line number Diff line number Diff line change
@@ -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 <stdio.h>
#include <future>
#include <thread>
#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();
}
Loading