Bug #96537 Differing error for MAX_EXECUTION_TIME depending on query stage at termination

Submitted: 14 Aug 2019 17:14 Modified: 22 Oct 2019 22:11
Reporter: Jeremy Cole (Basic Quality Contributor) (OCA) Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server: Optimizer Severity:S3 (Non-critical)
Version:5.7, 5.7.27, 8.0.17 OS:Any
Assigned to: CPU Architecture:Any
Tags: 1028, 3024, error, max_execution_time

[14 Aug 2019 17:14] Jeremy Cole
Description:
When a query is terminated due to exceeding its maximum execution time specified using the MAX_EXECUTION_TIME hint, the error produced will differ depending on the query stage at termination. Most queries will produce ER_QUERY_TIMEOUT (3024), but if a query is terminated during filesort, ER_FILSORT_ABORT (1028) will be produced instead.

This makes it unnecessarily harder to trap these errors and respond correctly. 

How to repeat:
Using a simple table with the sysbench structure:

CREATE TABLE `t` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `k` int(11) NOT NULL DEFAULT '0',
  `c` char(120) NOT NULL DEFAULT '',
  `pad` char(60) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`),
  KEY `k_1` (`k`)
) ENGINE=InnoDB;

<insert 500 rows as appropriate>

> select count(*) from t;
+----------+
| count(*) |
+----------+
|      500 |
+----------+

A query that gets terminated before sort produces error 3024 as expected:

> select /*+ max_execution_time(50) */ * from t a, t b order by a.pad asc, b.pad desc limit 1;
ERROR 3024 (HY000): Query execution was interrupted, maximum statement execution time exceeded

If the same query is terminated during filesort, error 1028 is produced instead of error 3024:

> select /*+ max_execution_time(300) */ * from t a, t b order by a.pad asc, b.pad desc limit 1;
ERROR 1028 (HY000): Sort aborted: Query execution was interrupted, maximum statement execution time exceeded

Suggested fix:
When a query is terminated due to exceeding maximum execution time, capture the ER_FILSORT_ABORT (1028) error internally and translate it to ER_QUERY_TIMEOUT (3024).
[14 Aug 2019 17:25] Jeremy Cole
Note this was noted originally in Rails: https://github.com/rails/rails/pull/36932
[15 Aug 2019 7:51] MySQL Verification Team
Hello Jeremy,

Thank you for the report and test case.
Observed this with 5.7.27 build.

regards,
Umesh
[15 Aug 2019 7:51] MySQL Verification Team
- 5.7.27

DROP TABLE if exists t;
CREATE TABLE `t` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `k` int(11) NOT NULL DEFAULT '0',
  `c` char(120) NOT NULL DEFAULT '',
  `pad` char(60) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`),
  KEY `k_1` (`k`)
) ENGINE=InnoDB;

set @id:=0;
insert into `t` values(@id:=@id+1,@id:=@id+1,repeat('A',120),repeat('A',60)), (@id:=@id+1,@id:=@id+1,repeat('A',120),repeat('A',60)), (@id:=@id+1,@id:=@id+1,repeat('A',120),repeat('A',60)), (@id:=@id+1,@id:=@id+1,repeat('A',120),repeat('A',60));
insert into `t`(`id`,`k`,`c`,`pad`) select  @id:=@id+1,@id:=@id+1,repeat('A',120),repeat('A',60)  from `t` k1, `t` k2, `t` k3, `t` k4,`t` k5,`t` k6, `t` k7, `t` k8, `t` k9,`t` k0,`t` ka, `t` kb, `t` kc, `t` kd limit  500;  

-- 5.7.27

mysql>
mysql> insert into `t`(`id`,`k`,`c`,`pad`) select  @id:=@id+1,@id:=@id+1,repeat('A',120),repeat('A',60)  from `t` k1, `t` k2, `t` k3, `t` k4,`t` k5,`t` k6, `t` k7, `t` k8, `t` k9,`t` k0,`t` ka, `t` kb, `t` kc, `t` kd limit  500;
Query OK, 500 rows affected (0.07 sec)
Records: 500  Duplicates: 0  Warnings: 0

