mirror of
https://github.com/MariaDB/server.git
synced 2025-08-31 22:22:30 +03:00
MDEV-11168: InnoDB: Failing assertion: !other_lock || wsrep_thd_is_BF(lock->trx->mysql_thd, FALSE) || wsrep_thd_is_BF(other_lock->trx->mysql_thd, FALSE)
Merged pull request: Fix error in lock_has_higher_priority #266 https://github.com/MariaDB/server/pull/266 Added test case.
This commit is contained in:
@@ -0,0 +1,89 @@
|
|||||||
|
CREATE TABLE t1 (i1 INT) ENGINE=InnoDB;
|
||||||
|
INSERT INTO t1 VALUES (1),(2);
|
||||||
|
CREATE TABLE t2 (i2 int) ENGINE=MyISAM;
|
||||||
|
BEGIN;
|
||||||
|
DELETE FROM t1;
|
||||||
|
BEGIN;
|
||||||
|
INSERT INTO t2 VALUES (1),(2);
|
||||||
|
SELECT * from t1;
|
||||||
|
i1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
UPDATE t1 SET i1 = 1;
|
||||||
|
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
||||||
|
COMMIT;
|
||||||
|
COMMIT;
|
||||||
|
SELECT * FROM t1;
|
||||||
|
i1
|
||||||
|
SELECT * FROM t2;
|
||||||
|
i2
|
||||||
|
1
|
||||||
|
2
|
||||||
|
DROP TABLE t1, t2;
|
||||||
|
CREATE TABLE t1 (i1 INT) ENGINE=InnoDB;
|
||||||
|
INSERT INTO t1 VALUES (1),(2);
|
||||||
|
CREATE TABLE t2 (i2 int) ENGINE=MyISAM;
|
||||||
|
BEGIN;
|
||||||
|
DELETE FROM t1;
|
||||||
|
BEGIN;
|
||||||
|
INSERT INTO t2 VALUES (1),(2);
|
||||||
|
SELECT * FROM t1;
|
||||||
|
i1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
UPDATE t1 SET i1 = 1;
|
||||||
|
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
||||||
|
COMMIT;
|
||||||
|
COMMIT;
|
||||||
|
SELECT * FROM t1;
|
||||||
|
i1
|
||||||
|
SELECT * FROM t2;
|
||||||
|
i2
|
||||||
|
1
|
||||||
|
2
|
||||||
|
DROP TABLE t1, t2;
|
||||||
|
# "restart: --loose-innodb-lock-schedule-algorithm=FCFS"
|
||||||
|
CREATE TABLE t1 (i1 INT) ENGINE=InnoDB;
|
||||||
|
INSERT INTO t1 VALUES (1),(2);
|
||||||
|
CREATE TABLE t2 (i2 int) ENGINE=MyISAM;
|
||||||
|
BEGIN;
|
||||||
|
DELETE FROM t1;
|
||||||
|
BEGIN;
|
||||||
|
INSERT INTO t2 VALUES (1),(2);
|
||||||
|
SELECT * from t1;
|
||||||
|
i1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
UPDATE t1 SET i1 = 1;
|
||||||
|
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
||||||
|
COMMIT;
|
||||||
|
COMMIT;
|
||||||
|
SELECT * FROM t1;
|
||||||
|
i1
|
||||||
|
SELECT * FROM t2;
|
||||||
|
i2
|
||||||
|
1
|
||||||
|
2
|
||||||
|
DROP TABLE t1, t2;
|
||||||
|
CREATE TABLE t1 (i1 INT) ENGINE=InnoDB;
|
||||||
|
INSERT INTO t1 VALUES (1),(2);
|
||||||
|
CREATE TABLE t2 (i2 int) ENGINE=MyISAM;
|
||||||
|
BEGIN;
|
||||||
|
DELETE FROM t1;
|
||||||
|
BEGIN;
|
||||||
|
INSERT INTO t2 VALUES (1),(2);
|
||||||
|
SELECT * FROM t1;
|
||||||
|
i1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
UPDATE t1 SET i1 = 1;
|
||||||
|
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
||||||
|
COMMIT;
|
||||||
|
COMMIT;
|
||||||
|
SELECT * FROM t1;
|
||||||
|
i1
|
||||||
|
SELECT * FROM t2;
|
||||||
|
i2
|
||||||
|
1
|
||||||
|
2
|
||||||
|
DROP TABLE t1, t2;
|
@@ -0,0 +1,2 @@
|
|||||||
|
--loose-innodb-lock-wait-timeout=1
|
||||||
|
--loose-innodb-lock-schedule-algorithm=VATS
|
106
mysql-test/suite/innodb/t/innodb-lock-schedule-algorithm.test
Normal file
106
mysql-test/suite/innodb/t/innodb-lock-schedule-algorithm.test
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
--source include/have_innodb.inc
|
||||||
|
|
||||||
|
CREATE TABLE t1 (i1 INT) ENGINE=InnoDB;
|
||||||
|
INSERT INTO t1 VALUES (1),(2);
|
||||||
|
|
||||||
|
CREATE TABLE t2 (i2 int) ENGINE=MyISAM;
|
||||||
|
BEGIN;
|
||||||
|
DELETE FROM t1;
|
||||||
|
|
||||||
|
--connect (con1,localhost,root,,test)
|
||||||
|
connection con1;
|
||||||
|
BEGIN;
|
||||||
|
INSERT INTO t2 VALUES (1),(2);
|
||||||
|
SELECT * from t1;
|
||||||
|
--error 1205
|
||||||
|
UPDATE t1 SET i1 = 1;
|
||||||
|
COMMIT;
|
||||||
|
|
||||||
|
connection default;
|
||||||
|
COMMIT;
|
||||||
|
SELECT * FROM t1;
|
||||||
|
SELECT * FROM t2;
|
||||||
|
DROP TABLE t1, t2;
|
||||||
|
disconnect con1;
|
||||||
|
|
||||||
|
CREATE TABLE t1 (i1 INT) ENGINE=InnoDB;
|
||||||
|
INSERT INTO t1 VALUES (1),(2);
|
||||||
|
|
||||||
|
CREATE TABLE t2 (i2 int) ENGINE=MyISAM;
|
||||||
|
BEGIN;
|
||||||
|
DELETE FROM t1;
|
||||||
|
|
||||||
|
--connect (con1,localhost,root,,test)
|
||||||
|
connection con1;
|
||||||
|
BEGIN;
|
||||||
|
INSERT INTO t2 VALUES (1),(2);
|
||||||
|
SELECT * FROM t1;
|
||||||
|
--error 1205
|
||||||
|
UPDATE t1 SET i1 = 1;
|
||||||
|
|
||||||
|
connection default;
|
||||||
|
COMMIT;
|
||||||
|
|
||||||
|
connection con1;
|
||||||
|
COMMIT;
|
||||||
|
|
||||||
|
connection default;
|
||||||
|
SELECT * FROM t1;
|
||||||
|
SELECT * FROM t2;
|
||||||
|
DROP TABLE t1, t2;
|
||||||
|
disconnect con1;
|
||||||
|
|
||||||
|
--echo # "restart: --loose-innodb-lock-schedule-algorithm=FCFS"
|
||||||
|
--let $restart_parameters=--loose_innodb_lock_schedule_algorithm=FCFS
|
||||||
|
-- source include/restart_mysqld.inc
|
||||||
|
|
||||||
|
CREATE TABLE t1 (i1 INT) ENGINE=InnoDB;
|
||||||
|
INSERT INTO t1 VALUES (1),(2);
|
||||||
|
|
||||||
|
CREATE TABLE t2 (i2 int) ENGINE=MyISAM;
|
||||||
|
BEGIN;
|
||||||
|
DELETE FROM t1;
|
||||||
|
|
||||||
|
--connect (con1,localhost,root,,test)
|
||||||
|
connection con1;
|
||||||
|
BEGIN;
|
||||||
|
INSERT INTO t2 VALUES (1),(2);
|
||||||
|
SELECT * from t1;
|
||||||
|
--error 1205
|
||||||
|
UPDATE t1 SET i1 = 1;
|
||||||
|
COMMIT;
|
||||||
|
|
||||||
|
connection default;
|
||||||
|
COMMIT;
|
||||||
|
SELECT * FROM t1;
|
||||||
|
SELECT * FROM t2;
|
||||||
|
DROP TABLE t1, t2;
|
||||||
|
disconnect con1;
|
||||||
|
|
||||||
|
CREATE TABLE t1 (i1 INT) ENGINE=InnoDB;
|
||||||
|
INSERT INTO t1 VALUES (1),(2);
|
||||||
|
|
||||||
|
CREATE TABLE t2 (i2 int) ENGINE=MyISAM;
|
||||||
|
BEGIN;
|
||||||
|
DELETE FROM t1;
|
||||||
|
|
||||||
|
--connect (con1,localhost,root,,test)
|
||||||
|
connection con1;
|
||||||
|
BEGIN;
|
||||||
|
INSERT INTO t2 VALUES (1),(2);
|
||||||
|
SELECT * FROM t1;
|
||||||
|
--error 1205
|
||||||
|
UPDATE t1 SET i1 = 1;
|
||||||
|
|
||||||
|
connection default;
|
||||||
|
COMMIT;
|
||||||
|
|
||||||
|
connection con1;
|
||||||
|
COMMIT;
|
||||||
|
|
||||||
|
connection default;
|
||||||
|
SELECT * FROM t1;
|
||||||
|
SELECT * FROM t2;
|
||||||
|
DROP TABLE t1, t2;
|
||||||
|
disconnect con1;
|
||||||
|
|
@@ -2267,8 +2267,6 @@ lock_rec_create(
|
|||||||
/*********************************************************************//**
|
/*********************************************************************//**
|
||||||
Check if lock1 has higher priority than lock2.
|
Check if lock1 has higher priority than lock2.
|
||||||
NULL has lowest priority.
|
NULL has lowest priority.
|
||||||
Respect the preference of the upper server layer to reduce conflict
|
|
||||||
during in-order parallel replication.
|
|
||||||
If neither of them is wait lock, the first one has higher priority.
|
If neither of them is wait lock, the first one has higher priority.
|
||||||
If only one of them is a wait lock, it has lower priority.
|
If only one of them is a wait lock, it has lower priority.
|
||||||
Otherwise, the one with an older transaction has higher priority.
|
Otherwise, the one with an older transaction has higher priority.
|
||||||
@@ -2282,22 +2280,13 @@ has_higher_priority(
|
|||||||
return false;
|
return false;
|
||||||
} else if (lock2 == NULL) {
|
} else if (lock2 == NULL) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// Ask the upper server layer if any of the two trx should be prefered.
|
// No preference. Compre them by wait mode and trx age.
|
||||||
int preference = thd_deadlock_victim_preference(lock1->trx->mysql_thd, lock2->trx->mysql_thd);
|
if (!lock_get_wait(lock1)) {
|
||||||
if (preference == -1) {
|
return true;
|
||||||
// lock1 is preferred as a victim, so lock2 has higher priority
|
} else if (!lock_get_wait(lock2)) {
|
||||||
return false;
|
return false;
|
||||||
} else if (preference == 1) {
|
}
|
||||||
// lock2 is preferred as a victim, so lock1 has higher priority
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// No preference. Compre them by wait mode and trx age.
|
|
||||||
if (!lock_get_wait(lock1)) {
|
|
||||||
return true;
|
|
||||||
} else if (!lock_get_wait(lock2)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return lock1->trx->start_time_micro <= lock2->trx->start_time_micro;
|
return lock1->trx->start_time_micro <= lock2->trx->start_time_micro;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6652,7 +6641,6 @@ lock_rec_queue_validate(
|
|||||||
|
|
||||||
if (!lock_rec_get_gap(lock) && !lock_get_wait(lock)) {
|
if (!lock_rec_get_gap(lock) && !lock_get_wait(lock)) {
|
||||||
|
|
||||||
#ifndef WITH_WSREP
|
|
||||||
enum lock_mode mode;
|
enum lock_mode mode;
|
||||||
|
|
||||||
if (lock_get_mode(lock) == LOCK_S) {
|
if (lock_get_mode(lock) == LOCK_S) {
|
||||||
@@ -6660,10 +6648,21 @@ lock_rec_queue_validate(
|
|||||||
} else {
|
} else {
|
||||||
mode = LOCK_S;
|
mode = LOCK_S;
|
||||||
}
|
}
|
||||||
ut_a(!lock_rec_other_has_expl_req(
|
|
||||||
mode, 0, 0, block, heap_no, lock->trx));
|
const lock_t* other_lock
|
||||||
|
= lock_rec_other_has_expl_req(
|
||||||
|
mode, 0, 0, block, heap_no,
|
||||||
|
lock->trx);
|
||||||
|
#ifdef WITH_WSREP
|
||||||
|
ut_a(!other_lock
|
||||||
|
|| wsrep_thd_is_BF(lock->trx->mysql_thd, FALSE)
|
||||||
|
|| wsrep_thd_is_BF(other_lock->trx->mysql_thd, FALSE));
|
||||||
|
|
||||||
|
#else
|
||||||
|
ut_a(!other_lock);
|
||||||
#endif /* WITH_WSREP */
|
#endif /* WITH_WSREP */
|
||||||
|
|
||||||
|
|
||||||
} else if (lock_get_wait(lock) && !lock_rec_get_gap(lock)
|
} else if (lock_get_wait(lock) && !lock_rec_get_gap(lock)
|
||||||
&& innodb_lock_schedule_algorithm == INNODB_LOCK_SCHEDULE_ALGORITHM_FCFS) {
|
&& innodb_lock_schedule_algorithm == INNODB_LOCK_SCHEDULE_ALGORITHM_FCFS) {
|
||||||
// If using VATS, it's possible that a wait lock is inserted to a place in the list
|
// If using VATS, it's possible that a wait lock is inserted to a place in the list
|
||||||
|
@@ -2057,8 +2057,6 @@ wsrep_print_wait_locks(
|
|||||||
/*********************************************************************//**
|
/*********************************************************************//**
|
||||||
Check if lock1 has higher priority than lock2.
|
Check if lock1 has higher priority than lock2.
|
||||||
NULL has lowest priority.
|
NULL has lowest priority.
|
||||||
Respect the preference of the upper server layer to reduce conflict
|
|
||||||
during in-order parallel replication.
|
|
||||||
If neither of them is wait lock, the first one has higher priority.
|
If neither of them is wait lock, the first one has higher priority.
|
||||||
If only one of them is a wait lock, it has lower priority.
|
If only one of them is a wait lock, it has lower priority.
|
||||||
Otherwise, the one with an older transaction has higher priority.
|
Otherwise, the one with an older transaction has higher priority.
|
||||||
@@ -2073,15 +2071,6 @@ has_higher_priority(
|
|||||||
} else if (lock2 == NULL) {
|
} else if (lock2 == NULL) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// Ask the upper server layer if any of the two trx should be prefered.
|
|
||||||
int preference = thd_deadlock_victim_preference(lock1->trx->mysql_thd, lock2->trx->mysql_thd);
|
|
||||||
if (preference == -1) {
|
|
||||||
// lock1 is preferred as a victim, so lock2 has higher priority
|
|
||||||
return false;
|
|
||||||
} else if (preference == 1) {
|
|
||||||
// lock2 is preferred as a victim, so lock1 has higher priority
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// No preference. Compre them by wait mode and trx age.
|
// No preference. Compre them by wait mode and trx age.
|
||||||
if (!lock_get_wait(lock1)) {
|
if (!lock_get_wait(lock1)) {
|
||||||
return true;
|
return true;
|
||||||
@@ -6713,7 +6702,6 @@ lock_rec_queue_validate(
|
|||||||
|
|
||||||
if (!lock_rec_get_gap(lock) && !lock_get_wait(lock)) {
|
if (!lock_rec_get_gap(lock) && !lock_get_wait(lock)) {
|
||||||
|
|
||||||
#ifndef WITH_WSREP
|
|
||||||
enum lock_mode mode;
|
enum lock_mode mode;
|
||||||
|
|
||||||
|
|
||||||
@@ -6722,8 +6710,18 @@ lock_rec_queue_validate(
|
|||||||
} else {
|
} else {
|
||||||
mode = LOCK_S;
|
mode = LOCK_S;
|
||||||
}
|
}
|
||||||
ut_a(!lock_rec_other_has_expl_req(
|
|
||||||
mode, 0, 0, block, heap_no, lock->trx->id));
|
const lock_t* other_lock
|
||||||
|
= lock_rec_other_has_expl_req(
|
||||||
|
mode, 0, 0, block, heap_no,
|
||||||
|
lock->trx->id);
|
||||||
|
#ifdef WITH_WSREP
|
||||||
|
ut_a(!other_lock
|
||||||
|
|| wsrep_thd_is_BF(lock->trx->mysql_thd, FALSE)
|
||||||
|
|| wsrep_thd_is_BF(other_lock->trx->mysql_thd, FALSE));
|
||||||
|
|
||||||
|
#else
|
||||||
|
ut_a(!other_lock);
|
||||||
#endif /* WITH_WSREP */
|
#endif /* WITH_WSREP */
|
||||||
|
|
||||||
} else if (lock_get_wait(lock) && !lock_rec_get_gap(lock)
|
} else if (lock_get_wait(lock) && !lock_rec_get_gap(lock)
|
||||||
|
Reference in New Issue
Block a user