Bug #110341 | FOUND_ROWS() gives wrong result on prepared query against partitioned table | ||
---|---|---|---|
Submitted: | 10 Mar 2023 17:18 | Modified: | 13 Mar 2023 7:50 |
Reporter: | Bill Karwin (Candidate Quality Contributor) (OCA) | Email Updates: | |
Status: | Verified | Impact on me: | |
Category: | MySQL Server: Partitions | Severity: | S3 (Non-critical) |
Version: | 8.0.32 | OS: | Any |
Assigned to: | CPU Architecture: | Any |
[10 Mar 2023 17:18]
Bill Karwin
[10 Mar 2023 17:22]
Bill Karwin
Further test: It seems to be a problem related only to using parameters. If I use a prepared query with fixed values (no parameters), then FOUND_ROWS() correctly reports 2. SET @s = CONCAT('select * from t2 where created_at in (', QUOTE(@p1), ',', QUOTE(@p2), ')'); prepare stmt from @s; execute stmt; -- returns 2 rows as expected select found_rows(); -- returns count of 2 as expected
[13 Mar 2023 6:34]
MySQL Verification Team
Hello Bill, Thank you for the report and feedback. Thanks, Umesh
[13 Mar 2023 6:38]
MySQL Verification Team
Also, SQL_CALC_FOUND_ROWS query modifier and accompanying FOUND_ROWS() function are deprecated as of MySQL 8.0.17 and will be removed in a future release. Consider using COUNT(*) instead. Please see https://dev.mysql.com/doc/refman/8.0/en/information-functions.html#function_found-rows
[13 Mar 2023 7:22]
MySQL Verification Team
- 5.7 not affected bin/mysql -uroot -S /tmp/mysql.sock Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 2 Server version: 5.7.41 MySQL Community Server (GPL) Copyright (c) 2000, 2023, Oracle and/or its affiliates. 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> SELECT VERSION(); SET @p1 = '2023-02-03', @p2='2023-02-25'; CREATE TABLE t1 ( created_at DATE ) ; INSERT INTO t1 VALUES (@p1), (@p2); SET @s = "select * from t1 where created_at in (?, ?)"; PREPARE stmt FROM @s; EXECUTE stmt USING @p1, @p2; -- returns 2 rows as expected SELECT FOUND_ROWS(); -- returns count of 2 as expected +-----------+ | VERSION() | +-----------+ | 5.7.41 | +-----------+ 1 row in set (0.00 sec) mysql> mysql> SET @p1 = '2023-02-03', @p2='2023-02-25'; Query OK, 0 rows affected (0.00 sec) mysql> mysql> CREATE TABLE t1 ( -> created_at DATE -> ) ; Query OK, 0 rows affected (0.01 sec) mysql> mysql> INSERT INTO t1 VALUES (@p1), (@p2); Query OK, 2 rows affected (0.00 sec) Records: 2 Duplicates: 0 Warnings: 0 mysql> mysql> SET @s = "select * from t1 where created_at in (?, ?)"; Query OK, 0 rows affected (0.00 sec) mysql> mysql> PREPARE stmt FROM @s; Query OK, 0 rows affected (0.00 sec) Statement prepared mysql> mysql> EXECUTE stmt USING @p1, @p2; -- returns 2 rows as expected +------------+ | created_at | +------------+ | 2023-02-03 | | 2023-02-25 | +------------+ 2 rows in set (0.00 sec) mysql> mysql> SELECT FOUND_ROWS(); -- returns count of 2 as expected +--------------+ | FOUND_ROWS() | +--------------+ | 2 | +--------------+ 1 row in set (0.00 sec) mysql> mysql> DEALLOCATE PREPARE stmt; Query OK, 0 rows affected (0.00 sec) mysql> DEALLOCATE PREPARE stmt; ERROR 1243 (HY000): Unknown prepared statement handler (stmt) given to DEALLOCATE PREPARE mysql> mysql> CREATE TABLE t2 ( -> created_at DATE -> ) -> PARTITION BY RANGE (DAYOFMONTH(created_at)) ( -> PARTITION p1 VALUES LESS THAN (16), -> PARTITION p2 VALUES LESS THAN MAXVALUE -> ); Query OK, 0 rows affected (0.02 sec) mysql> mysql> INSERT INTO t2 VALUES (@p1), (@p2); Query OK, 2 rows affected (0.00 sec) Records: 2 Duplicates: 0 Warnings: 0 mysql> mysql> SET @s = "select * from t2 where created_at in (?, ?)"; Query OK, 0 rows affected (0.00 sec) mysql> mysql> PREPARE stmt FROM @s; Query OK, 0 rows affected (0.00 sec) Statement prepared mysql> mysql> EXECUTE stmt USING @p1, @p2; -- returns 2 rows as expected +------------+ | created_at | +------------+ | 2023-02-03 | | 2023-02-25 | +------------+ 2 rows in set (0.00 sec) mysql> mysql> SELECT FOUND_ROWS(); -- returns count of 0, this is incorrect +--------------+ | FOUND_ROWS() | +--------------+ | 2 | +--------------+ 1 row in set (0.00 sec) mysql> mysql> DEALLOCATE PREPARE stmt; Query OK, 0 rows affected (0.00 sec)
[13 Mar 2023 7:50]
Bill Karwin
Thanks, I know that FOUND_ROWS() is deprecated. Deprecated does not mean buggy or that it fails in arbitrary ways. Deprecated means it should continue to work as it had worked in the past, to give users a chance to adopt another solution. Also, the same bug occurs in connectors that call the C API function mysql_affected_rows(). The C API is not deprecated.
[13 Mar 2023 7:55]
Bill Karwin
PHP script that demonstrates the bug using the C API.
Attachment: test.php (text/php), 649 bytes.
[16 Mar 2023 14:12]
huahua xu
Hi all: It is very terrible that my mysqld is crashed, when I excute the prepared query with parameters against a partitioned table. The error information: Assertion failed: param_state() != NO_VALUE, file D:\SourceDebug\MySQL\mysql-8.0.32\sql\item.cc, line 4224 abort() has been called2023-03-16T12:32:56Z UTC - mysqld got exception 0x80000003 ; Most likely, you have hit a bug, but this error can also be caused by malfunctioning hardware. Thread pointer: 0x1f3e4a46e50 Attempting backtrace. You can use the following information to find out where mysqld died. If you see no messages after this, something went terribly wrong... 7ff7672573a4 mysqld.exe!my_sigabrt_handler()[my_thr_init.cc:372] 7ff92e9bc3e1 ucrtbased.dll!raise() 7ff92e9be039 ucrtbased.dll!abort() 7ff92e9c386f ucrtbased.dll!_get_wide_winmain_command_line() 7ff92e9c1868 ucrtbased.dll!_get_wide_winmain_command_line() 7ff92e9c41cf ucrtbased.dll!_wassert() 7ff7650e6126 mysqld.exe!Item_param::val_str()[item.cc:4224] 7ff7650d1b5c mysqld.exe!Item::get_date_from_string()[item.cc:1434] 7ff7650e6933 mysqld.exe!Item_param::get_date()[item.cc:4118] 7ff7650cfa7f mysqld.exe!Item::val_date_temporal()[item.cc:392] 7ff764f257dc mysqld.exe!get_datetime_value()[item_cmpfunc.cc:1517] 7ff764f14d92 mysqld.exe!in_datetime::set()[item_cmpfunc.cc:4511] 7ff764f140cc mysqld.exe!in_vector::fill()[item_cmpfunc.cc:4251] 7ff764f1b868 mysqld.exe!Item_func_in::populate_bisection()[item_cmpfunc.cc:5396] 7ff7658d13b7 mysqld.exe!get_func_mm_tree_from_in_predicate()[range_analysis.cc:179] 7ff7658d327d mysqld.exe!get_func_mm_tree()[range_analysis.cc:609] 7ff7658d0b8c mysqld.exe!get_full_func_mm_tree()[range_analysis.cc:775] 7ff7658d437a mysqld.exe!get_mm_tree()[range_analysis.cc:964] 7ff765a76ca0 mysqld.exe!prune_partitions()[partition_pruning.cc:323] 7ff7657cb570 mysqld.exe!Query_block::apply_local_transforms()[sql_resolver.cc:809] 7ff7657cf070 mysqld.exe!Query_block::prepare()[sql_resolver.cc:592] 7ff76577f38f mysqld.exe!Sql_cmd_select::prepare_inner()[sql_select.cc:470] 7ff76577cfea mysqld.exe!Sql_cmd_dml::prepare()[sql_select.cc:386] 7ff7656b0159 mysqld.exe!Prepared_statement::prepare_query()[sql_prepare.cc:1419] 7ff7656b169e mysqld.exe!Prepared_statement::prepare()[sql_prepare.cc:2595] 7ff7656ae8d7 mysqld.exe!mysql_sql_stmt_prepare()[sql_prepare.cc:1826] 7ff7653668fa mysqld.exe!mysql_execute_command()[sql_parse.cc:3343] 7ff7653649f6 mysqld.exe!dispatch_sql_command()[sql_parse.cc:5322] 7ff7653701b6 mysqld.exe!dispatch_command()[sql_parse.cc:2040] 7ff76536d75e mysqld.exe!do_command()[sql_parse.cc:1439] 7ff764f440ae mysqld.exe!handle_connection()[connection_handler_per_thread.cc:302] 7ff7681e9a6f mysqld.exe!pfs_spawn_thread()[pfs.cc:2988] 7ff767255cfc mysqld.exe!win_thread_start()[my_thread.cc:73] 7ff92e9c542c ucrtbased.dll!_register_onexit_function() 7ff990647034 KERNEL32.DLL!BaseThreadInitThunk() 7ff990b62651 ntdll.dll!RtlUserThreadStart() Trying to get some variables. Some pointers may be invalid and cause the dump to abort. Query (1f3e1eef6d8): select * from t2 where created_at in (?, ?) Connection ID (thread ID): 8 Status: NOT_KILLED The manual page at http://dev.mysql.com/doc/mysql/en/crashing.html contains information that should help you find out what is causing the crash.