Bug #50953 | Locked rows change in number, strangely. | ||
---|---|---|---|
Submitted: | 5 Feb 2010 18:40 | Modified: | 6 Feb 2010 8:08 |
Reporter: | Yoshiaki Tajika (Basic Quality Contributor) | Email Updates: | |
Status: | Verified | Impact on me: | |
Category: | MySQL Server: Optimizer | Severity: | S2 (Serious) |
Version: | 5.1.41, 5.1.44, 5.5.99 | OS: | Any |
Assigned to: | CPU Architecture: | Any |
[5 Feb 2010 18:40]
Yoshiaki Tajika
[6 Feb 2010 8:08]
Sveta Smirnova
Thank you for the report. Verified as described.
[8 Feb 2010 15:47]
MySQL Verification Team
Sveta, Please check whether this bug is duplicate of, or related to the bug #41756. Thanks ...
[9 Feb 2010 7:26]
Sveta Smirnova
Sinisa, not, this is not duplicate of bug #41756. Also they could be not related at all, because this one repeatable with earlier versions.
[25 Feb 2010 8:23]
Jimmy Yang
My SQL Optimizer/QP should take a look at this issue. The root cause seems due to two different plans generated for the same query in scenario described by the reporter. The query plan before the "delete from t1" call is following: mysql> explain select 1 from t1 natural join (select * from t2) as d for update; +----+-------------+------------+--------+---------------+---------+---------+------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+------------+--------+---------------+---------+---------+------+------+-------------+ | 1 | PRIMARY | <derived2> | ALL | NULL | NULL | NULL | NULL | 2 | | | 1 | PRIMARY | t1 | eq_ref | PRIMARY | PRIMARY | 4 | d.c2 | 1 | Using where | | 2 | DERIVED | t2 | ALL | NULL | NULL | NULL | NULL | 2 | | +----+-------------+------------+--------+---------------+---------+---------+------+------+-------------+ 3 rows in set (7.82 sec) The query issued after the "delete from t1" call has following plan: mysql> explain select 1 from t1 natural join (select * from t2) as d for update; +----+-------------+------------+------+---------------+------+---------+------+------+--------------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+------------+------+---------------+------+---------+------+------+--------------------------------+ | 1 | PRIMARY | t1 | ALL | PRIMARY | NULL | NULL | NULL | 1 | | | 1 | PRIMARY | <derived2> | ALL | NULL | NULL | NULL | NULL | 2 | Using where; Using join buffer | | 2 | DERIVED | t2 | ALL | NULL | NULL | NULL | NULL | 2 | | +----+-------------+------------+------+---------------+------+---------+------+------+--------------------------------+ 3 rows in set (7.93 sec) In the first query, only one row in t1 is locked, here is the calling stack: sel_set_rec_lock row_search_for_mysql ha_innobase::index_read handler::index_read_map join_read_key sub_select evaluate_join_record sub_select do_select JOIN::exec mysql_select Table t1 is no long being scanned in subsequent loop, the temp table is checked instead: sub_select() { ... while (rc == NESTED_LOOP_OK) { error= info->read_record(info); rc= evaluate_join_record(join, join_tab, error); } ... } (gdb) p join_tab->read_record->table->s->path $120 = { str = 0xacbc118 "/home/jyang/backup/repo/mysql-5.1/mysql-test/var/tmp/mysqld.1/#sql_685c_0", length = 73} For the second query plan, table t1 is being reaccess in above loop, and thus all 4 rows in t1 are being read: (gdb) p join_tab->read_record->table->s->path $129 = {str = 0xac9c9e8 "./test/t1", length = 9} here is the actual calling stack that locks the 4 rows sel_set_rec_lock row_search_for_mysql ha_innobase::general_fetch ha_innobase::rnd_next rr_sequential sub_select do_select evaluate_join_record <=== sub_select do_select JOIN::exec mysql_select So for this query plan, in the final loop phase, all 4 t1 rows are read. While in the first query plan, the temp table is accessed instead of table t1. This explains the difference of 1 row locked vs. 4 row locked. The optimizer or query generation team need to look into why two different plan is generate in this scenario. Also, to explain why there is case that shows 5 rows locked, the one addition row is most likely the InnoDB internal row (supremum): RECORD LOCKS space id 0 page no 50 n bits 72 index `PRIMARY` of table `test`.`t1` trx id 0 1796 lock_mode X Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0 0: len 8; hex 73757072656d756d; asc supremum;;
[25 Feb 2010 8:34]
Calvin Sun
Change the category to optimizer based on Jimmy's analysis.