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

V2.0.9 var array review #2521

Closed
wants to merge 67 commits into from
Closed

V2.0.9 var array review #2521

wants to merge 67 commits into from

Conversation

renecannao
Copy link
Contributor

Creating a pull request to for review purposes. Not to be merged

for (int i=0; i<SQL_NAME_LAST; i++) {
if (i == SQL_CHARACTER_SET || i == SQL_CHARACTER_SET_RESULTS ||
i == SQL_CHARACTER_SET_CONNECTION || i == SQL_CHARACTER_SET_CLIENT ||
i == SQL_CHARACTER_SET_DATABASE) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All these variables cannot be set independently.

https://dev.mysql.com/doc/refman/8.0/en/charset-connection.html#charset-connection-client-configuration

We either:

  • only set collation_connection (what is that is actually exchanged in the protocol)
  • set collation_connection , and all the other variables need to be set accordingly

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Default character set is used when backend mysql server dose not support configured collation/charset. For example, mysql 5.7 does not support collation is greater than 254. There for it might be configured to switch to the default character set.

This code is useless. I should not add it, because default values should not be used to initialize variables.

ss << ci->nr;
sess->mysql_variables->client_set_value(i, ss.str());
} else {
sess->mysql_variables->client_set_value(i, mysql_thread___default_variables[i]);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For now, I am not sure about this.
If the client didn't set the variable, and a default it is not required (for example, collation_connection), probably we should not assign these variables.
To me, assigning a variable means that it needs to be tracked.

I may remove this comment after further review.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have removed this code completely. Client character set initialization takes place in

 bool MySQL_Protocol::process_pkt_handshake_response(unsigned char *pkt, unsigned int len)

From my understanding, default values, that are configured in the global_variables should not be used to initialize character set variables.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct.
As part of the handshake, in MySQL_Protocol::generate_pkt_initial_handshake() , we have this:

  const MARIADB_CHARSET_INFO *ci = NULL;
  ci = proxysql_find_charset_name(mysql_thread___default_variables[SQL_CHARACTER_SET]);
  if (!ci) {
      proxy_error("Cannot find character set for name [%s]. Configuration error. Check [%s] global variable.\n",
              mysql_thread___default_variables[SQL_CHARACTER_SET], mysql_tracked_variables[SQL_CHARACTER_SET].internal_variable_name);
      assert(0);
  }
  uint8_t uint8_charset = ci->nr & 255;

The client can, in process_pkt_handshake_response, either:

@@ -3683,7 +3341,7 @@ bool MySQL_Thread::init() {

match_regexes=(Session_Regex **)malloc(sizeof(Session_Regex *)*4);
match_regexes[0]=new Session_Regex((char *)"^SET (|SESSION |@@|@@session.)SQL_LOG_BIN( *)(:|)=( *)");
match_regexes[1]=new Session_Regex((char *)"^SET (|SESSION |@@|@@session.)(SQL_MODE|TIME_ZONE|CHARACTER_SET_RESULTS|SESSION_TRACK_GTIDS|SQL_AUTO_IS_NULL|SQL_SELECT_LIMIT|SQL_SAFE_UPDATES|COLLATION_CONNECTION|NET_WRITE_TIMEOUT|TX_ISOLATION|MAX_JOIN_SIZE( *)(:|)=( *))");
match_regexes[1]=new Session_Regex((char *)"^SET (|SESSION |@@|@@session.)(SQL_MODE|TIME_ZONE|CHARACTER_SET_RESULTS|CHARACTER_SET_CLIENT|CHARACTER_SET_DATABASE|SESSION_TRACK_GTIDS|SQL_AUTO_IS_NULL|SQL_SELECT_LIMIT|SQL_SAFE_UPDATES|COLLATION_CONNECTION|CHARACTER_SET_CONNECTION|NET_WRITE_TIMEOUT|TX_ISOLATION|MAX_JOIN_SIZE( *)(:|)=( *))");
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should automatically generate this regex, so we won't forget when adding new variables.


void print_backtrace(void);

void MySQL_Variables::client_set_value(int idx, const char* value) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function doesn't check if the client exists.

I see this function called by MySQL_Connection::set_charset() , that is in turned called by MySQL_Connection::connect_start() .
MySQL_Connection::connect_start() creates a connection to the backend.
Some sessions do not have a client connection, for example sessions used by mirroring.
Therefore, trying to set a variable on a not existing client will cause a crash

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

set_charset(c->nr, NAMES);
proxy_warning("TRACE : INITIAL ACTION client %s, server %s\n", myds->sess->mysql_variables->client_get_value(SQL_CHARACTER_ACTION), myds->sess->mysql_variables->server_get_value(SQL_CHARACTER_ACTION));
set_charset(c->nr, (charset_action)atoi(myds->sess->mysql_variables->client_get_value(SQL_CHARACTER_ACTION)));
//set_charset(c->nr, CONNECT_START);
mysql_options(mysql, MYSQL_SET_CHARSET_NAME, c->csname);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note to myself: the client (proxysql) send to the server (the backend) the default collation for a specific charset).

https://dev.mysql.com/doc/refman/8.0/en/charset-connection.html#charset-connection-client-configuration

If the client is using a collation that is not the default, we may need to change it later on.
We can probably force the desired collation directly into the struct mysql , instead of using mysql_options

@alpes214 alpes214 force-pushed the v2.0.9-var-array-review branch 2 times, most recently from 5e7fcc4 to fd02a36 Compare February 14, 2020 06:50
@pondix
Copy link
Contributor

pondix commented Feb 16, 2020

This causes the automated test server to crash as ProxySQL just accumulates memory until it crashes :D try avoid submitting for build testing until it works...

renecannao and others added 25 commits February 29, 2020 09:43
Revert to auto configuration of build job num
adding MariaDB ConnectorJ test case to set parser tests
- SQL_SAFE_UPDATES
- SQL_SELECT_LIMIT
- SQL_SQL_MODE
- automation tests
Added new array mysql_tracked_variables[] that defines the tracked variables.
Ideally, tracking a new session variable will requires adding only a couple of lines of code.

Removed session variables from mysql_thread_variables_names:
- now both MySQL_Threads_Handler::get_variables_list() and MySQL_Threads_Handler::has_variable() rely on mysql_tracked_variables[]

Simplified MySQL_Variables, as it now also uses mysql_tracked_variables[] .
Generalized code to handle two variables together:
- sql_auto_is_null
- sql_safe_updates
- collation_connection
- net_write_timeout
- max_join_size
- collation_connection
- net_write_timeout
- max_join_size
@pondix
Copy link
Contributor

pondix commented Mar 10, 2022

Automated message: PR pending admin approval for build testing

@renecannao renecannao closed this Jan 20, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants