#ifndef __CLASS_MYSQL_THREAD_H #define __CLASS_MYSQL_THREAD_H #define ____CLASS_STANDARD_MYSQL_THREAD_H #include "proxysql.h" #include "cpp.h" #include "MySQL_Variables.h" #ifdef IDLE_THREADS #include #endif // IDLE_THREADS #include // Headers for declaring Prometheus counters #include #include #define MIN_POLL_LEN 8 #define MIN_POLL_DELETE_RATIO 8 #define MY_EPOLL_THREAD_MAXEVENTS 128 #define ADMIN_HOSTGROUP -2 #define STATS_HOSTGROUP -3 #define SQLITE_HOSTGROUP -4 #define MYSQL_DEFAULT_TX_ISOLATION "READ-COMMITTED" #define MYSQL_DEFAULT_SESSION_TRACK_GTIDS "OFF" #define MYSQL_DEFAULT_COLLATION_CONNECTION "" #define MYSQL_DEFAULT_NET_WRITE_TIMEOUT "60" #define MYSQL_DEFAULT_MAX_JOIN_SIZE "18446744073709551615" extern class MySQL_Variables mysql_variables; #ifdef IDLE_THREADS typedef struct __attribute__((aligned(64))) _conn_exchange_t { pthread_mutex_t mutex_idles; PtrArray *idle_mysql_sessions; pthread_mutex_t mutex_resumes; PtrArray *resume_mysql_sessions; } conn_exchange_t; #endif // IDLE_THREADS typedef struct _thr_id_username_t { uint32_t id; char *username; } thr_id_usr; typedef struct _kill_queue_t { pthread_mutex_t m; std::vector conn_ids; std::vector query_ids; } kill_queue_t; class ProxySQL_Poll { private: void shrink(); void expand(unsigned int more); public: unsigned int poll_timeout; unsigned long loops; StatCounters *loop_counters; unsigned int len; unsigned int size; struct pollfd *fds; MySQL_Data_Stream **myds; unsigned long long *last_recv; unsigned long long *last_sent; volatile int pending_listener_add; volatile int pending_listener_del; ProxySQL_Poll(); ~ProxySQL_Poll(); void add(uint32_t _events, int _fd, MySQL_Data_Stream *_myds, unsigned long long sent_time); void remove_index_fast(unsigned int i); int find_index(int fd); }; class MySQL_Thread { private: unsigned int servers_table_version_previous; unsigned int servers_table_version_current; unsigned long long last_processing_idles; MySQL_Connection **my_idle_conns; bool processing_idles; bool maintenance_loop; PtrArray *cached_connections; #ifdef IDLE_THREADS struct epoll_event events[MY_EPOLL_THREAD_MAXEVENTS]; int efd; unsigned int mysess_idx; std::map sessmap; #endif // IDLE_THREADS Session_Regex **match_regexes; protected: int nfds; public: void *gen_args; // this is a generic pointer to create any sort of structure ProxySQL_Poll mypolls; pthread_t thread_id; unsigned long long curtime; unsigned long long pre_poll_time; unsigned long long last_maintenance_time; std::atomic atomic_curtime; PtrArray *mysql_sessions; PtrArray *mirror_queue_mysql_sessions; PtrArray *mirror_queue_mysql_sessions_cache; #ifdef IDLE_THREADS PtrArray *idle_mysql_sessions; PtrArray *resume_mysql_sessions; conn_exchange_t myexchange; #endif // IDLE_THREADS int pipefd[2]; int shutdown; kill_queue_t kq; bool epoll_thread; bool poll_timeout_bool; // status variables are per thread only // in this way, there is no need for atomic operation and there is no cache miss // when it is needed a total, all threads are checked struct { unsigned long long backend_stmt_prepare; unsigned long long backend_stmt_execute; unsigned long long backend_stmt_close; unsigned long long frontend_stmt_prepare; unsigned long long frontend_stmt_execute; unsigned long long frontend_stmt_close; unsigned long long queries; unsigned long long queries_slow; unsigned long long queries_gtid; unsigned long long queries_with_max_lag_ms; unsigned long long queries_with_max_lag_ms__delayed; unsigned long long queries_with_max_lag_ms__total_wait_time_us; unsigned long long queries_backends_bytes_sent; unsigned long long queries_backends_bytes_recv; unsigned long long queries_frontends_bytes_sent; unsigned long long queries_frontends_bytes_recv; unsigned long long query_processor_time; unsigned long long backend_query_time; unsigned long long mysql_backend_buffers_bytes; unsigned long long mysql_frontend_buffers_bytes; unsigned long long mysql_session_internal_bytes; unsigned long long ConnPool_get_conn_immediate; unsigned long long ConnPool_get_conn_success; unsigned long long ConnPool_get_conn_failure; unsigned long long ConnPool_get_conn_latency_awareness; unsigned long long gtid_binlog_collected; unsigned long long gtid_session_collected; unsigned long long generated_pkt_err; unsigned long long max_connect_timeout_err; unsigned long long backend_lagging_during_query; unsigned long long backend_offline_during_query; unsigned long long unexpected_com_quit; unsigned long long unexpected_packet; unsigned long long killed_connections; unsigned long long killed_queries; unsigned long long hostgroup_locked; unsigned long long hostgroup_locked_set_cmds; unsigned long long hostgroup_locked_queries; unsigned long long aws_aurora_replicas_skipped_during_query; unsigned long long automatic_detected_sqli; unsigned long long whitelisted_sqli_fingerprint; unsigned int active_transactions; } status_variables; struct { int min_num_servers_lantency_awareness; int aurora_max_lag_ms_only_read_from_replicas; bool stats_time_backend_query; bool stats_time_query_processor; bool query_cache_stores_empty_result; } variables; pthread_mutex_t thread_mutex; MySQL_Thread(); ~MySQL_Thread(); MySQL_Session * create_new_session_and_client_data_stream(int _fd); bool init(); void run(); void poll_listener_add(int sock); void poll_listener_del(int sock); void register_session(MySQL_Session*, bool up_start=true); void unregister_session(int); struct pollfd * get_pollfd(unsigned int i); bool process_data_on_data_stream(MySQL_Data_Stream *myds, unsigned int n); void process_all_sessions(); void refresh_variables(); void register_session_connection_handler(MySQL_Session *_sess, bool _new=false); void unregister_session_connection_handler(int idx, bool _new=false); void listener_handle_new_connection(MySQL_Data_Stream *myds, unsigned int n); void Get_Memory_Stats(); MySQL_Connection * get_MyConn_local(unsigned int, MySQL_Session *sess, char *gtid_uuid, uint64_t gtid_trxid, int max_lag_ms); void push_MyConn_local(MySQL_Connection *); void return_local_connections(); void Scan_Sessions_to_Kill(PtrArray *mysess); void Scan_Sessions_to_Kill_All(); }; typedef MySQL_Thread * create_MySQL_Thread_t(); typedef void destroy_MySQL_Thread_t(MySQL_Thread *); class iface_info { public: char *iface; char *address; int port; int fd; iface_info(char *_i, char *_a, int p, int f) { iface=strdup(_i); address=strdup(_a); port=p; fd=f; } ~iface_info() { free(iface); free(address); close(fd); } }; class MySQL_Listeners_Manager { private: PtrArray *ifaces; public: MySQL_Listeners_Manager(); ~MySQL_Listeners_Manager(); int add(const char *iface, unsigned int num_threads, int **perthrsocks); int find_idx(const char *iface); int find_idx(const char *address, int port); iface_info * find_iface_from_fd(int fd); int get_fd(unsigned int idx); void del(unsigned int idx); }; struct p_th_counter { enum metric { queries_backends_bytes_sent = 0, queries_backends_bytes_recv, queries_frontends_bytes_sent, queries_frontends_bytes_recv, client_connections_created, client_connections_aborted, query_processor_time_nsec, backend_query_time_nsec, com_backend_stmt_prepare, com_backend_stmt_execute, com_backend_stmt_close, com_frontend_stmt_prepare, com_frontend_stmt_execute, com_frontend_stmt_close, questions, slow_queries, gtid_consistent_queries, gtid_session_collected, connpool_get_conn_latency_awareness, connpool_get_conn_immediate, connpool_get_conn_success, connpool_get_conn_failure, generated_error_packets, max_connect_timeouts, backend_lagging_during_query, backend_offline_during_query, queries_with_max_lag_ms, queries_with_max_lag_ms__delayed, queries_with_max_lag_ms__total_wait_time_us, mysql_unexpected_frontend_com_quit, client_connections_hostgroup_locked, hostgroup_locked_set_cmds, hostgroup_locked_queries, mysql_unexpected_frontend_packets, aws_aurora_replicas_skipped_during_query, automatic_detected_sql_injection, whitelisted_sqli_fingerprint, mysql_killed_backend_connections, mysql_killed_backend_queries, __size }; }; struct p_th_gauge { enum metric { active_transactions = 0, client_connections_non_idle, mysql_backend_buffers_bytes, mysql_frontend_buffers_bytes, mysql_session_internal_bytes, mirror_concurrency, mirror_queue_lengths, mysql_thread_workers, __size }; }; struct th_metrics_map_idx { enum index { counters = 0, gauges }; }; using active_flag = bool; using metric_name = std::string; using metric_help = std::string; using metric_tags = std::map; const static std::tuple< std::vector< std::tuple< p_th_counter::metric, metric_name, metric_help, metric_tags > >, std::vector< std::tuple< p_th_gauge::metric, metric_name, metric_help, metric_tags > > > th_metrics_map { { { p_th_counter::queries_backends_bytes_sent, "proxysql_queries_backends_bytes_sent", "Total number of bytes sent to backend.", {} }, { p_th_counter::queries_backends_bytes_recv, "proxysql_queries_backends_bytes_recv", "Total number of bytes received from backend.", {} }, { p_th_counter::queries_frontends_bytes_sent, "proxysql_queries_frontends_bytes_sent", "Total number of bytes sent to frontend.", {} }, { p_th_counter::queries_frontends_bytes_recv, "proxysql_queries_frontends_bytes_recv", "Total number of bytes received from frontend.", {} }, { p_th_counter::client_connections_created, "proxysql_client_connections_created", "Total number of client connections created.", {} }, { p_th_counter::client_connections_aborted, "proxysql_client_connections_aborted", "Number of client failed connections (or closed improperly).", {} }, { // TODO: Change unit p_th_counter::query_processor_time_nsec, "proxysql_query_processor_time_nsec", "The time spent inside the \"Query Processor\" to determine what action needs to be taken with the query (internal module).", {} }, { // TODO: Change unit p_th_counter::backend_query_time_nsec, "proxysql_backend_query_time_nsec", "Time spent making network calls to communicate with the backends.", {} }, { p_th_counter::com_backend_stmt_prepare, "proxysql_com_backend_stmt_prepare", "Represents the number of “PREPARE” executed by ProxySQL against the backends.", {} }, { p_th_counter::com_backend_stmt_execute, "proxysql_com_backend_stmt_execute", "Represents the number of “EXECUTE” executed by ProxySQL against the backends.", {} }, { p_th_counter::com_backend_stmt_close, "proxysql_com_backend_stmt_close", "Represents the number of “CLOSE” executed by ProxySQL against the backends.", {} }, { p_th_counter::com_frontend_stmt_prepare, "proxysql_com_frontend_stmt_prepare", "Represents the number of “PREPARE” executed by clients.", {} }, { p_th_counter::com_frontend_stmt_execute, "proxysql_com_frontend_stmt_execute", "Represents the number of “EXECUTE” executed by clients.", {} }, { p_th_counter::com_frontend_stmt_close, "proxysql_com_frontend_stmt_close", "Represents the number of “CLOSE” executed by clients.", {} }, { p_th_counter::questions, "proxysql_questions", "The total number of client requests / statements executed.", {} }, { // TODO: Change unit p_th_counter::slow_queries, "proxysql_slow_queries", "The total number of queries with an execution time greater than \"mysql-long_query_time\" milliseconds.", {} }, { p_th_counter::gtid_consistent_queries, "proxysql_gtid_consistent_queries", "Total queries with GTID consistent read.", {} }, { p_th_counter::gtid_session_collected, "proxysql_gtid_session_collected", "Total queries with GTID session state.", {} }, { // TODO: Add meaningful HELP p_th_counter::connpool_get_conn_latency_awareness, "proxysql_connpool_get_conn_latency_awareness", "", {} }, { // TODO: Add meaningful HELP p_th_counter::connpool_get_conn_immediate, "proxysql_connpool_get_conn_immediate", "", {} }, { // TODO: Add meaningful HELP p_th_counter::connpool_get_conn_success, "proxysql_connpool_get_conn_success", "", {} }, { // TODO: Add meaningful HELP p_th_counter::connpool_get_conn_failure, "proxysql_connpool_get_conn_failure", "", {} }, { p_th_counter::generated_error_packets, "proxysql_generated_error_packets", "Total generated error packets.", {} }, { // TODO: Add meaningful HELP p_th_counter::max_connect_timeouts, "proxysql_max_connect_timeouts", "", {} }, { // TODO: Add meaningful HELP p_th_counter::backend_lagging_during_query, "proxysql_backend_lagging_during_query", "", {} }, { // TODO: Add meaningful HELP p_th_counter::backend_offline_during_query, "proxysql_backend_offline_during_query", "Number of times a backend was offline during a query.", {} }, { // TODO: Add meaningful HELP p_th_counter::queries_with_max_lag_ms, "proxysql_queries_with_max_lag_ms", "", {} }, { // TODO: Add meaningful HELP p_th_counter::queries_with_max_lag_ms__delayed, "proxysql_queries_with_max_lag_ms__delayed", "", {} }, { // TODO: Add meaningful HELP p_th_counter::queries_with_max_lag_ms__total_wait_time_us, "proxysql_queries_with_max_lag_ms__total_wait_time_us", "", {} }, { // TODO: Add meaningful HELP p_th_counter::mysql_unexpected_frontend_com_quit, "proxysql_mysql_unexpected_frontend_com_quit", "", {} }, { // TODO: Add meaningful HELP p_th_counter::client_connections_hostgroup_locked, "proxysql_client_connections_hostgroup_locked", "", {} }, { // TODO: Add meaningful HELP p_th_counter::hostgroup_locked_set_cmds, "proxysql_hostgroup_locked_set_cmds", "", {} }, { // TODO: Add meaningful HELP p_th_counter::hostgroup_locked_queries, "proxysql_hostgroup_locked_queries", "", {} }, { // TODO: Add meaningful HELP p_th_counter::mysql_unexpected_frontend_packets, "proxysql_mysql_unexpected_frontend_packets", "", {} }, { // TODO: Add meaningful HELP p_th_counter::aws_aurora_replicas_skipped_during_query, "proxysql_aws_aurora_replicas_skipped_during_query", "", {} }, { // TODO: Add meaningful HELP p_th_counter::automatic_detected_sql_injection, "proxysql_automatic_detected_sql_injection", "", {} }, { // TODO: Add meaningful HELP p_th_counter::whitelisted_sqli_fingerprint, "proxysql_whitelisted_sqli_fingerprint", "", {} }, { // TODO: Add meaningful HELP p_th_counter::mysql_killed_backend_connections, "proxysql_mysql_killed_backend_connections", "", {} }, { // TODO: Add meaningful HELP p_th_counter::mysql_killed_backend_queries, "proxysql_mysql_killed_backend_queries", "", {} }, }, { { p_th_gauge::active_transactions, "proxysql_active_transactions", "Provides a count of how many client connection are currently processing a transaction.", {} }, { p_th_gauge::client_connections_non_idle, "proxysql_client_connections_non_idle", "Number of client connections that are currently handled by the main worker threads.", {} }, { p_th_gauge::mysql_backend_buffers_bytes, "proxysql_mysql_backend_buffers_bytes", "Buffers related to backend connections if \"fast_forward\" is used (0 means fast_forward is not used).", {} }, { p_th_gauge::mysql_frontend_buffers_bytes, "proxysql_mysql_frontend_buffers_bytes", "Buffers related to frontend connections (read/write buffers and other queues).", {} }, { p_th_gauge::mysql_session_internal_bytes, "proxysql_mysql_session_internal_bytes", "Other memory used by ProxySQL to handle MySQL Sessions.", {} }, { // TODO: Add meaningful HELP p_th_gauge::mirror_concurrency, "proxysql_mirror_concurrency", "Mirror current concurrency", {} }, { // TODO: Add meaningful HELP p_th_gauge::mirror_queue_lengths, "proxysql_mirror_queue_lengths", "Mirror queue length", {} }, { p_th_gauge::mysql_thread_workers, "proxysql_mysql_thread_workers", "Number of MySQL Thread workers i.e. “mysql-threads”", {} } } }; class MySQL_Threads_Handler { private: int shutdown_; size_t stacksize; pthread_attr_t attr; pthread_rwlock_t rwlock; PtrArray *bind_fds; MySQL_Listeners_Manager *MLM; /** * @brief Initalizes the prometheus counters specified in th_metrics_map. */ void init_prometheus_counters(); /** * @brief Initalizes the prometheus gagues specified in th_metrics_map. */ void init_prometheus_gauges(); public: struct { int monitor_history; int monitor_connect_interval; int monitor_connect_timeout; int monitor_ping_interval; int monitor_ping_max_failures; int monitor_ping_timeout; int monitor_read_only_interval; int monitor_read_only_timeout; int monitor_read_only_max_timeout_count; bool monitor_enabled; bool monitor_wait_timeout; bool monitor_writer_is_also_reader; int monitor_replication_lag_interval; int monitor_replication_lag_timeout; int monitor_groupreplication_healthcheck_interval; int monitor_groupreplication_healthcheck_timeout; int monitor_groupreplication_healthcheck_max_timeout_count; int monitor_groupreplication_max_transactions_behind_count; int monitor_galera_healthcheck_interval; int monitor_galera_healthcheck_timeout; int monitor_galera_healthcheck_max_timeout_count; int monitor_query_interval; int monitor_query_timeout; int monitor_slave_lag_when_null; int monitor_threads_min; int monitor_threads_max; int monitor_threads_queue_maxsize; char *monitor_username; char *monitor_password; char * monitor_replication_lag_use_percona_heartbeat; int ping_interval_server_msec; int ping_timeout_server; int shun_on_failures; int shun_recovery_time_sec; int query_retries_on_failure; bool client_multi_statements; bool connection_warming; int connect_retries_on_failure; int connect_retries_delay; int connection_delay_multiplex_ms; int connection_max_age_ms; int connect_timeout_server; int connect_timeout_server_max; int free_connections_pct; int show_processlist_extended; #ifdef IDLE_THREADS int session_idle_ms; bool session_idle_show_processlist; #endif // IDLE_THREADS bool sessions_sort; char *default_schema; char *interfaces; char *server_version; char *keep_multiplexing_variables; unsigned int default_charset; unsigned int handle_unknown_charset; bool servers_stats; bool commands_stats; bool query_digests; bool query_digests_lowercase; bool query_digests_replace_null; bool query_digests_no_digits; bool query_digests_normalize_digest_text; bool query_digests_track_hostname; bool default_reconnect; bool have_compress; bool have_ssl; bool client_found_rows; bool multiplexing; // bool stmt_multiplexing; bool log_unhealthy_connections; bool forward_autocommit; bool enforce_autocommit_on_reads; bool autocommit_false_not_reusable; bool autocommit_false_is_transaction; bool verbose_query_error; int max_allowed_packet; bool automatic_detect_sqli; bool firewall_whitelist_enabled; bool use_tcp_keepalive; int tcp_keepalive_time; int throttle_connections_per_sec_to_hostgroup; int max_transaction_time; int threshold_query_length; int threshold_resultset_size; int query_digests_max_digest_length; int query_digests_max_query_length; int wait_timeout; int throttle_max_bytes_per_second_to_client; int throttle_ratio_server_to_client; int max_connections; int max_stmts_per_connection; int max_stmts_cache; int mirror_max_concurrency; int mirror_max_queue_length; int default_max_latency_ms; int default_query_delay; int default_query_timeout; int query_processor_iterations; int query_processor_regex; int set_query_lock_on_hostgroup; int reset_connection_algorithm; int auto_increment_delay_multiplex; int long_query_time; int hostgroup_manager_verbose; int binlog_reader_connect_retry_msec; char *init_connect; char *ldap_user_variable; char *add_ldap_user_comment; char *default_tx_isolation; char *default_session_track_gtids; char *default_variables[SQL_NAME_LAST]; char *firewall_whitelist_errormsg; #ifdef DEBUG bool session_debug; #endif /* DEBUG */ uint32_t server_capabilities; int poll_timeout; int poll_timeout_on_failure; int connpoll_reset_queue_length; char *eventslog_filename; int eventslog_filesize; int eventslog_default_log; int eventslog_format; char *auditlog_filename; int auditlog_filesize; // SSL related, proxy to server char * ssl_p2s_ca; char * ssl_p2s_cert; char * ssl_p2s_key; char * ssl_p2s_cipher; int query_cache_size_MB; int min_num_servers_lantency_awareness; int aurora_max_lag_ms_only_read_from_replicas; bool stats_time_backend_query; bool stats_time_query_processor; bool query_cache_stores_empty_result; bool kill_backend_connection_when_disconnect; bool client_session_track_gtid; } variables; struct { unsigned int mirror_sessions_current; /// Prometheus metrics arrays std::array p_counter_array {}; std::array p_gauge_array {}; } status_variables; /** * @brief Callback to update the metrics. */ void p_update_metrics(); unsigned int num_threads; proxysql_mysql_thread_t *mysql_threads; #ifdef IDLE_THREADS proxysql_mysql_thread_t *mysql_threads_idles; #endif // IDLE_THREADS unsigned int get_global_version(); void wrlock(); void wrunlock(); void commit(); char *get_variable(char *name); bool set_variable(char *name, const char *value); char **get_variables_list(); bool has_variable(const char * name); MySQL_Threads_Handler(); ~MySQL_Threads_Handler(); char *get_variable_string(char *name); unsigned int get_variable_uint(char *name); uint16_t get_variable_uint16(char *name); int get_variable_int(const char *name); void print_version(); void init(unsigned int num=0, size_t stack=0); proxysql_mysql_thread_t *create_thread(unsigned int tn, void *(*start_routine) (void *), bool); void shutdown_threads(); int listener_add(const char *iface); int listener_add(const char *address, int port); int listener_del(const char *iface); int listener_del(const char *address, int port); void start_listeners(); void stop_listeners(); void signal_all_threads(unsigned char _c=0); SQLite3_result * SQL3_Processlist(); SQLite3_result * SQL3_GlobalStatus(bool _memory); bool kill_session(uint32_t _thread_session_id); unsigned long long get_total_mirror_queue(); unsigned long long get_total_backend_stmt_prepare(); unsigned long long get_total_backend_stmt_execute(); unsigned long long get_total_backend_stmt_close(); unsigned long long get_total_frontend_stmt_prepare(); unsigned long long get_total_frontend_stmt_execute(); unsigned long long get_total_frontend_stmt_close(); unsigned long long get_total_queries(); unsigned long long get_slow_queries(); unsigned long long get_gtid_queries(); unsigned long long get_gtid_session_collected(); unsigned long long get_queries_backends_bytes_recv(); unsigned long long get_queries_backends_bytes_sent(); unsigned long long get_queries_frontends_bytes_recv(); unsigned long long get_queries_frontends_bytes_sent(); unsigned int get_active_transations(); #ifdef IDLE_THREADS unsigned int get_non_idle_client_connections(); #endif // IDLE_THREADS unsigned long long get_query_processor_time(); unsigned long long get_backend_query_time(); unsigned long long get_mysql_backend_buffers_bytes(); unsigned long long get_mysql_frontend_buffers_bytes(); unsigned long long get_mysql_session_internal_bytes(); unsigned long long get_ConnPool_get_conn_immediate(); unsigned long long get_ConnPool_get_conn_success(); unsigned long long get_ConnPool_get_conn_failure(); unsigned long long get_ConnPool_get_conn_latency_awareness(); unsigned long long get_generated_pkt_err(); unsigned long long get_max_connect_timeout(); unsigned long long get_unexpected_com_quit(); unsigned long long get_unexpected_packet(); unsigned long long get_hostgroup_locked(); unsigned long long get_hostgroup_locked_set_cmds(); unsigned long long get_hostgroup_locked_queries(); unsigned long long get_aws_aurora_replicas_skipped_during_query(); unsigned long long get_automatic_detected_sqli(); unsigned long long get_whitelisted_sqli_fingerprint(); unsigned long long get_backend_lagging_during_query(); unsigned long long get_backend_offline_during_query(); unsigned long long get_queries_with_max_lag_ms(); unsigned long long get_queries_with_max_lag_ms__delayed(); unsigned long long get_queries_with_max_lag_ms__total_wait_time_us(); unsigned long long get_killed_connections(); unsigned long long get_killed_queries(); iface_info *MLM_find_iface_from_fd(int fd) { return MLM->find_iface_from_fd(fd); } void Get_Memory_Stats(); void kill_connection_or_query(uint32_t _thread_session_id, bool query, char *username); }; #endif /* __CLASS_MYSQL_THREAD_H */