mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
MDEV-28930 ALTER TABLE Deadlocks with parallel TL_WRITE
ALTER ONLINE TABLE acquires table with TL_READ. Myisam normally acquires TL_WRITE for DML, which makes it hang until table is freed. We deadlock once ALTER upgrades its MDL lock. Solution: Unlock table earlier. We don't need to hold TL_READ once we finished copying. Relay log replication requires no data locks on `from` table.
This commit is contained in:
committed by
Sergei Golubchik
parent
8fbdc76038
commit
2ed03a41e6
@ -579,6 +579,27 @@ drop table t1;
|
||||
drop table t2;
|
||||
drop table t3;
|
||||
#
|
||||
# MDEV-28930 ALTER TABLE Deadlocks with parallel TL_WRITE
|
||||
#
|
||||
create table t1(a int) engine=myisam select 1;
|
||||
set debug_sync='alter_table_online_before_lock SIGNAL ready WAIT_FOR go_for_locking';
|
||||
alter table t1 force;
|
||||
connection con2;
|
||||
set debug_sync='now WAIT_FOR ready';
|
||||
set debug_sync='thr_multi_lock_before_thr_lock SIGNAL go_for_locking';
|
||||
update t1 set a=2;
|
||||
connection default;
|
||||
set debug_sync='alter_table_online_before_lock SIGNAL ready WAIT_FOR go_for_locking';
|
||||
alter table mysql.global_priv force;
|
||||
connection con2;
|
||||
set debug_sync='now WAIT_FOR ready';
|
||||
set debug_sync='thr_multi_lock_before_thr_lock SIGNAL go_for_locking';
|
||||
create user user1@localhost;
|
||||
connection default;
|
||||
set debug_sync=reset;
|
||||
drop user user1@localhost;
|
||||
drop table t1;
|
||||
#
|
||||
# MDEV-28959 Online alter ignores strict table mode
|
||||
#
|
||||
create table t1 (a int);
|
||||
|
@ -717,6 +717,39 @@ drop table t1;
|
||||
drop table t2;
|
||||
drop table t3;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-28930 ALTER TABLE Deadlocks with parallel TL_WRITE
|
||||
--echo #
|
||||
create table t1(a int) engine=myisam select 1;
|
||||
|
||||
set debug_sync='alter_table_online_before_lock SIGNAL ready WAIT_FOR go_for_locking';
|
||||
--send
|
||||
alter table t1 force;
|
||||
|
||||
--connection con2
|
||||
set debug_sync='now WAIT_FOR ready';
|
||||
set debug_sync='thr_multi_lock_before_thr_lock SIGNAL go_for_locking';
|
||||
update t1 set a=2;
|
||||
|
||||
--connection default
|
||||
--reap
|
||||
|
||||
set debug_sync='alter_table_online_before_lock SIGNAL ready WAIT_FOR go_for_locking';
|
||||
--send
|
||||
alter table mysql.global_priv force;
|
||||
|
||||
--connection con2
|
||||
set debug_sync='now WAIT_FOR ready';
|
||||
set debug_sync='thr_multi_lock_before_thr_lock SIGNAL go_for_locking';
|
||||
create user user1@localhost;
|
||||
|
||||
--connection default
|
||||
--reap
|
||||
|
||||
set debug_sync=reset;
|
||||
drop user user1@localhost;
|
||||
drop table t1;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-28959 Online alter ignores strict table mode
|
||||
--echo #
|
||||
|
@ -75,17 +75,15 @@ stage/sql/table lock NULL NULL
|
||||
stage/sql/After create NULL NULL
|
||||
stage/sql/copy to tmp table 5 5
|
||||
stage/sql/Enabling keys NULL NULL
|
||||
stage/sql/Unlocking tables NULL NULL
|
||||
stage/sql/Enabling keys NULL NULL
|
||||
stage/sql/Apply log event NULL NULL
|
||||
stage/sql/After apply log event NULL NULL
|
||||
stage/sql/Rename result table NULL NULL
|
||||
stage/sql/Unlocking tables NULL NULL
|
||||
stage/sql/Rename result table NULL NULL
|
||||
stage/sql/End of update loop NULL NULL
|
||||
stage/sql/Query end NULL NULL
|
||||
stage/sql/Commit NULL NULL
|
||||
stage/sql/closing tables NULL NULL
|
||||
stage/sql/Unlocking tables NULL NULL
|
||||
stage/sql/closing tables NULL NULL
|
||||
stage/sql/Commit implicit NULL NULL
|
||||
stage/sql/Starting cleanup NULL NULL
|
||||
stage/sql/Freeing items NULL NULL
|
||||
|
@ -4781,12 +4781,11 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi)
|
||||
thd->set_query_timer();
|
||||
|
||||
/*
|
||||
If there is no locks taken, this is the first binrow event seen
|
||||
after the table map events. We should then lock all the tables
|
||||
used in the transaction and proceed with execution of the actual
|
||||
event.
|
||||
If there are no tables open, this must be the first row event seen
|
||||
after the table map events. We should then open and lock all tables
|
||||
used in the transaction and proceed with execution of the actual event.
|
||||
*/
|
||||
if (!thd->lock)
|
||||
if (!thd->open_tables)
|
||||
{
|
||||
/*
|
||||
Lock_tables() reads the contents of thd->lex, so they must be
|
||||
|
@ -11998,6 +11998,11 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
|
||||
// We restore bitmaps, because update event is going to mess up with them.
|
||||
to->default_column_bitmaps();
|
||||
|
||||
end_read_record(&info);
|
||||
init_read_record_done= false;
|
||||
mysql_unlock_tables(thd, thd->lock);
|
||||
thd->lock= NULL;
|
||||
|
||||
error= online_alter_read_from_binlog(thd, &rgi, binlog);
|
||||
|
||||
DEBUG_SYNC(thd, "alter_table_online_before_lock");
|
||||
|
Reference in New Issue
Block a user