From 0fc9de63ee011bae50c5b56916f8b00bf91fb7e2 Mon Sep 17 00:00:00 2001 From: Phil Porada Date: Thu, 21 Dec 2023 13:06:30 -0500 Subject: [PATCH] SA: Enforce microsecond granularity for long_query_time and max_statement_time (#7224) In MariaDB, `long_query_time`[1] and `max_statement_time`[2] have up to microsecond granularity (6 digits to the right of the decimal). Fixes an issue detected by proxysql in staging. ``` MySQL_Session.cpp:6567:handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_COM_QUERY_qpo(): [ERROR] Unable to parse query. If correct, report it as a bug: SET long_query_time=3.9200000000000004 ``` 1. https://mariadb.com/kb/en/server-system-variables/#long_query_time 2. https://mariadb.com/kb/en/server-system-variables/#max_statement_time --------- Co-authored-by: Aaron Gable --- sa/database.go | 7 ++++--- sa/database_test.go | 8 ++++---- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/sa/database.go b/sa/database.go index 7078ac872..19f8f4498 100644 --- a/sa/database.go +++ b/sa/database.go @@ -223,11 +223,12 @@ func adjustMySQLConfig(conf *mysql.Config) error { // `?max_statement_time=2`. A zero value in the DSN means these won't be // sent on new connections. if conf.ReadTimeout != 0 { - // In MariaDB, max_statement_time and long_query_time are both seconds. + // In MariaDB, max_statement_time and long_query_time are both seconds, + // but can have up to microsecond granularity. // Note: in MySQL (which we don't use), max_statement_time is millis. readTimeout := conf.ReadTimeout.Seconds() - setDefault("max_statement_time", fmt.Sprintf("%g", readTimeout*0.95)) - setDefault("long_query_time", fmt.Sprintf("%g", readTimeout*0.80)) + setDefault("max_statement_time", fmt.Sprintf("%.6f", readTimeout*0.95)) + setDefault("long_query_time", fmt.Sprintf("%.6f", readTimeout*0.80)) } omitZero("max_statement_time") diff --git a/sa/database_test.go b/sa/database_test.go index 400e02c90..1585c6d89 100644 --- a/sa/database_test.go +++ b/sa/database_test.go @@ -108,7 +108,7 @@ func TestDbSettings(t *testing.T) { // TODO: Change this to test `newDbMapFromMySQLConfig` instead? func TestNewDbMap(t *testing.T) { const mysqlConnectURL = "policy:password@tcp(boulder-proxysql:6033)/boulder_policy_integration?readTimeout=800ms&writeTimeout=800ms" - const expected = "policy:password@tcp(boulder-proxysql:6033)/boulder_policy_integration?clientFoundRows=true&parseTime=true&readTimeout=800ms&writeTimeout=800ms&long_query_time=0.6400000000000001&max_statement_time=0.76&sql_mode=%27STRICT_ALL_TABLES%27" + const expected = "policy:password@tcp(boulder-proxysql:6033)/boulder_policy_integration?clientFoundRows=true&parseTime=true&readTimeout=800ms&writeTimeout=800ms&long_query_time=0.640000&max_statement_time=0.760000&sql_mode=%27STRICT_ALL_TABLES%27" oldSQLOpen := sqlOpen defer func() { sqlOpen = oldSQLOpen @@ -199,8 +199,8 @@ func TestAdjustMySQLConfig(t *testing.T) { test.AssertNotError(t, err, "unexpected err setting server variables") test.AssertDeepEquals(t, conf.Params, map[string]string{ "sql_mode": "'STRICT_ALL_TABLES'", - "max_statement_time": "95", - "long_query_time": "80", + "max_statement_time": "95.000000", + "long_query_time": "80.000000", }) conf = &mysql.Config{ @@ -213,7 +213,7 @@ func TestAdjustMySQLConfig(t *testing.T) { test.AssertNotError(t, err, "unexpected err setting server variables") test.AssertDeepEquals(t, conf.Params, map[string]string{ "sql_mode": "'STRICT_ALL_TABLES'", - "long_query_time": "80", + "long_query_time": "80.000000", }) conf = &mysql.Config{