bug#28570: handler::index_read() is called with different find_flag when
ORDER BY is used The range analysis module did not correctly signal to the handler that a range represents a ref (EQ_RANGE flag). This causes non-range queries like SELECT ... FROM ... WHERE keypart_1=const, ..., keypart_n=const ORDER BY ... FOR UPDATE to wait for a lock unneccesarily if another running transaction uses SELECT ... FOR UPDATE on the same table. Fixed by setting EQ_RANGE for all range accesses that represent an equality predicate. mysql-test/r/innodb_mysql.result: bug#28570: Test Result mysql-test/t/innodb_mysql.test: bug#28570: Test Case sql/handler.cc: bug#28570: Updated comment sql/opt_range.cc: bug#28570: Removed the criterion that key has to be unique (HA_NOSAME) in order for the EQ_RANGE flag to be set. It is sufficient that the range represent a ref access.
This commit is contained in:
parent
1f83b35181
commit
01f8130aa6
@ -1007,4 +1007,22 @@ CALL p1();
|
||||
CALL p1();
|
||||
DROP PROCEDURE p1;
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (
|
||||
a INT,
|
||||
b INT,
|
||||
KEY (b)
|
||||
) ENGINE=InnoDB;
|
||||
INSERT INTO t1 VALUES (1,10), (2,10), (2,20), (3,30);
|
||||
START TRANSACTION;
|
||||
SELECT * FROM t1 WHERE b=20 FOR UPDATE;
|
||||
a b
|
||||
2 20
|
||||
START TRANSACTION;
|
||||
SELECT * FROM t1 WHERE b=10 ORDER BY A FOR UPDATE;
|
||||
a b
|
||||
1 10
|
||||
2 10
|
||||
ROLLBACK;
|
||||
ROLLBACK;
|
||||
DROP TABLE t1;
|
||||
End of 5.0 tests
|
||||
|
@ -840,5 +840,34 @@ DISCONNECT con2;
|
||||
DROP PROCEDURE p1;
|
||||
DROP TABLE t1;
|
||||
|
||||
#
|
||||
# Bug #28570: handler::index_read() is called with different find_flag when
|
||||
# ORDER BY is used
|
||||
#
|
||||
|
||||
CREATE TABLE t1 (
|
||||
a INT,
|
||||
b INT,
|
||||
KEY (b)
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
INSERT INTO t1 VALUES (1,10), (2,10), (2,20), (3,30);
|
||||
|
||||
START TRANSACTION;
|
||||
SELECT * FROM t1 WHERE b=20 FOR UPDATE;
|
||||
|
||||
--connect (conn2, localhost, root,,test)
|
||||
|
||||
# This statement gives a "failed: 1205: Lock wait timeout exceeded; try
|
||||
# restarting transaction" message when the bug is present.
|
||||
START TRANSACTION;
|
||||
SELECT * FROM t1 WHERE b=10 ORDER BY A FOR UPDATE;
|
||||
ROLLBACK;
|
||||
|
||||
--disconnect conn2
|
||||
--connection default
|
||||
|
||||
ROLLBACK;
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo End of 5.0 tests
|
||||
|
@ -2610,7 +2610,8 @@ int handler::read_multi_range_next(KEY_MULTI_RANGE **found_range_p)
|
||||
read_range_first()
|
||||
start_key Start key. Is 0 if no min range
|
||||
end_key End key. Is 0 if no max range
|
||||
eq_range_arg Set to 1 if start_key == end_key
|
||||
eq_range_arg Set to 1 if start_key == end_key and the range endpoints
|
||||
will not change during query execution.
|
||||
sorted Set to 1 if result should be sorted per key
|
||||
|
||||
NOTES
|
||||
|
@ -6369,8 +6369,7 @@ QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table,
|
||||
range->min_key=range->max_key=(char*) ref->key_buff;
|
||||
range->min_length=range->max_length=ref->key_length;
|
||||
range->flag= ((ref->key_length == key_info->key_length &&
|
||||
(key_info->flags & (HA_NOSAME | HA_END_SPACE_KEY)) ==
|
||||
HA_NOSAME) ? EQ_RANGE : 0);
|
||||
(key_info->flags & HA_END_SPACE_KEY) == 0) ? EQ_RANGE : 0);
|
||||
|
||||
if (!(quick->key_parts=key_part=(KEY_PART *)
|
||||
alloc_root(&quick->alloc,sizeof(KEY_PART)*ref->key_parts)))
|
||||
|
Loading…
x
Reference in New Issue
Block a user