mysql> select /*+ max_execution_time(50) */ * from t a, t b order by a.pad asc, b.pad desc limit 1;
ERROR 3024 (HY000): Query execution was interrupted, maximum statement execution time exceeded
mysql>
mysql> select /*+ max_execution_time(300) */ * from t a, t b order by a.pad asc, b.pad desc limit 1;
ERROR 1028 (HY000): Sort aborted: Query execution was interrupted, maximum statement execution time exceeded
mysql>
mysql> show variables like '%version%';
+-------------------------+------------------------------+
| Variable_name           | Value                        |
+-------------------------+------------------------------+
| innodb_version          | 5.7.27                       |
| protocol_version        | 10                           |
| slave_type_conversions  |                              |
| tls_version             | TLSv1,TLSv1.1                |
| version                 | 5.7.27                       |
| version_comment         | MySQL Community Server (GPL) |
| version_compile_machine | x86_64                       |
| version_compile_os      | linux-glibc2.12              |
+-------------------------+------------------------------+
8 rows in set (0.00 sec)

 cat /etc/*release
Oracle Linux Server release 7.1
NAME="Oracle Linux Server"
VERSION="7.1"
ID="ol"
VERSION_ID="7.1"
PRETTY_NAME="Oracle Linux Server 7.1"
ANSI_COLOR="0;31"
CPE_NAME="cpe:/o:oracle:linux:7:1"
HOME_URL="https://linux.oracle.com/"
BUG_REPORT_URL="https://bugzilla.oracle.com/"

ORACLE_BUGZILLA_PRODUCT="Oracle Linux 7"
ORACLE_BUGZILLA_PRODUCT_VERSION=7.1
ORACLE_SUPPORT_PRODUCT="Oracle Linux"
ORACLE_SUPPORT_PRODUCT_VERSION=7.1
Red Hat Enterprise Linux Server release 7.1 (Maipo)
Oracle Linux Server release 7.1
[15 Aug 2019 7:54] MySQL Verification Team
- 8.0.17

 bin/mysql -uroot -S /tmp/mysql_ushastry.sock
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 7
Server version: 8.0.17 MySQL Community Server - GPL

Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> create database test;
Query OK, 1 row affected (0.00 sec)

mysql> use test
Database changed
mysql> DROP TABLE if exists t;
CREATE TABLE `t` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `k` int(11) NOT NULL DEFAULT '0',
  `c` char(120) NOT NULL DEFAULT '',
  `pad` char(60) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`),
  KEY `k_1` (`k`)
) ENGINE=InnoDB;

set @id:=0;
insert into `t` values(@id:=@id+1,@id:=@id+1,repeat('A',120),repeat('A',60)), (@id:=@id+1,@id:=@id+1,repeat('A',120),repeat('A',60)), (@id:=@id+1,@id:=@id+1,repeat('A',120),repeat('A',60)), (@id:=@id+1,@id:=@id+1,repeat('A',120),repeat('A',60));
insert into `t`(`id`,`k`,`c`,`pad`) select  @id:=@id+1,@id:=@id+1,repeat('A',120),repeat('A',60)  from `t` k1, `t` k2, `t` k3, `t` k4,`t` k5,`t` k6, `t` k7, `t` k8, `t` k9,`t` k0,`t` ka, `t` kb, `t` kc, `t` kd limit  500;
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> CREATE TABLE `t` (
    ->   `id` int(11) NOT NULL AUTO_INCREMENT,
    ->   `k` int(11) NOT NULL DEFAULT '0',
    ->   `c` char(120) NOT NULL DEFAULT '',
    ->   `pad` char(60) NOT NULL DEFAULT '',
    ->   PRIMARY KEY (`id`),
    ->   KEY `k_1` (`k`)
    -> ) ENGINE=InnoDB;
Query OK, 0 rows affected, 2 warnings (0.01 sec)

mysql>
mysql> set @id:=0;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into `t` values(@id:=@id+1,@id:=@id+1,repeat('A',120),repeat('A',60)), (@id:=@id+1,@id:=@id+1,repeat('A',120),repeat('A',60)), (@id:=@id+1,@id:=@id+1,repeat('A',120),repeat('A',60)), (@id:=@id+1,@id:=@id+1,repeat('A',120),repeat('A',60));
Query OK, 4 rows affected, 8 warnings (0.01 sec)
Records: 4  Duplicates: 0  Warnings: 8

mysql> insert into `t`(`id`,`k`,`c`,`pad`) select  @id:=@id+1,@id:=@id+1,repeat('A',120),repeat('A',60)  from `t` k1, `t` k2, `t` k3, `t` k4,`t` k5,`t` k6, `t` k7, `t` k8, `t` k9,`t` k0,`t` ka, `t` kb, `t` kc, `t` kd limit  500;
Query OK, 500 rows affected, 2 warnings (0.06 sec)
Records: 500  Duplicates: 0  Warnings: 2

mysql> show warnings;
+---------+------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Level   | Code | Message                                                                                                                                                                                              |
+---------+------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Warning | 1287 | Setting user variables within expressions is deprecated and will be removed in a future release. Consider alternatives: 'SET variable=expression, ...', or 'SELECT expression(s) INTO variables(s)'. |
| Warning | 1287 | Setting user variables within expressions is deprecated and will be removed in a future release. Consider alternatives: 'SET variable=expression, ...', or 'SELECT expression(s) INTO variables(s)'. |
+---------+------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
2 rows in set (0.00 sec)

mysql> select /*+ max_execution_time(50) */ * from t a, t b order by a.pad asc, b.pad desc limit 1;
ERROR 3024 (HY000): Query execution was interrupted, maximum statement execution time exceeded
mysql>
mysql> select /*+ max_execution_time(300) */ * from t a, t b order by a.pad asc, b.pad desc limit 1;
ERROR 1028 (HY000): Sort aborted: Query execution was interrupted, maximum statement execution time exceeded
[22 Oct 2019 22:11] Jon Stephens
DOcumented fix in the MySQL 8.0.19 changelog as follows:

    When a query terminated due to exceeding the time specified
    using the MAX_EXECUTION_TIME hint, the error produced differed
    depending on the stage of the query. In particular, if the query
    terminated during a filesort, the error raised was
    ER_FILSORT_ABORT, even though in such cases the query should
    always exit with ER_QUERY_TIMEOUT. This made it unnecessarily
    difficult to trap such errors and to handle them correctly.

    This fix removes the error codes ER_FILSORT_ABORT and
    ER_FILESORT_TERMINATED.

Closed.

Portions of this website are copyright © 2001, 2002 The PHP Group

Page generated in 0.055 sec. using MySQL 8.4.7-u6-cloud

Timestamp references displayed by the system are UTC.
Content reproduced on this site is the property of the respective copyright holders.
It is not reviewed in advance by Oracle and does not necessarily represent the opinion of Oracle or any other party.