In a previous commit we fixed the fact that if more than 16KB of data was
sent to Admin, SQLite3 Server or Clickhouse Server, no further data was
detected thus blocking.
It seems that in some circumstances data can be returned in chunks of 4KB,
thus we removed the 16KB logic replacing it with multiples of 4KB.
This commit is related to the previous one:
4c21a6d8c7
OpenSSL handles data in blocks of 16KB.
If more than 16KB of data was sent to Admin, SQLite3 Server or Clickhouse Server,
no further data was detected, thus blocking.
Added test_ssl_fast_forward-2-t.cpp for further testing.
Also added marker PMC-10004
* 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.
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.
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.
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
The following cluster modules now compute their expected checksums after fetch:
- mysql_query_rules
- mysql_users
- mysql_servers
- mysql_global_variables
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.
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'.
* 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.
Query_Processor::get_current_query_rules_fast_routing_count() now allows to
quickly execute this query is ran on Admin:
SELECT COUNT(*) FROM runtime_mysql_query_rules_fast_routing
Not only the default value is change from 1000 to 1 , but it also perform an upgrade from earlier release.
If during bootstrap a value of 1000 is found, it is automatically changed to 1 and a warning is generated.
This release also prevents the value 1000 to be a valid one during bootstrap.
This means that it is still possible to set the value to 1000 and to have a running proxysql instance with value 1000 , but during bootstrap it will be switched to 1.
If you really want to set mysql-session_idle_ms close to 1000 , it is recommended to set it to a closer value like 999 or 1001
Add initial support for FR limiting the number of connection errors that
can be initiated from a particular address before deniying future
connections from that address. Feature is controlled by new introduced
variables:
- mysql-client_host_error_counts
- mysql-client_host_cache_size
Command PROXYSQL RELOAD TLS is able to load new key/cert files and
create a new SSL context.
Loading of SSL can happens in two stages:
* during bootstrap: if it fails, proxysql dies
* running PROXYSQL RELOAD TLS: if it fails, proxysql will keep the old SSL context
This new method should successfully handle errors like missing or corrupted files.
We are also adding two buffers used to store the key/cert, to be used by the web interface.
This commit introduces a first simulator for read_only monitoring
ProxySQL itself will simulate hundreds of backends across hundreds of
hostgroups, all configured in hundreds of clusters, and return read_only
values for each of the simulated backend.
The read_only value can be configured in table READONLY_STATUS available in
the SQLite3Server module.
If a backend isn't configured in table READONLY_STATUS , its default read_only
value is 1.
It is possible to simulate a lot of simultaneous failover running queries like
the following:
UPDATE READONLY_STATUS SET read_only=1;
CREATE TABLE t1 AS SELECT hostname FROM READONLY_STATUS ORDER BY RANDOM() LIMIT 50;
UPDATE READONLY_STATUS SET read_only=0 WHERE hostname IN (SELECT hostname FROM t1);
DROP TABLE t1;
When a cluster node (client) connects to another cluster node, it
advertises its UUID but also exports its `admin-mysql_ifaces` .
The receiving cluster can use this information to try to guess how
to connect to the node that initialized the connection, for example
to collect metrics.
This is visible in table `stats_proxysql_servers_clients_status` .
HostGroups are stored in an array of pointers.
This commit allows the lookup using an unordered_map if the number of
Hostgroups is greater than 100.
For less number of hostgroups, a sequential scan seems more efficient.
This also introduce a test for micro benchmark.
This commit rewrites MySQL_HostGroups_Manager::read_only_action() in way to
reduce the calls to SQLite. It relies on two new std::set() :
- read_only_set1: if the server is already in a writer hostgroup
- read_only_set2: a cache to track the first time that a server has RO=0
Added also an index on MySQL_HostGroups_Manager,
ON mysql_servers (hostname,port)
ProxySQL will now automatically generate a UUID during start up.
The UUID can be either passed through the command line using -U or --uuid,
or saved on disk in a new table named global_settings.
The new table is used to distinguish it from global_variables that is replicated.
Table global_settings isn't replicated by Cluster.
If UUID is not present, it is automatically generated and saved.
* Added forgotten metric increase in case of 'sync conflict' on proxysql_servers
* Added support for 'global_variables' sync in proxysql_cluster
- Added several for getting the peers to be sync.
- Added function to pull the target 'global_variables' to sync.
- Added metrics for 'global_variables' sync:
+ Number of syncs done / failed.
+ Sync conflicts.
+ Sync warnings.
* Removed unnecesary escaping for '%' char
* Fixed issue due to 'flush_mysql_variables___runtime_to_database' being called without proper locking
* Added simple helper function to get the output from a command execution
* Multiple changes to 'cluster_synct' test
+ Spawned proxysql instance now runs inside a docker container.
+ Simplified launching and logging of spawned proxysql instance.
+ Added more verbose logging about the tables state.
+ Added new tests for 'global_variables' synchronization.
* Commented several variables known to not-sync and fixed port for replica 'proxysql_server'
* Removed deprecated and non-syncable variables from 'test_cluster_sync-t'
* Added extra logging for variables sync for 'test_cluster_sync-t'
- Labelling has been simplified to group metrics which
are part of a common group.
- Help has been fixed to reflect this labelling change.
- Doxygen doc and comment marks has been added to signal
metrics grouping.
- Metrics now follow prometheus base unit convention.
- Many metrics now make use of labels instead of enconding
the info in the metric name.
- Almost all metrics now have a meaningful 'help' message.
Fix a mem leak in flush_ldap_variables___database_to_runtime fun of ProxySQL_Admin class when call admindb->execute_statement function.
Because in the called function(admindb->execute_statement), the strdup--strdup(sqlite3_errmsg(db)) function is used to allocate memory to store the error message of the sqlite database operation failure.
In 2.1 we are mapping the command PROXYSQL SHUTDOWN to PROXYSQL KILL = a very fast shutdown.
The legacy old PROXYSQL SHUTDOWN is now implemented as PROXYSQL SHUTDOWN SLOW
- Added new logic for making both commands actually wait
for the completion of the operations they started.
- Now "PROXYSQL STOP" command sends and OK packet to the
client on completion.
If mysql-default_charset is changed but mysql-default_collation_connection it is not,
use mysql-default_charset to tune mysql-default_collation_connection.
Extended `mysql_variable_st` to add a new variable `is_global_variable`.
Using this variable we define the global variables.
Modified `mysql_tracked_variables[]` to also specify `is_global_variable`.
Removed `default_charset` from `MySQL_Threads_Handler::variables` to use `mysql_tracked_variables[]` instead.
Removed `default_charset` also from `mysql_thread_variables_names[]`.
Fixed `MySQL_Threads_Handler::get_variable_string()` : it was *not* returning `mysql-default_` variables.
`MySQL_Threads_Handler::set_variable()` adds `mysql-default_` variables only if `is_global_variable` is set.
In `MySQL_Threads_Handler::set_variable()` replaced a `strcasecmp()` with `strcmp()` for `mysql-default_` variables.
`MySQL_Threads_Handler::get_variables_list()` returns only `mysql-default_` variables with `is_global_variable` enabled.
`MySQL_Threads_Handler::has_variable()` for `mysql-default_` variables returns true only if variable has `is_global_variable` enabled.
`MySQL_Thread::refresh_variables()` does not refresh `mysql-default_` variables if `is_global_variable` is not enabled.
`MySQL_Thread::MySQL_Thread()` initializes to NULL all `mysql_thread___default_variables[]` variables.
Completely disabled in `ProxySQL_Admin::flush_mysql_variables___database_to_runtime()` the logic applied to all charset variables.
In the same methos was implemented the logic described in #1785 :
`mysql-default_charset` and `mysql-default_collation_connection` must be compatible:
* if only one is present, the other is configured automatically
* if not compatible, `mysql-default_charset` is configured from `mysql-default_collation_connection`
This commit prepares proxysql for further development related to SQLite3.
Specifically, it allows to either use built-in SQLite3 library, or to load it from a plugin.
Added admin variables:
* cluster_mysql_variables_save_to_disk
* cluster_admin_variables_save_to_disk
* cluster_mysql_variables_diffs_before_sync
* cluster_admin_variables_diffs_before_sync
When flush_admin_variables___database_to_runtime() is executed, flush_admin_variables___runtime_to_database() is also called to update admin variable checksum.
When flush_mysql_variables___database_to_runtime() is executed, flush_mysql_variables___runtime_to_database() is also called to update mysql variable checksum.
flush_mysql_variables___runtime_to_database() was also modified to avoid locking twice.
From 1.3.0 till 2.0.x , when COM_STMT_PREPARE is executed and Query Processor is executed, metadata are stored in MySQL_STMT_Global_info().
These metadata include routing information.
Is a prepared statement is prepared on a specific hostgroup, it will always be executed on the same hostgroup.
This causes negative consequences, like the one reported in issue #2691 .
This commit:
* remove hostgroup_id from MySQL_STMT_Global_info() and other metadata
* Query Processor is called also during COM_STMT_EXECUTE
* removes hostgroup from table stats_mysql_prepared_statements_info
* Query Processor do not perform any query rewrite ruding COM_STMT_EXECUTE
- Added new helper function to simplify ''prometheus::counters' update
and removed code duplication using it.
- 'hostgroup_manager' now exposes the same method 'p_update_metrics' as
the other modules.
- GCC 4.8 and 5 have issues with uniform initialization syntax, for
this reason, all it's uses have been replaced with assignements.
- Per-module metrics initialization functions are no longer required,
they have been replaced with the new generic ones.
libsqlinjection generates a lot of false positives.
This commit introduces a new table: mysql_firewall_whitelist_sqli_fingerprints
This table can list fingerprints generated by libsqlinjection:
if the fingerprint is listed in this table, proxysql will consider it as
a false positive.
This commit also enables SQLi algorithm only if the query is not already
explicitly whitelisted.
* introduced 2 new variables:
- mysql-firewall_whitelist_enabled : defines if the firewall with whitelist algorithm is enabled or not
- firewall_whitelist_errormsg : error message returned to the client if an error message is not already set
* Query_Processor returns firewall_whitelist_mode to the calling MySQL_Session, but the logging on error log currently happens within the Query_Processor itself
* if mysql-firewall_whitelist_enabled is turned on and a user it is not found in mysql_firewall_whitelist_users , the default behavior is that query is rejected
* lookup on mysql_firewall_whitelist_users happens for username@ip (specific IP) and username@'' (all IPs) . Match on network subnet is currently not implemented
* implemented SAVE MYSQL FIREWALL FROM RUNTIME
* fixed implementation of SAVE MYSQL FIREWALL TO DISK
* runtime configuration can be viewed in runtime_mysql_firewall_whitelist_rules and runtime_mysql_firewall_whitelist_users