mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 20:12:31 +01:00
Fixed bug #31310.
Locked rows of the InnoDB storage was silently skipped in the read-committed isolation level. QUICK_RANGE_SELECT for unique ranges lacks second (blocking) read of the record that was read semi-consistently and just skip it. The handler::read_multi_range_next method has been modified to retry previous unique range if the previous read was semi-consistent. sql/handler.cc: Fixed bug #31310. The handler::read_multi_range_next method has been modified to retry previous unique range if the previous read was semi-consistent. mysql-test/include/mix1.inc: Added test case for bug #31310. mysql-test/r/innodb_mysql.result: Added test case for bug #31310.
This commit is contained in:
parent
db39be9510
commit
b9805a5a45
3 changed files with 210 additions and 3 deletions
|
@ -29,6 +29,7 @@ eval SET SESSION STORAGE_ENGINE = $engine_type;
|
|||
|
||||
--disable_warnings
|
||||
drop table if exists t1,t2,t3,t1m,t1i,t2m,t2i,t4;
|
||||
drop procedure if exists p1;
|
||||
--enable_warnings
|
||||
|
||||
|
||||
|
@ -1146,4 +1147,128 @@ select @b:=f2 from t1;
|
|||
select if(@a=@b,"ok","wrong");
|
||||
drop table t1;
|
||||
|
||||
#
|
||||
# Bug #31310: Locked rows silently skipped in read-committed isolation level.
|
||||
#
|
||||
|
||||
connect (con1,localhost,root,,);
|
||||
connect (con2,localhost,root,,);
|
||||
SET SESSION AUTOCOMMIT = 0;
|
||||
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
|
||||
--echo # Switch to connection con1
|
||||
connection con1;
|
||||
|
||||
eval
|
||||
CREATE TABLE t1 (a INT PRIMARY KEY, b VARCHAR(256))
|
||||
ENGINE = $engine_type;
|
||||
INSERT INTO t1 VALUES (1,2);
|
||||
|
||||
--#echo 1. test for locking:
|
||||
|
||||
BEGIN;
|
||||
--enable_info
|
||||
UPDATE t1 SET b = 12 WHERE a = 1;
|
||||
--disable_info
|
||||
SELECT * FROM t1;
|
||||
|
||||
--echo # Switch to connection con2
|
||||
connection con2;
|
||||
|
||||
--enable_info
|
||||
--disable_abort_on_error
|
||||
--error ER_LOCK_WAIT_TIMEOUT
|
||||
UPDATE t1 SET b = 21 WHERE a = 1;
|
||||
--disable_info
|
||||
|
||||
--echo # Switch to connection con1
|
||||
connection con1;
|
||||
SELECT * FROM t1;
|
||||
ROLLBACK;
|
||||
|
||||
--echo # 2. test for serialized update:
|
||||
|
||||
CREATE TABLE t2 (a INT);
|
||||
|
||||
TRUNCATE t1;
|
||||
INSERT INTO t1 VALUES (1,'init');
|
||||
|
||||
DELIMITER |;
|
||||
CREATE PROCEDURE p1()
|
||||
BEGIN
|
||||
UPDATE t1 SET b = CONCAT(b, '+con2') WHERE a = 1;
|
||||
INSERT INTO t2 VALUES ();
|
||||
END|
|
||||
DELIMITER ;|
|
||||
|
||||
BEGIN;
|
||||
--enable_info
|
||||
UPDATE t1 SET b = CONCAT(b, '+con1') WHERE a = 1;
|
||||
--disable_info
|
||||
SELECT * FROM t1;
|
||||
|
||||
--echo # Switch to connection con2
|
||||
connection con2;
|
||||
|
||||
--send CALL p1;
|
||||
|
||||
--echo # Switch to connection con1
|
||||
connection con1;
|
||||
SELECT * FROM t1;
|
||||
COMMIT;
|
||||
|
||||
let $bug31310 = 1;
|
||||
while ($bug31310)
|
||||
{
|
||||
let $bug31310= `SELECT 1 - COUNT(*) FROM t2`;
|
||||
}
|
||||
|
||||
SELECT * FROM t1;
|
||||
|
||||
--echo # Switch to connection con2
|
||||
connection con2;
|
||||
SELECT * FROM t1;
|
||||
|
||||
--echo # Switch to connection con1
|
||||
connection con1;
|
||||
|
||||
--echo # 3. test for updated key column:
|
||||
|
||||
TRUNCATE t1;
|
||||
TRUNCATE t2;
|
||||
|
||||
INSERT INTO t1 VALUES (1,'init');
|
||||
|
||||
BEGIN;
|
||||
--enable_info
|
||||
UPDATE t1 SET a = 2, b = CONCAT(b, '+con1') WHERE a = 1;
|
||||
--disable_info
|
||||
SELECT * FROM t1;
|
||||
|
||||
--echo # Switch to connection con2
|
||||
connection con2;
|
||||
|
||||
--send CALL p1;
|
||||
|
||||
--echo # Switch to connection con1
|
||||
connection con1;
|
||||
SELECT * FROM t1;
|
||||
COMMIT;
|
||||
|
||||
let $bug31310 = 1;
|
||||
while ($bug31310)
|
||||
{
|
||||
let $bug31310= `SELECT 1 - COUNT(*) FROM t2`;
|
||||
}
|
||||
|
||||
SELECT * FROM t1;
|
||||
|
||||
--echo # Switch to connection con2
|
||||
connection con2;
|
||||
SELECT * FROM t1;
|
||||
|
||||
connection default;
|
||||
disconnect con1;
|
||||
disconnect con2;
|
||||
DROP PROCEDURE p1;
|
||||
DROP TABLE t1, t2;
|
||||
--echo End of 5.1 tests
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
SET SESSION STORAGE_ENGINE = InnoDB;
|
||||
drop table if exists t1,t2,t3,t1m,t1i,t2m,t2i,t4;
|
||||
drop procedure if exists p1;
|
||||
create table t1 (
|
||||
c_id int(11) not null default '0',
|
||||
org_id int(11) default null,
|
||||
|
@ -1419,4 +1420,83 @@ select if(@a=@b,"ok","wrong");
|
|||
if(@a=@b,"ok","wrong")
|
||||
ok
|
||||
drop table t1;
|
||||
SET SESSION AUTOCOMMIT = 0;
|
||||
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
|
||||
# Switch to connection con1
|
||||
CREATE TABLE t1 (a INT PRIMARY KEY, b VARCHAR(256))
|
||||
ENGINE = InnoDB;
|
||||
INSERT INTO t1 VALUES (1,2);
|
||||
BEGIN;
|
||||
UPDATE t1 SET b = 12 WHERE a = 1;
|
||||
affected rows: 1
|
||||
info: Rows matched: 1 Changed: 1 Warnings: 0
|
||||
SELECT * FROM t1;
|
||||
a b
|
||||
1 12
|
||||
# Switch to connection con2
|
||||
UPDATE t1 SET b = 21 WHERE a = 1;
|
||||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
||||
# Switch to connection con1
|
||||
SELECT * FROM t1;
|
||||
a b
|
||||
1 12
|
||||
ROLLBACK;
|
||||
# 2. test for serialized update:
|
||||
CREATE TABLE t2 (a INT);
|
||||
TRUNCATE t1;
|
||||
INSERT INTO t1 VALUES (1,'init');
|
||||
CREATE PROCEDURE p1()
|
||||
BEGIN
|
||||
UPDATE t1 SET b = CONCAT(b, '+con2') WHERE a = 1;
|
||||
INSERT INTO t2 VALUES ();
|
||||
END|
|
||||
BEGIN;
|
||||
UPDATE t1 SET b = CONCAT(b, '+con1') WHERE a = 1;
|
||||
affected rows: 1
|
||||
info: Rows matched: 1 Changed: 1 Warnings: 0
|
||||
SELECT * FROM t1;
|
||||
a b
|
||||
1 init+con1
|
||||
# Switch to connection con2
|
||||
CALL p1;;
|
||||
# Switch to connection con1
|
||||
SELECT * FROM t1;
|
||||
a b
|
||||
1 init+con1
|
||||
COMMIT;
|
||||
SELECT * FROM t1;
|
||||
a b
|
||||
1 init+con1
|
||||
# Switch to connection con2
|
||||
SELECT * FROM t1;
|
||||
a b
|
||||
1 init+con1+con2
|
||||
# Switch to connection con1
|
||||
# 3. test for updated key column:
|
||||
TRUNCATE t1;
|
||||
TRUNCATE t2;
|
||||
INSERT INTO t1 VALUES (1,'init');
|
||||
BEGIN;
|
||||
UPDATE t1 SET a = 2, b = CONCAT(b, '+con1') WHERE a = 1;
|
||||
affected rows: 1
|
||||
info: Rows matched: 1 Changed: 1 Warnings: 0
|
||||
SELECT * FROM t1;
|
||||
a b
|
||||
2 init+con1
|
||||
# Switch to connection con2
|
||||
CALL p1;;
|
||||
# Switch to connection con1
|
||||
SELECT * FROM t1;
|
||||
a b
|
||||
2 init+con1
|
||||
COMMIT;
|
||||
SELECT * FROM t1;
|
||||
a b
|
||||
2 init+con1
|
||||
# Switch to connection con2
|
||||
SELECT * FROM t1;
|
||||
a b
|
||||
2 init+con1
|
||||
DROP PROCEDURE p1;
|
||||
DROP TABLE t1, t2;
|
||||
End of 5.1 tests
|
||||
|
|
|
@ -3145,6 +3145,8 @@ int handler::read_multi_range_next(KEY_MULTI_RANGE **found_range_p)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (was_semi_consistent_read())
|
||||
goto scan_it_again;
|
||||
/*
|
||||
We need to set this for the last range only, but checking this
|
||||
condition is more expensive than just setting the result code.
|
||||
|
@ -3152,10 +3154,10 @@ int handler::read_multi_range_next(KEY_MULTI_RANGE **found_range_p)
|
|||
result= HA_ERR_END_OF_FILE;
|
||||
}
|
||||
|
||||
multi_range_curr++;
|
||||
scan_it_again:
|
||||
/* Try the next range(s) until one matches a record. */
|
||||
for (multi_range_curr++;
|
||||
multi_range_curr < multi_range_end;
|
||||
multi_range_curr++)
|
||||
for (; multi_range_curr < multi_range_end; multi_range_curr++)
|
||||
{
|
||||
result= read_range_first(multi_range_curr->start_key.keypart_map ?
|
||||
&multi_range_curr->start_key : 0,
|
||||
|
|
Loading…
Reference in a new issue