-
Notifications
You must be signed in to change notification settings - Fork 713
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adding high_priority syntax in DDL commands
Summary: This diff introduces `HIGH_PRIORITY` syntax in some DDL commands and optimize command. The purpose is the same as the system variable `high_priority_ddl` which is described in D4784076. The list of commands that support `HIGH_PRIORITY` syntax is: - create/drop/alter/truncate table - create/drop index - create/drop trigger - optimize table With this diff, there are two ways of issuing high priority DDLs: e.g. `CREATE HIGH_PRIORITY INDEX ...` Recap of the high_priority ddl feature: - Only the shared locks (read/write) will be affected, which are DML queries such as select, insert, update, etc. Any lock higher than upgradable MDL (i.e. from conflicting DDL) will not be affected. - When killing the blocking connections, their transactions will automatically be rolled back. This is the same behavior as `kill processlist_id` command. - The DDL will kill blocking connections at the end of the timeout instead of instantly. Admin can control the waiting period by setting the session lock_wait_timeout before issuing the DDL. Reviewed By: abhinav04sharma Differential Revision: D5635549 fbshipit-source-id: e51ed02
- Loading branch information
1 parent
87784d3
commit 397fa65
Showing
16 changed files
with
2,456 additions
and
257 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,174 @@ | ||
############################################################################### | ||
# Common test file for high priority DDL | ||
############################################################################### | ||
|
||
|
||
create user test_user1@localhost; | ||
grant all on test to test_user1@localhost; | ||
create user test_user2@localhost; | ||
grant all on test to test_user2@localhost; | ||
|
||
# Default values | ||
--let $con_block = con1 | ||
--let $con_kill = default | ||
--let $should_kill = 1 | ||
--let $recreate_table = 1 | ||
--let $throw_error = 1 | ||
|
||
## | ||
## killing conflicting shared locks by alter table | ||
## | ||
|
||
--let $blocking_sql = lock tables t1 read; | ||
--let $cmd = alter table t1 modify i bigint; | ||
--let $high_priority_cmd = alter high_priority table t1 modify i bigint; | ||
|
||
--source include/ddl_high_priority_module.inc | ||
|
||
## | ||
## killing conflicting shared lock in a transaction | ||
## transaction will rollback | ||
## | ||
|
||
--let $blocking_sql = begin; insert into t1 values (4); select i from t1; | ||
--let $cmd = alter table t1 rename t1_new; | ||
--let $high_priority_cmd = alter high_priority table t1 rename t1_new; | ||
|
||
--source include/ddl_high_priority_module.inc | ||
|
||
select * from t1_new; | ||
drop table t1_new; | ||
|
||
## | ||
## simulate conflicting DDL which will not be killed | ||
## | ||
|
||
# Simulate conflicting DDL | ||
# This will hold MDL_SHARED_NO_READ_WRITE, which may be upgraded to exclusive | ||
# locks to run DDLs like ALTER TABLE | ||
# the upgradable/exclusive lock should not be killed | ||
|
||
--let $should_kill = 0 | ||
|
||
--let $blocking_sql = lock tables t1 write; | ||
--let $cmd = drop table t1; | ||
--let $high_priority_cmd = drop high_priority table t1; | ||
|
||
--source include/ddl_high_priority_module.inc | ||
|
||
# restore $should_kill | ||
--let $should_kill = 1 | ||
|
||
## | ||
## killing conflicting transaction by drop table DDL | ||
## | ||
|
||
--let $blocking_sql = lock tables t1 read; begin; insert into t1 values (4); | ||
--let $cmd = drop table t1; | ||
--let $high_priority_cmd = drop high_priority table t1; | ||
|
||
--source include/ddl_high_priority_module.inc | ||
|
||
## | ||
## no effect for regular users | ||
## | ||
|
||
connect (con2,localhost,test_user2,,test,,); | ||
# $con_kill is regular user | ||
--let $con_kill = con2 | ||
--let $should_kill = 0 | ||
|
||
--let $blocking_sql = lock tables t1 read; | ||
--let $cmd = alter table t1 modify i bigint; | ||
--let $high_priority_cmd = alter high_priority table t1 modify i bigint; | ||
|
||
--source include/ddl_high_priority_module.inc | ||
|
||
disconnect con2; | ||
|
||
# restore $con_kill | ||
--let $con_kill = default | ||
# restore $should_kill | ||
--let $should_kill = 1 | ||
|
||
## | ||
## create/drop index | ||
## | ||
|
||
# create index | ||
|
||
--let $blocking_sql = lock tables t1 read; | ||
--let $cmd = create index idx1 on t1 (i); | ||
--let $high_priority_cmd = create high_priority index idx1 on t1 (i); | ||
|
||
--source include/ddl_high_priority_module.inc | ||
|
||
# drop index (use the previously created table) | ||
--let $recreate_table = 0 | ||
|
||
--let $cmd = drop index idx1 on t1; | ||
--let $high_priority_cmd = drop high_priority index idx1 on t1; | ||
|
||
--source include/ddl_high_priority_module.inc | ||
|
||
# restore $recreate_table | ||
--let $recreate_table = 1 | ||
|
||
## | ||
## high_priority truncate table | ||
## | ||
|
||
--let $blocking_sql = lock tables t1 read; | ||
--let $cmd = truncate t1; | ||
--let $high_priority_cmd = truncate high_priority t1; | ||
|
||
--source include/ddl_high_priority_module.inc | ||
|
||
## | ||
## high_priority create/drop trigger | ||
## | ||
|
||
--let $blocking_sql = lock tables t1 read; | ||
--let $cmd = create trigger ins_sum before insert on t1 for each row set @sum = @sum + new.i; | ||
--let $high_priority_cmd = create high_priority trigger ins_sum before insert on t1 for each row set @sum = @sum + new.i; | ||
|
||
--source include/ddl_high_priority_module.inc | ||
|
||
# drop trigger (use the previously created table) | ||
--let $recreate_table = 0 | ||
|
||
--let $cmd = drop trigger ins_sum; | ||
--let $high_priority_cmd = drop high_priority trigger ins_sum; | ||
|
||
--source include/ddl_high_priority_module.inc | ||
|
||
# restore $recreate_table | ||
--let $recreate_table = 1 | ||
|
||
## | ||
## high_priority optimize table | ||
## | ||
## "optimize table" doesn't throw errors. It catches all errors, and | ||
## returns a result set in a table | ||
## | ||
|
||
--let $throw_error = 0 | ||
|
||
--let $blocking_sql = lock tables t1 read; | ||
--let $cmd = optimize table t1; | ||
--let $high_priority_cmd = optimize high_priority table t1; | ||
|
||
--source include/ddl_high_priority_module.inc | ||
|
||
# restore throw_error | ||
--let $throw_error = 1 | ||
|
||
## | ||
## clean up | ||
## | ||
|
||
drop user test_user1@localhost; | ||
drop user test_user2@localhost; | ||
--disable_warnings | ||
drop table if exists t1; | ||
--enable_warnings |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
############################################################################### | ||
# This file plays as a function/module for ddl_high_priority test | ||
# | ||
# Usage: set the following variables before including | ||
# | ||
# $use_sys_var: whether using sys_var or syntax to trigger high_priority | ||
# value: 0/1 | ||
# | ||
# $con_block: a blocking connection | ||
# value: con1/con2/default | ||
# | ||
# $con_kill: a connection that will attempt to kill $con_blocking | ||
# value: con1/con2/default | ||
# | ||
# $cmd: a regular command to evaluate (to use with sys var) | ||
# value: sql command | ||
# | ||
# $high_priority_cmd: a high_priority command to evaluate | ||
# value: sql command | ||
# | ||
# $should_kill: Expect the con_block to be killed or not | ||
# value: 0/1 | ||
# | ||
# $recreate_table: Should recreate the test table or not | ||
# value: 0/1 | ||
# | ||
# $throw_error: whether a command will throw lock_wait_timeout error. | ||
# Note, optimize table catches all errors. | ||
# value: 0/1 | ||
############################################################################### | ||
|
||
## | ||
## Print out the parameters of the test set | ||
## (useful for debugging) | ||
## | ||
--echo | ||
--echo ## Test parameters: | ||
--echo ## use_sys_var = $use_sys_var | ||
--echo ## con_block = $con_block | ||
--echo ## con_kill = $con_kill | ||
--echo ## cmd = $cmd | ||
--echo ## high_priority_cmd = $high_priority_cmd | ||
--echo ## should_kill = $should_kill | ||
--echo ## recreate_table = $recreate_table | ||
--echo ## throw_error = $throw_error | ||
--echo | ||
|
||
|
||
## | ||
## Setup | ||
## | ||
|
||
connection default; | ||
|
||
# create con1 | ||
connect (con1,localhost,test_user1,,test,,); | ||
|
||
if ($recreate_table) { | ||
# create t1 | ||
--disable_warnings | ||
drop table if exists t1; | ||
--enable_warnings | ||
create table t1 (i int); | ||
show create table t1; | ||
insert into t1 values (1), (2), (3); | ||
} | ||
|
||
## | ||
## Testing | ||
## | ||
|
||
--echo connection: $con_block | ||
--connection $con_block | ||
--eval $blocking_sql | ||
|
||
--echo connection: $con_kill | ||
--connection $con_kill | ||
set lock_wait_timeout = 0.02; | ||
|
||
describe t1; | ||
|
||
--echo connection: default (for show processlist) | ||
connection default; | ||
--echo # both $con_block and $con_kill exist | ||
--replace_column 1 <Id> 3 <Host> 5 <Command> 6 <Time> 7 <State> 8 <Info> 9 <RExam> 10 <RSent> 11 <TID> | ||
show processlist; | ||
|
||
--echo connection: $con_kill | ||
--connection $con_kill | ||
|
||
# command will fail without high_priority | ||
if ($throw_error) { | ||
--error ER_LOCK_WAIT_TIMEOUT | ||
--eval $cmd | ||
} | ||
|
||
if (!$throw_error) { | ||
--eval $cmd | ||
} | ||
|
||
if ($use_sys_var) { | ||
set high_priority_ddl = 1; | ||
select @@high_priority_ddl; | ||
|
||
# non-supported command will timeout | ||
--error ER_LOCK_WAIT_TIMEOUT | ||
lock tables t1 write; | ||
|
||
if (!$should_kill) { | ||
# regular user ddl will fail regardless of high_priority_ddl being on | ||
--error ER_LOCK_WAIT_TIMEOUT | ||
--eval $cmd | ||
} | ||
|
||
if ($should_kill) { | ||
--eval $cmd | ||
} | ||
|
||
# reset high_priority_ddl | ||
set high_priority_ddl = 0; | ||
} | ||
|
||
if (!$use_sys_var) { | ||
if (!$should_kill) { | ||
# regular user ddl will fail regardless of high_priority being on | ||
--error ER_LOCK_WAIT_TIMEOUT | ||
--eval $high_priority_cmd | ||
} | ||
|
||
if ($should_kill) { | ||
--eval $high_priority_cmd | ||
} | ||
} | ||
|
||
--echo connection: default (for show processlist) | ||
connection default; | ||
--replace_column 1 <Id> 3 <Host> 5 <Command> 6 <Time> 7 <State> 8 <Info> 9 <RExam> 10 <RSent> 11 <TID> | ||
show processlist; | ||
|
||
disconnect con1; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
############################################################################### | ||
# Test replication of the high_priority syntax | ||
############################################################################### | ||
|
||
|
||
--source include/master-slave.inc | ||
|
||
--let $rpl_connection_name= slave_block | ||
--let $rpl_server_number= 2 | ||
--source include/rpl_connect.inc | ||
|
||
connection master; | ||
|
||
# create t1 | ||
--disable_warnings | ||
drop table if exists t1; | ||
--enable_warnings | ||
create table t1 (i int); | ||
show create table t1; | ||
insert into t1 values (1), (2), (3); | ||
|
||
sync_slave_with_master; | ||
|
||
--echo connection slave | ||
connection slave; | ||
select * from t1; | ||
|
||
let $sql_thread=`select id from information_schema.processlist where state | ||
like 'Slave has read all relay log; waiting for the slave I/O thread%'`; | ||
let $worker_thread=`select id from information_schema.processlist where state | ||
like 'Waiting for%'`; | ||
|
||
--echo # set slave thread's lock_wait_timeout to a small value | ||
|
||
--replace_regex /session [0-9]*/session sql_thread/ | ||
--eval set session $sql_thread lock_wait_timeout = 0.2 | ||
|
||
--replace_regex /session [0-9]*/session sql_thread/ | ||
--eval show session $sql_thread variables like 'lock_wait_timeout' | ||
|
||
--echo connection slave_block | ||
connection slave_block; | ||
|
||
# issue a bloking read from slave_block connection | ||
lock tables t1 read; | ||
|
||
--echo connection master; | ||
connection master; | ||
|
||
# issue a high_pri command from master | ||
create high_priority index idx1 on t1 (i); | ||
show create table t1; | ||
|
||
# sync | ||
sync_slave_with_master; | ||
|
||
--echo connection slave; | ||
connection slave; | ||
|
||
# the high_pri ddl replication should go through | ||
show create table t1; | ||
|
||
|
||
## | ||
## clean up | ||
## | ||
|
||
connection master; | ||
drop table t1; | ||
|
||
source include/rpl_end.inc; |
Oops, something went wrong.