diff --git a/include/thr_timer.h b/include/thr_timer.h index 6bca815480b4a..233a66bc6fa87 100644 --- a/include/thr_timer.h +++ b/include/thr_timer.h @@ -24,6 +24,7 @@ extern "C" { typedef struct st_timer { struct timespec expire_time; ulonglong period; + ulonglong timeout; /* Timeout value in microseconds */ my_bool expired; uint index_in_queue; void (*func)(void*); diff --git a/mysql-test/main/alter_table_lock.result b/mysql-test/main/alter_table_lock.result index b98f8d50c8069..c42a621faf1b0 100644 --- a/mysql-test/main/alter_table_lock.result +++ b/mysql-test/main/alter_table_lock.result @@ -47,9 +47,9 @@ LOCK TABLE t READ; connection con1; SET max_statement_time=0.001; ALTER TABLE t FORCE; -ERROR 70100: Query execution was interrupted (max_statement_time exceeded) +ERROR 70100: Query was interrupted: execution time limit 0.001 sec exceeded ALTER TABLE IF EXISTS t FORCE; -ERROR 70100: Query execution was interrupted (max_statement_time exceeded) +ERROR 70100: Query was interrupted: execution time limit 0.001 sec exceeded disconnect con1; connection default; UNLOCK TABLES; diff --git a/mysql-test/main/backup_lock.result b/mysql-test/main/backup_lock.result index 6e2ccad5091ea..0103a0fc92626 100644 --- a/mysql-test/main/backup_lock.result +++ b/mysql-test/main/backup_lock.result @@ -55,7 +55,7 @@ MDL_SHARED_WRITE Table metadata lock test t1 MDL_SHARED_UPGRADABLE Table metadata lock test t1 MDL_INTENTION_EXCLUSIVE Schema metadata lock test SET STATEMENT max_statement_time=1 FOR backup stage block_ddl; -ERROR 70100: Query execution was interrupted (max_statement_time exceeded) +ERROR 70100: Query was interrupted: execution time limit 1.0 sec exceeded backup stage block_ddl; connection default; commit; diff --git a/mysql-test/main/backup_locks.result b/mysql-test/main/backup_locks.result index 4d5de53c1fbf3..0d4f24cfb611c 100644 --- a/mysql-test/main/backup_locks.result +++ b/mysql-test/main/backup_locks.result @@ -51,13 +51,13 @@ connection con1; CREATE OR REPLACE SEQUENCE seq1 START -28; ERROR HY000: Sequence 'test.seq1' has out of range value for options SET STATEMENT max_statement_time=10 FOR CREATE OR REPLACE SEQUENCE seq1 START 50; -ERROR 70100: Query execution was interrupted (max_statement_time exceeded) +ERROR 70100: Query was interrupted: execution time limit 10.0 sec exceeded SET STATEMENT max_statement_time=10 FOR ALTER SEQUENCE IF EXISTS seq1 NOMAXVALUE; -ERROR 70100: Query execution was interrupted (max_statement_time exceeded) +ERROR 70100: Query was interrupted: execution time limit 10.0 sec exceeded SET STATEMENT max_statement_time=10 FOR ALTER SEQUENCE IF EXISTS seq1 MAXVALUE 1000; -ERROR 70100: Query execution was interrupted (max_statement_time exceeded) +ERROR 70100: Query was interrupted: execution time limit 10.0 sec exceeded SET STATEMENT max_statement_time=10 for rename table seq2 to seq3, seq3 to seq1; -ERROR 70100: Query execution was interrupted (max_statement_time exceeded) +ERROR 70100: Query was interrupted: execution time limit 10.0 sec exceeded connection default; backup unlock; drop table seq1,seq2; diff --git a/mysql-test/main/func_json_notembedded.result b/mysql-test/main/func_json_notembedded.result index ba4d38dd623f3..569f41de70e55 100644 --- a/mysql-test/main/func_json_notembedded.result +++ b/mysql-test/main/func_json_notembedded.result @@ -13,29 +13,29 @@ set max_statement_time=0.0001; SET @old_debug= @@debug_dbug; SET debug_dbug='+d,debug_max_statement_time exceeded'; select json_array_append(@arr, '$[0]', 1); -ERROR 70100: Query execution was interrupted (max_statement_time exceeded) +ERROR 70100: Query was interrupted: execution time limit 0.0001 sec exceeded select json_array_insert(@arr, '$[0]', 1); -ERROR 70100: Query execution was interrupted (max_statement_time exceeded) +ERROR 70100: Query was interrupted: execution time limit 0.0001 sec exceeded select json_insert(@obj, '$.meta', 1); -ERROR 70100: Query execution was interrupted (max_statement_time exceeded) +ERROR 70100: Query was interrupted: execution time limit 0.0001 sec exceeded select json_compact(@arr); -ERROR 70100: Query execution was interrupted (max_statement_time exceeded) +ERROR 70100: Query was interrupted: execution time limit 0.0001 sec exceeded select json_detailed(@arr); -ERROR 70100: Query execution was interrupted (max_statement_time exceeded) +ERROR 70100: Query was interrupted: execution time limit 0.0001 sec exceeded select json_loose(@arr); -ERROR 70100: Query execution was interrupted (max_statement_time exceeded) +ERROR 70100: Query was interrupted: execution time limit 0.0001 sec exceeded select json_merge(@obj, @arr); -ERROR 70100: Query execution was interrupted (max_statement_time exceeded) +ERROR 70100: Query was interrupted: execution time limit 0.0001 sec exceeded select json_merge_patch(@obj, @obj); -ERROR 70100: Query execution was interrupted (max_statement_time exceeded) +ERROR 70100: Query was interrupted: execution time limit 0.0001 sec exceeded select json_merge_preserve(@obj, @arr); -ERROR 70100: Query execution was interrupted (max_statement_time exceeded) +ERROR 70100: Query was interrupted: execution time limit 0.0001 sec exceeded select json_remove(@obj,'$.foo'); -ERROR 70100: Query execution was interrupted (max_statement_time exceeded) +ERROR 70100: Query was interrupted: execution time limit 0.0001 sec exceeded select json_replace(@obj,'$.foo',1); -ERROR 70100: Query execution was interrupted (max_statement_time exceeded) +ERROR 70100: Query was interrupted: execution time limit 0.0001 sec exceeded select json_set(@arr,'$[1000]',1); -ERROR 70100: Query execution was interrupted (max_statement_time exceeded) +ERROR 70100: Query was interrupted: execution time limit 0.0001 sec exceeded SET debug_dbug= @old_debug; disconnect u; connection default; diff --git a/mysql-test/main/opt_hint_timeout.result b/mysql-test/main/opt_hint_timeout.result index 9045d80b89152..96e51d087b2f4 100644 --- a/mysql-test/main/opt_hint_timeout.result +++ b/mysql-test/main/opt_hint_timeout.result @@ -5,36 +5,36 @@ CREATE TABLE t1 (a INT); INSERT INTO t1 SELECT seq FROM seq_1_to_5000; # Correct hint usage SELECT /*+ MAX_EXECUTION_TIME(10) */* FROM t1 a, t1 b; -ERROR 70100: Query execution was interrupted (max_statement_time exceeded) +ERROR 70100: Query was interrupted: execution time limit 0.01 sec exceeded EXPLAIN EXTENDED SELECT /*+ MAX_EXECUTION_TIME(0001490) */* FROM t1; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 5000 100.00 Warnings: Note 1003 select /*+ MAX_EXECUTION_TIME(0001490) */ `test`.`t1`.`a` AS `a` from `test`.`t1` SELECT /*+ MAX_EXECUTION_TIME(20) */ *, SLEEP(1) FROM t1 UNION SELECT 1, 2; -ERROR 70100: Query execution was interrupted (max_statement_time exceeded) +ERROR 70100: Query was interrupted: execution time limit 0.02 sec exceeded (SELECT /*+ MAX_EXECUTION_TIME(300) */ *, SLEEP(1) FROM t1) UNION (SELECT 1, 2); -ERROR 70100: Query execution was interrupted (max_statement_time exceeded) +ERROR 70100: Query was interrupted: execution time limit 0.3 sec exceeded ((SELECT /*+ MAX_EXECUTION_TIME(500) */ *, SLEEP(1) FROM t1)); -ERROR 70100: Query execution was interrupted (max_statement_time exceeded) +ERROR 70100: Query was interrupted: execution time limit 0.5 sec exceeded # Make sure the hint overrides global/session/statement settings. # Global setting 30 seconds, won't be exceeded for sure SET @@max_statement_time = 30; SELECT /*+ MAX_EXECUTION_TIME(10)*/ count(*) FROM t1 a natural join t1 b natural join t1 c; -ERROR 70100: Query execution was interrupted (max_statement_time exceeded) +ERROR 70100: Query was interrupted: execution time limit 0.01 sec exceeded # Session setting 30 seconds, too long to be exceeded SET SESSION max_statement_time = 30; SELECT /*+ MAX_EXECUTION_TIME(15) */ count(*) FROM t1 a natural join t1 b natural join t1 c; -ERROR 70100: Query execution was interrupted (max_statement_time exceeded) +ERROR 70100: Query was interrupted: execution time limit 0.015 sec exceeded SET STATEMENT max_statement_time = 20 FOR SELECT /*+ MAX_EXECUTION_TIME(5)*/ count(*) FROM t1 a natural join t1 b natural join t1 c; -ERROR 70100: Query execution was interrupted (max_statement_time exceeded) +ERROR 70100: Query was interrupted: execution time limit 0.005 sec exceeded # Check that prepared statements process the hint correctly PREPARE s FROM 'SELECT /*+ MAX_EXECUTION_TIME(20) */ seq, SLEEP(1) FROM seq_1_to_10'; EXECUTE s; -ERROR 70100: Query execution was interrupted (max_statement_time exceeded) +ERROR 70100: Query was interrupted: execution time limit 0.02 sec exceeded EXECUTE s; -ERROR 70100: Query execution was interrupted (max_statement_time exceeded) +ERROR 70100: Query was interrupted: execution time limit 0.02 sec exceeded # Hint duplication SELECT /*+ MAX_EXECUTION_TIME(50000) MAX_EXECUTION_TIME(100) */ count(*) FROM t1; count(*) @@ -111,5 +111,5 @@ Warning 4172 'MAX_EXECUTION_TIME(30)' is not allowed in this context SELECT /*+ MAX_EXECUTION_TIME(20) */ count(*), SLEEP(1) FROM t1 UNION SELECT count(*), SLEEP(1) FROM t1; -ERROR 70100: Query execution was interrupted (max_statement_time exceeded) +ERROR 70100: Query was interrupted: execution time limit 0.02 sec exceeded DROP TABLE t1, t2; diff --git a/mysql-test/main/set_statement_notembedded.result b/mysql-test/main/set_statement_notembedded.result index 67d2d8bc505cc..8dea207626e72 100644 --- a/mysql-test/main/set_statement_notembedded.result +++ b/mysql-test/main/set_statement_notembedded.result @@ -8,7 +8,7 @@ SHOW STATUS LIKE "max_statement_time_exceeded"; Variable_name Value Max_statement_time_exceeded 0 SET STATEMENT MAX_STATEMENT_TIME=1 FOR SELECT SLEEP(10); -ERROR 70100: Query execution was interrupted (max_statement_time exceeded) +ERROR 70100: Query was interrupted: execution time limit 1.0 sec exceeded SHOW STATUS LIKE "max_statement_time_exceeded"; Variable_name Value Max_statement_time_exceeded 1 diff --git a/mysql-test/suite/parts/r/print_error.result b/mysql-test/suite/parts/r/print_error.result index 74a13afeb4656..c1a9f139bc897 100644 --- a/mysql-test/suite/parts/r/print_error.result +++ b/mysql-test/suite/parts/r/print_error.result @@ -6,7 +6,7 @@ CREATE TABLE t2 SELECT * FROM t1;; connect con2,localhost,root,,test; SET max_statement_time= 1; DELETE FROM t1 PARTITION (p1) ORDER BY i LIMIT 2; -ERROR 70100: Query execution was interrupted (max_statement_time exceeded) +ERROR 70100: Query was interrupted: execution time limit 1.0 sec exceeded disconnect con2; connection default; XA END 'xid'; diff --git a/mysql-test/suite/versioning/r/not_embedded.result b/mysql-test/suite/versioning/r/not_embedded.result index 31de051a22070..19d15bece22f6 100644 --- a/mysql-test/suite/versioning/r/not_embedded.result +++ b/mysql-test/suite/versioning/r/not_embedded.result @@ -87,7 +87,7 @@ connection default; set timestamp= unix_timestamp('2000-01-01 01:00:00'); update t set a= a + 3; connection con1; -ERROR 70100: Query execution was interrupted (max_statement_time exceeded) +ERROR 70100: Query was interrupted: execution time limit 1.0 sec exceeded disconnect con1; connection default; commit; diff --git a/mysys/thr_timer.c b/mysys/thr_timer.c index 0fa932ceaf176..3a31b5ddd89eb 100644 --- a/mysys/thr_timer.c +++ b/mysys/thr_timer.c @@ -186,6 +186,7 @@ my_bool thr_timer_settime(thr_timer_t *timer_data, ulonglong micro_seconds) DBUG_ASSERT(timer_data->expired == 1); + timer_data->timeout= micro_seconds; set_timespec_nsec(timer_data->expire_time, micro_seconds*1000); timer_data->expired= 0; diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index 28cefd3dbf299..aa81e032c2e27 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -10516,10 +10516,10 @@ ER_PLUGIN_INSTALLED spa "Ya instalado el enchufe (plugin) '%-.192s'" sw "Programu-jalizi '%-.192s' tayari imesakinishwa" ER_STATEMENT_TIMEOUT 70100 - chi "查询执行中断(超出MAX_STATEMENT_TIME)" - eng "Query execution was interrupted (max_statement_time exceeded)" - sw "Utekelezaji wa hoja ulikatizwa (muda_wa_max_statement umepitwa)" - spa "Se ha interrumpido la ejecución de una consulta (query) (excedido max_statement_time) + chi "查询被中断:执行时间限制 %s 已超出" + eng "Query was interrupted: execution time limit %s exceeded" + sw "Hoja ilikatizwa: kikomo cha muda wa utekelezaji %s kimepitwa" + spa "Consulta interrumpida: límite de tiempo de ejecución %s excedido" ER_SUBQUERIES_NOT_SUPPORTED 42000 chi "%s不支持子查询或存储的函数" eng "%s does not support subqueries or stored functions" diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 0676a8d7d6466..8219562914b21 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -631,8 +631,29 @@ extern "C" void thd_kill_timeout(void *thd_) { THD *thd= static_cast(thd_); thd->status_var.max_statement_time_exceeded++; - /* Kill queries that can't cause data corruptions */ - thd->awake(KILL_TIMEOUT); + + if (thd->slave_thread) + { + /* Slave threads use ER_SLAVE_STATEMENT_TIMEOUT without custom message */ + thd->awake(KILL_TIMEOUT); + } + else + { + char msg[256], timeout_str[32]; + double timeout_sec= thd->query_timer.timeout / 1000000.0; + size_t len= my_snprintf(timeout_str, sizeof(timeout_str), "%g", timeout_sec); + /* + Ensure at least one decimal digit (e.g., "1" -> "1.0"), + but not for scientific notation + */ + if (!strchr(timeout_str, '.') && !strchr(timeout_str, 'e')) + len+= my_snprintf(timeout_str + len, sizeof(timeout_str) - len, ".0"); + my_snprintf(timeout_str + len, sizeof(timeout_str) - len, " sec"); + my_snprintf(msg, sizeof(msg), ER_THD(thd, ER_STATEMENT_TIMEOUT), timeout_str); + + /* Kill queries that can't cause data corruptions */ + thd->awake(KILL_TIMEOUT, ER_STATEMENT_TIMEOUT, msg); + } } const char *thd_where(THD *thd) @@ -2060,7 +2081,9 @@ void add_diff_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var, NOT_KILLED is used to awake a thread for a slave */ extern std::atomic shutdown_thread_id; -void THD::awake_no_mutex(killed_state state_to_set) +void THD::awake_no_mutex(killed_state state_to_set, + int killed_errno_arg, + const char *killed_err_msg_arg) { DBUG_ENTER("THD::awake_no_mutex"); DBUG_PRINT("enter", ("this: %p current_thd: %p state: %d", @@ -2078,7 +2101,7 @@ void THD::awake_no_mutex(killed_state state_to_set) if (killed >= KILL_CONNECTION) state_to_set= killed; - set_killed_no_mutex(state_to_set); + set_killed_no_mutex(state_to_set, killed_errno_arg, killed_err_msg_arg); if (state_to_set >= KILL_CONNECTION || state_to_set == NOT_KILLED) { diff --git a/sql/sql_class.h b/sql/sql_class.h index bf9df5cdce7b9..d30bb015dbcf6 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -4399,12 +4399,16 @@ class THD: public THD_count, /* this must be first */ } void close_active_vio(); #endif - void awake_no_mutex(killed_state state_to_set); - void awake(killed_state state_to_set) + void awake_no_mutex(killed_state state_to_set, + int killed_errno_arg= 0, + const char *killed_err_msg_arg= 0); + void awake(killed_state state_to_set, + int killed_errno_arg= 0, + const char *killed_err_msg_arg= 0) { mysql_mutex_lock(&LOCK_thd_kill); mysql_mutex_lock(&LOCK_thd_data); - awake_no_mutex(state_to_set); + awake_no_mutex(state_to_set, killed_errno_arg, killed_err_msg_arg); mysql_mutex_unlock(&LOCK_thd_data); mysql_mutex_unlock(&LOCK_thd_kill); }