This commit pack a couple of fixes and improvements for the RESTAPI:
- Homogenization of GET/POST endpoint responses by ProxySQL. All
responses should now be guaranteed to be valid JSON.
- Fix JSON construction from parameters supplied to GET endpoint.
- Add two new fields 'script_stdout' and 'script_stderr' to the
JSON response when the target script fails to be executed. This is,
when it exists with an error code other than zero. This makes the
response homogeneous to when the scripts fails to produce a valid
JSON output, and add extra information for debugging on client side.
- Add a new debugging module 'PROXY_DEBUG_RESTAPI', to help tracing in
debugging builds the requests to the endpoints.
This commit addresses several issues with 'wexecvp':
- Fix invalid double call to 'close' in case fd was higher than
'FD_SETSIZE'. This could lead to the invalidation of an unrelated
fd resulting in asserts, as in issue #4001 and other instabilities.
- Fix previous limitations of the legacy 'select 'impl that rendered
the RESTAPI unusable when ProxySQL had more then 'FD_SETSIZE' fds
opened.
- Other minor improvements in function logic and interface.
* Added forced triggering of DNS Cache Update on MySQL Servers and ProxySQL Servers table update.
* Direct DNS cache update via socket (connected peer ip) if record is not available in cache.
* Used strdup instead of realloc.
* DNS lookup only once for ProxySQL Cluster Nodes.
Fix invalid resultset when using query cache and mixing clients using
and not using CLIENT_DEPRECATE_EOF.
If a client connects to ProxySQL not using CLIENT_DEPRECATE_EOF and it
caches a resultset, when a client using CLIENT_DEPRECATE_EOF executes
the same query it will get an invalid resultset and the client will
disconnect. The data in the resultset is correct, but proxysql skips a
sequence id thus the client assumes it is corrupted.
* Added multiple IP support with load balancing (Round Robin Scheduling)
* Added DNS resolver request max queue size
* Added AI_ADDRCONFIG flag
* Exception handling
Right now server session state isn't tracked for backend connections,
so we don't include this information in the generated OK packet. Because
of this, we should never report of this status change to clients.
This commit also introduces the following changes:
- Fix invalid formatting of 'stats_mysql_users' when username exceeds
'256' characters.
- Improve error handling in utility function 'string_format'.
- Add new utility functions 'cstr_format', as improved versions of
previous 'string_format' function.
- Compression flag is now propagated from client to backend connection
when the backend connection is being created for a 'fast_forward'
session. In case of client trying to connect without compression, to
a server configured with compression, we fallback to an uncompressed
connection.
- After a 'MySQL_Session' has obtained a connection for a 'fast_forward'
session, i.e, the one-to-one relationship between the client and
backend connection has been stablished, we completely disable the
compression 'STATUS_MYSQL_CONNECTION_COMPRESSION' flag from the client
'MySQL_Connection'.
- Correct the behavior for 'connect_retries_on_failure' for
'fast_forward' sessions to match regular sessions, reusing the
same implementation based on 'MySQL_Data_Stream::max_connect_time'.
- Change 'connect_timeout' for 'fast_forward' sessions to be the
highest of 'connect_timeout_server' and 'connect_timeout_server_max'.
- Add handling for 'COM_QUIT' packets for 'fast_forward' sessions which
have not yet received a backend connection.
Removed dependency from installed curl and openssl: now it uses
statically linked ones.
Updated config.guess and config.sub for cityhash and libdaemon
MariaDB client connector uses statically linked libssl and installed
libiconv
DEBUG build uses pthread_threadid_np() instead of syscall(SYS_gettid)
Fixed some variable types.
Enabled the use of jemalloc also for MacOS
Alias mallctl() to je_mallctl()
Removed libre2.a from libproxysql.a
If ProxySQL Cluster is running and the proxysql instance is shutting
down in a graceful way, Cluster was trying to access already freed
resources causing a crash.
This forces the re-evaluation of the query digest for each
'STMT_EXECUTE' for impossing the required flags over the current
backend 'MySQL_Connection'.
This commit contains an implementation rework and a fix:
- Impl for 'auto_increment_delay_multiplex_timeout_ms' has been
reworked in favor of reusing 'wait_until' to share logic with
previous 'connection_delay_multiplex_ms' variable.
- Fix previous 'connection_delay_multiplex_ms' behavior preventing
connection retaining when traffic unrelated to target hostgroup is
being received by the session.
Only the delimiter present at the end of the digest will be removed.
Delimiters found in the middle of the full digest, like in the case of
multi-statements should be preserved.
If any scenario is found in which we may want to consider a non
'ASYNC_IDLE' connection for expiring, this precondition shall be
removed, and checks should be responsible for ensuring 'ASYNC_IDLE'
state in the connection.
Because of MySQL bug https://bugs.mysql.com/bug.php?id=107875 ,
autocommit=0 can "create a transaction" even if SERVER_STATUS_IN_TRANS
is not set. This means that a SAVEPOINT can be created in a "transaction"
created with autocommit=0 but without SERVER_STATUS_IN_TRANS .
This commit takes also care of scenarios when autocommit=0 was switched back
to autocommit=1 when a SELECT was executed while variable
mysql-enforce_autocommit_on_reads was false.
MySQL_Session::NumActiveTransactions() now accepts a flag to check
for savepoints.
Query 'CLUSTER_QUERY_MYSQL_SERVERS' is now responded by 'runtime_mysql_servers'
as it previously was. Documentation reasoning about the change has been added
to 'MySQL_HostGroups_Manager::runtime_mysql_servers'.
- Cluster now syncs the server tables via 'incoming_*' tables generated
during 'load_mysql_servers_to_runtime'.
- Cluster now syncs 'mysql_users' table via a resultset generated via
'__refresh_users'.
Multiple changes:
- Query_Processor stored the resultset of query rules loaded to runtime
(previously this was only for query rules fast routing)
- Admin returns the stored resultset (query rules and fast routing)
when queries by Cluster
- In khash replaced the hashing function from the built-in
__ac_X31_hash_string to CityHash32
- When Cluster is used, it calls load_mysql_query_rules_to_runtime() passing
the resultsets retrieved by the remote peer
- Increased SQLite cache_size to ~50MB: this seems to be a very small optimization
and probably it will be reverted
- pull_mysql_query_rules_from_peer() uses transactions to write
to mysql_query_rules_fast_routing
- (important change) pull_mysql_query_rules_from_peer() verifies the checksum
of MySQL Query ules before loading them to runtime
if:
mysql-reset_connection_algorithm=1 and
mysql-connpoll_reset_queue_length=0
we will not return a connection with connection_quality_level == 1
because we want to run COM_CHANGE_USER
This change was introduced to work around Galera bug
https://github.com/codership/galera/issues/613
The following cluster modules now compute their expected checksums after fetch:
- mysql_query_rules
- mysql_users
- mysql_servers
- mysql_global_variables
In MySQL_Connection::IsActiveTransaction:
in the past we were incorrectly checking STATUS_MYSQL_CONNECTION_HAS_SAVEPOINT
and returning true in case there were any savepoint.
Although flag STATUS_MYSQL_CONNECTION_HAS_SAVEPOINT was not reset in
case of no transaction, thus the check was incorrect.
We can ignore STATUS_MYSQL_CONNECTION_HAS_SAVEPOINT for multiplexing
purpose in IsActiveTransaction() because it is also checked
in MultiplexDisabled()
PMC-10003: Retrieved a resultset while running a simple command using async_send_simple_command() .
async_send_simple_command() is used by ProxySQL to configure the connection, thus it
shouldn't retrieve any resultset.
A common issue for triggering this error is to have configure mysql-init_connect to
run a statement that returns a resultset.
If variable mysql-monitor_replication_lag_group_by_host=false: (default)
Monitor will perform 1 replication lag check per server per hostgroup.
If variable mysql-monitor_replication_lag_group_by_host=true:
Monitor will perform 1 replication lag check per server.
This variable need to be set only in setups in which the same server is
configured in many hostgroups, thus reducing the number of checks
MySQL Monitor was tracking failed connections.
SQLite3 server was:
* executing functions again null string
* writing an error message using an incorrect return code
Solved previously left TODOs, removed faulty logic for whitespace
processing for comments using position 'res_cur_pos'. This position
shall not be used because points to yet uninitialized memory, last
position with copied query data should always be 'res_cur_pos-1'.
Because of it, removing the extra logic based on 'res_cur_pos' should be
harmless.
* uninitialized variables variables.read_only in Clickhouse
* generate_proxysql_internal_session_json() may try to access variables not set
This commit also prevents watchdog to restart ProxySQL if running under valgrind.
In debug build, the spinning loops also have a minor usleep.
This to prevent valgrind to loop for long time
Solved previously left TODOs, removing legacy code performing a filtering
and addition of whitespaces while processing comments. This filtering or
addition should be performed during 'stage_1_parsing' main processing
loop if 'query_digests_keep_comment' is 'false' and within
'process_cmnt_type_1' otherwise.
This is now used in ProxySQL_Admin and MySQL_HostGroups_Manager.
It improves readibility and it makes the code less error prone.
Drawback: queries are generated at runtime.
It is possible that in future we will replace this with some strings
initialization during bootstrap.
Previously any error that wasn't ETIME (timeout) was reported as
'Internal error' and 'errno' was reported. This didn't cover reporting
terminations of the child processes by signals.
Track NO_BACKSLASH_ESCAPES in case it is changed:
- using SET sql_mode by the client
- directly on the backend (for example default sql_mode, or an
sql_mode set from another variable)
A deadlock could take place due to reverse mutex acquisition order by
'GenericRefreshStatistics' and 'load_mysql_variables_to_runtime' when
called by Cluster via 'pull_global_variables_from_peer'.
- Add new version of macros proxy_error|proxy_warning|proxy_info.
- Add new tables 'stats_proxysql_message_metrics' and
'stats_proxysql_message_metrics_reset'.
- Add new prometheus metric family 'proxysql_message_count_total'.
- Monitoring actions 'ping' and 'connect' now make use of a new
introduced table 'monitor.mysql_servers' instead of 'mysql_servers'
table from Admin.
- This table is kept in sync via a shared resulset in
'MySQL_HostGroups_Manager'.
'DEPRECATE_EOF' support wasn't properly tracked in
'server_capabilities'. Because this property is used for setting
'DEPRECATE_EOF' in 'client_flags' options for backend connections when
'fast_forward' is used, a mismatch between a client and a backend
connection could take place.
Before this commit we were calling GloAdmin->mysql_servers_wrlock() at the
beginning of the synchronization.
This was not ideal as we should call GloAdmin->mysql_servers_wrlock() only
if we are really going to write the tables. In other words, only if the
resultsets are fetched from the remote peer, and if their checksums didn't
change in the meantime.
New variables supported:
- lc_messages
- lc_time_names
- long_query_time
- max_execution_time
- max_heap_table_size
- max_sort_length
- optimizer_prune_level
- optimizer_search_depth
- optimizer_switch
- sort_buffer_size
- sql_big_selects
- timestamp
- tmp_table_size
Note: sql_big_selects is still not fully supported when
combined with max_join_size.
In set testing TAP ,set large max_execution_time.
If max_execution_time is too small, the TAP test may fails because the
queries will timeout.
Better parsing of SET SQL_LOG_BIN .
SQL_LOG_BIN is now managed by the same functions that handle boolean variables
instead of the now deprecated MySQL_Session::handler_WCD_SS_MCQ_qpo_Parse_SQL_LOG_BIN()
For naming convention, enum value SQL_LOG_BIN was renamed to SQL_SQL_LOG_BIN
In MySQL_Thread we also deprecated match_regexes[0] , previously
used to parse `set sql_log_bin`.
Functions Variable::fill_server_internal_session() and
Variable::fill_client_internal_session() seems to handle sql_log_bin as a
special value. This exception was removed.
Fixed a bug in MySQL_Session::generate_proxysql_internal_session_json() where
when backend variables needed to be generated, fill_client_internal_session()
was incorrectly called instead of fill_server_internal_session() , leading to
incorrect values reported by `PROXYSQL INTERNAL SESSION`
- Provided a new function to partially initialize 'MySQL_ResultSet'.
- Replaced 'generate_pkt_row' in favor of 'generate_pkt_row3' for
resulset writing.
Deprecated variables:
- net_write_timeout
Renamed set_testing-t.csv to set_testing-t.csv.obsolete , and removed net_write_timeout from set_testing-t.csv
Variables added to ignore list:
- net_write_timeout
- net_buffer_length
- read_buffer_size
- read_rnd_buffer_size
Added support for quoting with backtick
Renamed `enum variable_name` into `enum mysql_variable_name` for better readibility
`enum mysql_variable_name` has variable names alphabetically ordered after SQL_NAME_LAST_LOW_WM
`mysql_tracked_variables` has variable names alphabetically ordered after SQL_NAME_LAST_LOW_WM
A lot of new variables added in `mysql_tracked_variables` , although not all tracked yet (TODO)
In `MySQL_Variables::MySQL_Variables()`:
- if `internal_variable_name` in `mysql_tracked_variables` is NULL , it will be automatically initialized
- it performs some sanity check between `enum mysql_variable_name` and `mysql_tracked_variables`
Testing:
- refactored code in set_testing-t.cpp and set_testing-multi-t.cpp
- added set_testing-240-t.cpp to test improvements in 2.4.0
- generate_set_session_csv to automatically create set_testing-240.csv used by set_testing-240-t
+ Improved stage parsing to get the maximum compression from the maximum
digest size imposed by 'mysql_thread___query_digests_max_query_length'.
+ Homogenized staging API and improved offset computation between
stages.
+ Improved documentation (WIP).
+ Simplified literal parsing logic for some states of stage 1 parsing.
* Fixed typo for variable_id in history_mysql_status_variables table definition to be INT NOT NULL as intended.
* Added comments before debug ifdefs to explain their purpose
* Optimized get_variable_id_for_name by performing one less search by using iterator insteaed of knows_variable_name() call.
* Fixed memory leak by deleting resultset before return in lambda.
Changed the get_variable_id_for_name, and knows_variable_name to use const string &. Changed immutable strings to to be const as well. Added details comment to test_admin_stats-t.cpp test. In the test code, improved documentation, set a valid interval for metrics insertion, and added the commands to set the interval. Changed the sleep time to be the inteval plus a second should be long enough to let new metrics data be added. Put additional sleep before test 2. Fixed incorrect column index usage in test 4 result set. Reformulated test 5, to check the number of records inserted after new interval is correct.
MySQL_HostGroups_Manager::unshun_server_all_hostgroups() scans all hostgroups
looking for a specific server, and if shunned it will bring it back online
* Fixed regression introduced for 'at-signs' parsing and improved implementation
* Added minimal test for checking multiplexing disabling via 'mysql-keep_multiplexing_variables'
* Added missing 'plan()' to test specifying the number of test cases
* Added missing check to 'update_client_host_cache' in case cache elem is not found
* Added check to avoid calling 'update_client_host_cache' when 'host_cache_size' is zero
* Improved implementation and enabled 'test_client_limit_error-t' for CI
* Added extra check using 'client_host_cache_size' to prevent searchs if size is zero
* Restored currently unused testing scripts for creating/deleting network namespaces