mirror of
https://github.com/MariaDB/server.git
synced 2025-07-27 18:02:13 +03:00
MDEV-27962 Instant DDL downgrades the MDL when table is empty
- Server incorrectly downgrading the MDL after prepare phase when
table is empty. mdl_exclusive_after_prepare is being set in
prepare phase only. But mdl_exclusive_after_prepare condition was
misplaced and checked before prepare phase by
commit d270525dfd
and it is now
changed to check after prepare phase.
- main.innodb_mysql_sync test case was changed to avoid locking
optimization when table is empty.
This commit is contained in:
@ -131,6 +131,7 @@ connection default;
|
||||
DROP DATABASE db1;
|
||||
# Test 2: Primary index (implicit), should block writes.
|
||||
CREATE TABLE t1(a INT NOT NULL, b INT NOT NULL) engine=innodb;
|
||||
INSERT INTO t1 VALUES(1, 2);
|
||||
SET DEBUG_SYNC= "alter_table_inplace_after_lock_downgrade SIGNAL manage WAIT_FOR query";
|
||||
# Sending:
|
||||
ALTER TABLE t1 ADD UNIQUE INDEX(a), LOCK=SHARED;
|
||||
@ -139,15 +140,16 @@ SET DEBUG_SYNC= "now WAIT_FOR manage";
|
||||
USE test;
|
||||
SELECT * FROM t1;
|
||||
a b
|
||||
1 2
|
||||
# Sending:
|
||||
UPDATE t1 SET a=NULL;
|
||||
UPDATE t1 SET a=3;
|
||||
connection con2;
|
||||
# Waiting for SELECT to be blocked by the metadata lock on t1
|
||||
SET DEBUG_SYNC= "now SIGNAL query";
|
||||
connection default;
|
||||
# Reaping: ALTER TABLE t1 ADD UNIQUE INDEX(a)
|
||||
connection con1;
|
||||
# Reaping: UPDATE t1 SET a=NULL
|
||||
# Reaping: UPDATE t1 SET a=3
|
||||
# Test 3: Primary index (explicit), should block writes.
|
||||
connection default;
|
||||
ALTER TABLE t1 DROP INDEX a;
|
||||
@ -158,15 +160,16 @@ connection con1;
|
||||
SET DEBUG_SYNC= "now WAIT_FOR manage";
|
||||
SELECT * FROM t1;
|
||||
a b
|
||||
3 2
|
||||
# Sending:
|
||||
UPDATE t1 SET a=NULL;
|
||||
UPDATE t1 SET a=4;
|
||||
connection con2;
|
||||
# Waiting for SELECT to be blocked by the metadata lock on t1
|
||||
SET DEBUG_SYNC= "now SIGNAL query";
|
||||
connection default;
|
||||
# Reaping: ALTER TABLE t1 ADD PRIMARY KEY (a)
|
||||
connection con1;
|
||||
# Reaping: UPDATE t1 SET a=NULL
|
||||
# Reaping: UPDATE t1 SET a=4
|
||||
# Test 4: Secondary unique index, should not block reads.
|
||||
connection default;
|
||||
SET DEBUG_SYNC= "alter_table_inplace_after_lock_downgrade SIGNAL manage WAIT_FOR query";
|
||||
@ -176,6 +179,7 @@ connection con1;
|
||||
SET DEBUG_SYNC= "now WAIT_FOR manage";
|
||||
SELECT * FROM t1;
|
||||
a b
|
||||
4 2
|
||||
SET DEBUG_SYNC= "now SIGNAL query";
|
||||
connection default;
|
||||
# Reaping: ALTER TABLE t1 ADD UNIQUE (b)
|
||||
|
@ -176,6 +176,7 @@ DROP DATABASE db1;
|
||||
--echo # Test 2: Primary index (implicit), should block writes.
|
||||
|
||||
CREATE TABLE t1(a INT NOT NULL, b INT NOT NULL) engine=innodb;
|
||||
INSERT INTO t1 VALUES(1, 2);
|
||||
SET DEBUG_SYNC= "alter_table_inplace_after_lock_downgrade SIGNAL manage WAIT_FOR query";
|
||||
--echo # Sending:
|
||||
--send ALTER TABLE t1 ADD UNIQUE INDEX(a), LOCK=SHARED
|
||||
@ -185,13 +186,13 @@ SET DEBUG_SYNC= "now WAIT_FOR manage";
|
||||
USE test;
|
||||
SELECT * FROM t1;
|
||||
--echo # Sending:
|
||||
--send UPDATE t1 SET a=NULL
|
||||
--send UPDATE t1 SET a=3
|
||||
|
||||
connection con2;
|
||||
--echo # Waiting for SELECT to be blocked by the metadata lock on t1
|
||||
let $wait_condition= SELECT COUNT(*)= 1 FROM information_schema.processlist
|
||||
WHERE state= 'Waiting for table metadata lock'
|
||||
AND info='UPDATE t1 SET a=NULL';
|
||||
AND info='UPDATE t1 SET a=3';
|
||||
--source include/wait_condition.inc
|
||||
SET DEBUG_SYNC= "now SIGNAL query";
|
||||
|
||||
@ -200,7 +201,7 @@ connection default;
|
||||
--reap
|
||||
|
||||
connection con1;
|
||||
--echo # Reaping: UPDATE t1 SET a=NULL
|
||||
--echo # Reaping: UPDATE t1 SET a=3
|
||||
--reap
|
||||
|
||||
--echo # Test 3: Primary index (explicit), should block writes.
|
||||
@ -215,13 +216,13 @@ connection con1;
|
||||
SET DEBUG_SYNC= "now WAIT_FOR manage";
|
||||
SELECT * FROM t1;
|
||||
--echo # Sending:
|
||||
--send UPDATE t1 SET a=NULL
|
||||
--send UPDATE t1 SET a=4
|
||||
|
||||
connection con2;
|
||||
--echo # Waiting for SELECT to be blocked by the metadata lock on t1
|
||||
let $wait_condition= SELECT COUNT(*)= 1 FROM information_schema.processlist
|
||||
WHERE state= 'Waiting for table metadata lock'
|
||||
AND info='UPDATE t1 SET a=NULL';
|
||||
AND info='UPDATE t1 SET a=4';
|
||||
--source include/wait_condition.inc
|
||||
SET DEBUG_SYNC= "now SIGNAL query";
|
||||
|
||||
@ -230,7 +231,7 @@ connection default;
|
||||
--reap
|
||||
|
||||
connection con1;
|
||||
--echo # Reaping: UPDATE t1 SET a=NULL
|
||||
--echo # Reaping: UPDATE t1 SET a=4
|
||||
--reap
|
||||
|
||||
--echo # Test 4: Secondary unique index, should not block reads.
|
||||
|
@ -462,12 +462,27 @@ INSERT INTO t1 SET a=0, i=REPEAT('1', 10000);
|
||||
ROLLBACK;
|
||||
set DEBUG_SYNC='now SIGNAL go';
|
||||
connection default;
|
||||
disconnect con1;
|
||||
SELECT * FROM t1;
|
||||
a b c d e f g h i
|
||||
1 2 3 4 5 6 7 8 test
|
||||
DROP TABLE t1;
|
||||
SET DEBUG_SYNC=RESET;
|
||||
#
|
||||
# MDEV-27962 Instant DDL downgrades the MDL when table is empty
|
||||
#
|
||||
CREATE TABLE t1(f1 INT NOT NULL, f2 INT NOT NULL)ENGINE=InnoDB;
|
||||
SET DEBUG_SYNC="alter_table_inplace_after_lock_downgrade SIGNAL try_insert WAIT_FOR alter_progress";
|
||||
ALTER TABLE t1 ADD INDEX(f1), ADD INDEX(f2);
|
||||
connection con1;
|
||||
SET SESSION lock_wait_timeout=1;
|
||||
SET DEBUG_SYNC="now WAIT_FOR try_insert";
|
||||
INSERT INTO t1 VALUES(1, 2);
|
||||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
||||
SET DEBUG_SYNC="now SIGNAL alter_progress";
|
||||
disconnect con1;
|
||||
connection default;
|
||||
DROP TABLE t1;
|
||||
SET DEBUG_SYNC=reset;
|
||||
# End of 10.4 tests
|
||||
SET GLOBAL innodb_purge_rseg_truncate_frequency = @save_frequency;
|
||||
SELECT variable_value-@old_instant instants
|
||||
|
@ -533,11 +533,28 @@ set DEBUG_SYNC='now SIGNAL go';
|
||||
connection default;
|
||||
reap;
|
||||
|
||||
disconnect con1;
|
||||
SELECT * FROM t1;
|
||||
DROP TABLE t1;
|
||||
SET DEBUG_SYNC=RESET;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-27962 Instant DDL downgrades the MDL when table is empty
|
||||
--echo #
|
||||
CREATE TABLE t1(f1 INT NOT NULL, f2 INT NOT NULL)ENGINE=InnoDB;
|
||||
SET DEBUG_SYNC="alter_table_inplace_after_lock_downgrade SIGNAL try_insert WAIT_FOR alter_progress";
|
||||
send ALTER TABLE t1 ADD INDEX(f1), ADD INDEX(f2);
|
||||
connection con1;
|
||||
SET SESSION lock_wait_timeout=1;
|
||||
SET DEBUG_SYNC="now WAIT_FOR try_insert";
|
||||
--error ER_LOCK_WAIT_TIMEOUT
|
||||
INSERT INTO t1 VALUES(1, 2);
|
||||
SET DEBUG_SYNC="now SIGNAL alter_progress";
|
||||
disconnect con1;
|
||||
connection default;
|
||||
reap;
|
||||
DROP TABLE t1;
|
||||
SET DEBUG_SYNC=reset;
|
||||
|
||||
--echo # End of 10.4 tests
|
||||
|
||||
SET GLOBAL innodb_purge_rseg_truncate_frequency = @save_frequency;
|
||||
|
@ -7716,16 +7716,15 @@ static bool mysql_inplace_alter_table(THD *thd,
|
||||
lock for prepare phase under LOCK TABLES in the same way as when
|
||||
exclusive lock is required for duration of the whole statement.
|
||||
*/
|
||||
if (!ha_alter_info->mdl_exclusive_after_prepare &&
|
||||
(inplace_supported == HA_ALTER_INPLACE_EXCLUSIVE_LOCK ||
|
||||
((inplace_supported == HA_ALTER_INPLACE_COPY_NO_LOCK ||
|
||||
if (inplace_supported == HA_ALTER_INPLACE_EXCLUSIVE_LOCK ||
|
||||
((inplace_supported == HA_ALTER_INPLACE_COPY_NO_LOCK ||
|
||||
inplace_supported == HA_ALTER_INPLACE_COPY_LOCK ||
|
||||
inplace_supported == HA_ALTER_INPLACE_NOCOPY_NO_LOCK ||
|
||||
inplace_supported == HA_ALTER_INPLACE_NOCOPY_LOCK ||
|
||||
inplace_supported == HA_ALTER_INPLACE_INSTANT) &&
|
||||
(thd->locked_tables_mode == LTM_LOCK_TABLES ||
|
||||
thd->locked_tables_mode == LTM_PRELOCKED_UNDER_LOCK_TABLES)) ||
|
||||
alter_info->requested_lock == Alter_info::ALTER_TABLE_LOCK_EXCLUSIVE))
|
||||
alter_info->requested_lock == Alter_info::ALTER_TABLE_LOCK_EXCLUSIVE)
|
||||
{
|
||||
if (wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN))
|
||||
goto cleanup;
|
||||
@ -7822,7 +7821,8 @@ static bool mysql_inplace_alter_table(THD *thd,
|
||||
necessary only for prepare phase (unless we are not under LOCK TABLES) and
|
||||
user has not explicitly requested exclusive lock.
|
||||
*/
|
||||
if ((inplace_supported == HA_ALTER_INPLACE_COPY_NO_LOCK ||
|
||||
if (!ha_alter_info->mdl_exclusive_after_prepare &&
|
||||
(inplace_supported == HA_ALTER_INPLACE_COPY_NO_LOCK ||
|
||||
inplace_supported == HA_ALTER_INPLACE_COPY_LOCK ||
|
||||
inplace_supported == HA_ALTER_INPLACE_NOCOPY_LOCK ||
|
||||
inplace_supported == HA_ALTER_INPLACE_NOCOPY_NO_LOCK) &&
|
||||
|
Reference in New Issue
Block a user