Browse Source
Added syntax and implementation for BACKUP STAGE's
Added syntax and implementation for BACKUP STAGE's
Part of MDEV-5336 Implement LOCK FOR BACKUP - Changed check of Global_only_lock to also include BACKUP lock. - We store latest MDL_BACKUP_DDL lock in thd->mdl_backup_ticket to be able to downgrade lock during copy_data_between_tables()pull/1005/head
38 changed files with 3530 additions and 41 deletions
-
2libmysqld/CMakeLists.txt
-
158mysql-test/main/backup_aria.result
-
157mysql-test/main/backup_aria.test
-
520mysql-test/main/backup_interaction.result
-
503mysql-test/main/backup_interaction.test
-
221mysql-test/main/backup_lock.result
-
290mysql-test/main/backup_lock.test
-
40mysql-test/main/backup_priv.result
-
52mysql-test/main/backup_priv.test
-
335mysql-test/main/backup_stages.result
-
385mysql-test/main/backup_stages.test
-
163mysql-test/main/backup_syntax.result
-
181mysql-test/main/backup_syntax.test
-
2mysql-test/main/deprecated_features.result
-
2mysql-test/main/mysqld--help.result
-
4mysql-test/suite/sys_vars/r/sysvars_server_embedded.result
-
4mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result
-
2sql/CMakeLists.txt
-
356sql/backup.cc
-
31sql/backup.h
-
1sql/lex.h
-
10sql/lock.cc
-
4sql/mdl.cc
-
2sql/mysqld.cc
-
10sql/share/errmsg-utf8.txt
-
6sql/sql_base.cc
-
12sql/sql_class.cc
-
27sql/sql_class.h
-
1sql/sql_cmd.h
-
2sql/sql_insert.cc
-
1sql/sql_lex.h
-
17sql/sql_parse.cc
-
5sql/sql_reload.cc
-
19sql/sql_table.cc
-
20sql/sql_yacc.yy
-
20sql/sql_yacc_ora.yy
-
4sql/sys_vars.cc
-
2sql/wsrep_mysqld.cc
@ -0,0 +1,158 @@ |
|||
connect con1,localhost,root,,; |
|||
SET SESSION lock_wait_timeout = 1; |
|||
#----------------------------------------------------------------------- |
|||
# Single-threaded tests |
|||
#----------------------------------------------------------------------- |
|||
# Show the fate and impact of some SELECT /HANDLER ... READ |
|||
# sliding through the sequence. |
|||
CREATE TABLE t_permanent_aria (col1 INT) ENGINE = Aria TRANSACTIONAL = 0; |
|||
INSERT INTO t_permanent_aria SET col1 = 1; |
|||
BACKUP STAGE START; |
|||
SELECT COUNT(*) FROM t_permanent_aria; |
|||
COUNT(*) |
|||
1 |
|||
HANDLER t_permanent_aria OPEN; |
|||
HANDLER t_permanent_aria READ FIRST; |
|||
col1 |
|||
1 |
|||
HANDLER t_permanent_aria CLOSE; |
|||
BACKUP STAGE FLUSH; |
|||
SELECT COUNT(*) FROM t_permanent_aria; |
|||
COUNT(*) |
|||
1 |
|||
HANDLER t_permanent_aria OPEN; |
|||
HANDLER t_permanent_aria READ FIRST; |
|||
col1 |
|||
1 |
|||
HANDLER t_permanent_aria CLOSE; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
SELECT COUNT(*) FROM t_permanent_aria; |
|||
COUNT(*) |
|||
1 |
|||
HANDLER t_permanent_aria OPEN; |
|||
HANDLER t_permanent_aria READ FIRST; |
|||
col1 |
|||
1 |
|||
HANDLER t_permanent_aria CLOSE; |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
SELECT COUNT(*) FROM t_permanent_aria; |
|||
COUNT(*) |
|||
1 |
|||
HANDLER t_permanent_aria OPEN; |
|||
HANDLER t_permanent_aria READ FIRST; |
|||
col1 |
|||
1 |
|||
HANDLER t_permanent_aria CLOSE; |
|||
BACKUP STAGE END; |
|||
# In case the backup lock is taken by the current connection than |
|||
# - DML modifying some permanent table is not allowed |
|||
BACKUP STAGE START; |
|||
SET AUTOCOMMIT = 0; |
|||
INSERT INTO t_permanent_aria SET col1 = 1; |
|||
ERROR HY000: Can't execute the command as you have a BACKUP STAGE active |
|||
SET AUTOCOMMIT = 1; |
|||
INSERT INTO t_permanent_aria SET col1 = 1; |
|||
ERROR HY000: Can't execute the command as you have a BACKUP STAGE active |
|||
# - DDL creating or renaming a permanent table or a procedure is not |
|||
# allowed. |
|||
# The latter tries to modify a permanent system table. |
|||
CREATE TABLE throw_away (col1 INT) ENGINE = Aria TRANSACTIONAL = 0; |
|||
ERROR HY000: Can't execute the command as you have a BACKUP STAGE active |
|||
RENAME TABLE t_permanent_aria To throw_away; |
|||
ERROR HY000: Can't execute the command as you have a BACKUP STAGE active |
|||
# - DDL creating a temporary table is allowed. |
|||
CREATE TEMPORARY TABLE t_temporary_aria (col1 INT) ENGINE = Aria TRANSACTIONAL = 0; |
|||
# - DML modifying that temporary table is allowed. |
|||
INSERT INTO t_temporary_aria SET col1 = 1; |
|||
SELECT COUNT(*) FROM t_temporary_aria; |
|||
COUNT(*) |
|||
1 |
|||
BACKUP STAGE END; |
|||
# Show the fate and impact of some auto committed INSERT into temporary |
|||
# table sliding through the sequence. |
|||
SET AUTOCOMMIT = 1; |
|||
BACKUP STAGE START; |
|||
INSERT INTO t_temporary_aria SET col1 = 1; |
|||
BACKUP STAGE FLUSH; |
|||
INSERT INTO t_temporary_aria SET col1 = 1; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
INSERT INTO t_temporary_aria SET col1 = 1; |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
INSERT INTO t_temporary_aria SET col1 = 1; |
|||
BACKUP STAGE END; |
|||
SELECT COUNT(*) FROM t_temporary_aria; |
|||
COUNT(*) |
|||
5 |
|||
# Show the fate and impact of some DROP/CREATE TEMPORARY TABLE sliding |
|||
# through the sequence. |
|||
SET AUTOCOMMIT = 1; |
|||
BACKUP STAGE START; |
|||
DROP TEMPORARY TABLE t_temporary_aria; |
|||
CREATE TEMPORARY TABLE t_temporary_aria (col1 INT) ENGINE = Aria TRANSACTIONAL = 0; |
|||
BACKUP STAGE FLUSH; |
|||
DROP TEMPORARY TABLE t_temporary_aria; |
|||
CREATE TEMPORARY TABLE t_temporary_aria (col1 INT) ENGINE = Aria TRANSACTIONAL = 0; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
DROP TEMPORARY TABLE t_temporary_aria; |
|||
CREATE TEMPORARY TABLE t_temporary_aria (col1 INT) ENGINE = Aria TRANSACTIONAL = 0; |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
DROP TEMPORARY TABLE t_temporary_aria; |
|||
CREATE TEMPORARY TABLE t_temporary_aria (col1 INT) ENGINE = Aria TRANSACTIONAL = 0; |
|||
BACKUP STAGE END; |
|||
# Show that even more DDL on the temporary table is allowed. |
|||
BACKUP STAGE START; |
|||
TRUNCATE t_temporary_aria; |
|||
ALTER TABLE t_temporary_aria ADD COLUMN col2 INT; |
|||
ALTER TABLE t_temporary_aria ADD KEY idx(col2); |
|||
BACKUP STAGE END; |
|||
DROP TABLE t_permanent_aria; |
|||
#----------------------------------------------------------------------- |
|||
# Show that non transactional tables locks with BACKUP STAGE FLUSH |
|||
#----------------------------------------------------------------------- |
|||
set session lock_wait_timeout=default; |
|||
create table t1 (a int) engine=aria transactional=0; |
|||
insert into t1 values (1), (2); |
|||
connection con1; |
|||
backup stage start; |
|||
backup stage flush; |
|||
connection default; |
|||
select * from t1; |
|||
a |
|||
1 |
|||
2 |
|||
SET STATEMENT lock_wait_timeout=0 FOR INSERT INTO t1 values (3); |
|||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction |
|||
INSERT INTO t1 values (4); |
|||
connection con1; |
|||
backup stage end; |
|||
connection default; |
|||
select * from t1; |
|||
a |
|||
1 |
|||
2 |
|||
4 |
|||
drop table t1; |
|||
#----------------------------------------------------------------------- |
|||
# Show that transactional tables doesn't lock with BACKUP STAGE FLUSH |
|||
#----------------------------------------------------------------------- |
|||
set session lock_wait_timeout=default; |
|||
create table t1 (a int) engine=aria transactional=1 page_checksum=1; |
|||
insert into t1 values (1), (2); |
|||
connection con1; |
|||
backup stage start; |
|||
backup stage flush; |
|||
connection default; |
|||
INSERT INTO t1 values (4); |
|||
connection con1; |
|||
backup stage end; |
|||
connection default; |
|||
select * from t1; |
|||
a |
|||
1 |
|||
2 |
|||
4 |
|||
drop table t1; |
|||
# |
|||
# Cleanup |
|||
# |
|||
disconnect con1; |
@ -0,0 +1,157 @@ |
|||
######################################################################## |
|||
# Tests for Implement LOCK FOR BACKUP (MDEV-5336) |
|||
######################################################################## |
|||
# Check a non transactional table per ENGINE = Aria TRANSACTIONAL = 0. |
|||
# |
|||
|
|||
--source include/not_embedded.inc |
|||
# As non transactional engine we use Aria with TRANSACTIONAL = 0 |
|||
--source include/have_aria.inc |
|||
|
|||
# Following connections are used in a few of the following tests |
|||
connect (con1,localhost,root,,); |
|||
|
|||
SET SESSION lock_wait_timeout = 1; |
|||
|
|||
--echo #----------------------------------------------------------------------- |
|||
--echo # Single-threaded tests |
|||
--echo #----------------------------------------------------------------------- |
|||
|
|||
--echo # Show the fate and impact of some SELECT /HANDLER ... READ |
|||
--echo # sliding through the sequence. |
|||
CREATE TABLE t_permanent_aria (col1 INT) ENGINE = Aria TRANSACTIONAL = 0; |
|||
INSERT INTO t_permanent_aria SET col1 = 1; |
|||
BACKUP STAGE START; |
|||
SELECT COUNT(*) FROM t_permanent_aria; |
|||
HANDLER t_permanent_aria OPEN; |
|||
HANDLER t_permanent_aria READ FIRST; |
|||
HANDLER t_permanent_aria CLOSE; |
|||
BACKUP STAGE FLUSH; |
|||
SELECT COUNT(*) FROM t_permanent_aria; |
|||
HANDLER t_permanent_aria OPEN; |
|||
HANDLER t_permanent_aria READ FIRST; |
|||
HANDLER t_permanent_aria CLOSE; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
SELECT COUNT(*) FROM t_permanent_aria; |
|||
HANDLER t_permanent_aria OPEN; |
|||
HANDLER t_permanent_aria READ FIRST; |
|||
HANDLER t_permanent_aria CLOSE; |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
SELECT COUNT(*) FROM t_permanent_aria; |
|||
HANDLER t_permanent_aria OPEN; |
|||
HANDLER t_permanent_aria READ FIRST; |
|||
HANDLER t_permanent_aria CLOSE; |
|||
BACKUP STAGE END; |
|||
|
|||
--echo # In case the backup lock is taken by the current connection than |
|||
--echo # - DML modifying some permanent table is not allowed |
|||
BACKUP STAGE START; |
|||
SET AUTOCOMMIT = 0; |
|||
--error ER_BACKUP_LOCK_IS_ACTIVE |
|||
INSERT INTO t_permanent_aria SET col1 = 1; |
|||
SET AUTOCOMMIT = 1; |
|||
--error ER_BACKUP_LOCK_IS_ACTIVE |
|||
INSERT INTO t_permanent_aria SET col1 = 1; |
|||
|
|||
--echo # - DDL creating or renaming a permanent table or a procedure is not |
|||
--echo # allowed. |
|||
--echo # The latter tries to modify a permanent system table. |
|||
|
|||
--error ER_BACKUP_LOCK_IS_ACTIVE |
|||
CREATE TABLE throw_away (col1 INT) ENGINE = Aria TRANSACTIONAL = 0; |
|||
--error ER_BACKUP_LOCK_IS_ACTIVE |
|||
RENAME TABLE t_permanent_aria To throw_away; |
|||
--echo # - DDL creating a temporary table is allowed. |
|||
CREATE TEMPORARY TABLE t_temporary_aria (col1 INT) ENGINE = Aria TRANSACTIONAL = 0; |
|||
--echo # - DML modifying that temporary table is allowed. |
|||
INSERT INTO t_temporary_aria SET col1 = 1; |
|||
SELECT COUNT(*) FROM t_temporary_aria; |
|||
BACKUP STAGE END; |
|||
|
|||
--echo # Show the fate and impact of some auto committed INSERT into temporary |
|||
--echo # table sliding through the sequence. |
|||
SET AUTOCOMMIT = 1; |
|||
BACKUP STAGE START; |
|||
INSERT INTO t_temporary_aria SET col1 = 1; |
|||
BACKUP STAGE FLUSH; |
|||
INSERT INTO t_temporary_aria SET col1 = 1; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
INSERT INTO t_temporary_aria SET col1 = 1; |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
INSERT INTO t_temporary_aria SET col1 = 1; |
|||
BACKUP STAGE END; |
|||
SELECT COUNT(*) FROM t_temporary_aria; |
|||
|
|||
--echo # Show the fate and impact of some DROP/CREATE TEMPORARY TABLE sliding |
|||
--echo # through the sequence. |
|||
|
|||
SET AUTOCOMMIT = 1; |
|||
BACKUP STAGE START; |
|||
DROP TEMPORARY TABLE t_temporary_aria; |
|||
CREATE TEMPORARY TABLE t_temporary_aria (col1 INT) ENGINE = Aria TRANSACTIONAL = 0; |
|||
BACKUP STAGE FLUSH; |
|||
DROP TEMPORARY TABLE t_temporary_aria; |
|||
CREATE TEMPORARY TABLE t_temporary_aria (col1 INT) ENGINE = Aria TRANSACTIONAL = 0; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
DROP TEMPORARY TABLE t_temporary_aria; |
|||
CREATE TEMPORARY TABLE t_temporary_aria (col1 INT) ENGINE = Aria TRANSACTIONAL = 0; |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
DROP TEMPORARY TABLE t_temporary_aria; |
|||
CREATE TEMPORARY TABLE t_temporary_aria (col1 INT) ENGINE = Aria TRANSACTIONAL = 0; |
|||
BACKUP STAGE END; |
|||
--echo # Show that even more DDL on the temporary table is allowed. |
|||
BACKUP STAGE START; |
|||
TRUNCATE t_temporary_aria; |
|||
ALTER TABLE t_temporary_aria ADD COLUMN col2 INT; |
|||
ALTER TABLE t_temporary_aria ADD KEY idx(col2); |
|||
BACKUP STAGE END; |
|||
|
|||
DROP TABLE t_permanent_aria; |
|||
|
|||
--echo #----------------------------------------------------------------------- |
|||
--echo # Show that non transactional tables locks with BACKUP STAGE FLUSH |
|||
--echo #----------------------------------------------------------------------- |
|||
|
|||
set session lock_wait_timeout=default; |
|||
create table t1 (a int) engine=aria transactional=0; |
|||
insert into t1 values (1), (2); |
|||
|
|||
connection con1; |
|||
backup stage start; |
|||
backup stage flush; |
|||
connection default; |
|||
select * from t1; |
|||
--error ER_LOCK_WAIT_TIMEOUT |
|||
SET STATEMENT lock_wait_timeout=0 FOR INSERT INTO t1 values (3); |
|||
--send INSERT INTO t1 values (4) |
|||
connection con1; |
|||
backup stage end; |
|||
connection default; |
|||
--reap # send |
|||
select * from t1; |
|||
drop table t1; |
|||
|
|||
--echo #----------------------------------------------------------------------- |
|||
--echo # Show that transactional tables doesn't lock with BACKUP STAGE FLUSH |
|||
--echo #----------------------------------------------------------------------- |
|||
|
|||
set session lock_wait_timeout=default; |
|||
create table t1 (a int) engine=aria transactional=1 page_checksum=1; |
|||
insert into t1 values (1), (2); |
|||
|
|||
connection con1; |
|||
backup stage start; |
|||
backup stage flush; |
|||
connection default; |
|||
INSERT INTO t1 values (4); |
|||
connection con1; |
|||
backup stage end; |
|||
connection default; |
|||
select * from t1; |
|||
drop table t1; |
|||
|
|||
--echo # |
|||
--echo # Cleanup |
|||
--echo # |
|||
|
|||
disconnect con1; |
@ -0,0 +1,520 @@ |
|||
# |
|||
# Check backup and FTWRL |
|||
# |
|||
flush tables with read lock; |
|||
backup stage start; |
|||
ERROR HY000: Can't execute the query because you have a conflicting read lock |
|||
unlock tables; |
|||
backup stage start; |
|||
flush tables with read lock; |
|||
ERROR HY000: Can't execute the command as you have a BACKUP STAGE active |
|||
backup stage end; |
|||
# |
|||
# Check backup and FLUSH TABLES |
|||
# |
|||
flush tables; |
|||
backup stage start; |
|||
flush tables; |
|||
backup stage end; |
|||
# |
|||
# Check BACKUP STAGE under lock tables |
|||
# |
|||
create table t1 (a int); |
|||
lock table t1 write; |
|||
backup stage start; |
|||
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction |
|||
backup stage end; |
|||
ERROR HY000: You must start backup with "BACKUP STAGE START" |
|||
unlock tables; |
|||
lock table t1 read; |
|||
backup stage start; |
|||
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction |
|||
backup stage end; |
|||
ERROR HY000: You must start backup with "BACKUP STAGE START" |
|||
unlock tables; |
|||
# |
|||
# Check lock tables under BACKUP STAGE |
|||
# |
|||
backup stage start; |
|||
unlock tables; |
|||
select lock_mode from information_schema.metadata_lock_info; |
|||
lock_mode |
|||
MDL_BACKUP_START |
|||
lock table t1 write; |
|||
ERROR HY000: Can't execute the command as you have a BACKUP STAGE active |
|||
lock table t1 read; |
|||
ERROR HY000: Can't execute the command as you have a BACKUP STAGE active |
|||
unlock tables; |
|||
backup stage end; |
|||
drop table t1; |
|||
# |
|||
# Check setting readonly under BACKUP STAGE |
|||
# |
|||
backup stage start; |
|||
set @@global.read_only=1; |
|||
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction |
|||
backup stage end; |
|||
# also make sure going back from read-only mode is not allowed |
|||
set @@global.read_only=1; |
|||
backup stage start; |
|||
set @@global.read_only=0; |
|||
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction |
|||
backup stage end; |
|||
set @@global.read_only=0; |
|||
# |
|||
# Check BACKUP STAGE under read_only |
|||
# |
|||
set @@global.read_only=1; |
|||
backup stage start; |
|||
backup stage end; |
|||
set @@global.read_only=0; |
|||
# |
|||
# Check that we can't create tables during backup |
|||
# |
|||
backup stage start; |
|||
create table t1 (a int); |
|||
ERROR HY000: Can't execute the command as you have a BACKUP STAGE active |
|||
backup stage end; |
|||
# also make sure we can't write to a table during backup |
|||
create table t1(a INT); |
|||
backup stage start; |
|||
insert into t1 values(1); |
|||
ERROR HY000: Can't execute the command as you have a BACKUP STAGE active |
|||
insert delayed into t1 values(1); |
|||
ERROR HY000: Can't execute the command as you have a BACKUP STAGE active |
|||
update t1 set a=1; |
|||
ERROR HY000: Can't execute the command as you have a BACKUP STAGE active |
|||
delete from t1; |
|||
ERROR HY000: Can't execute the command as you have a BACKUP STAGE active |
|||
truncate table t1; |
|||
ERROR HY000: Can't execute the command as you have a BACKUP STAGE active |
|||
drop table t1; |
|||
ERROR HY000: Can't execute the command as you have a BACKUP STAGE active |
|||
backup stage end; |
|||
drop table t1; |
|||
# |
|||
# BACKUP STAGE performs implicit commits |
|||
# |
|||
create table t1(a int) engine=InnoDB; |
|||
begin; |
|||
insert into t1 values(1); |
|||
select lock_mode from information_schema.metadata_lock_info; |
|||
lock_mode |
|||
MDL_SHARED_WRITE |
|||
backup stage start; |
|||
select lock_mode from information_schema.metadata_lock_info; |
|||
lock_mode |
|||
MDL_BACKUP_START |
|||
backup stage block_commit; |
|||
commit; |
|||
backup stage end; |
|||
drop table t1; |
|||
# Ensure that BACKUP STAGE ... does AUTOCOMMIT like most DDL. |
|||
# Sideeffect: |
|||
# Show the impact of not yet committed INSERT before sequence start |
|||
# and ROLLBACK sliding through the sequence. |
|||
CREATE TABLE t1 (col1 INT) ENGINE = InnoDB; |
|||
SET AUTOCOMMIT = 0; |
|||
INSERT INTO t1 SET col1 = 1; |
|||
BACKUP STAGE START; |
|||
ROLLBACK; |
|||
BACKUP STAGE END; |
|||
#---- |
|||
INSERT INTO t1 SET col1 = 1; |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE FLUSH; |
|||
ROLLBACK; |
|||
BACKUP STAGE END; |
|||
#---- |
|||
INSERT INTO t1 SET col1 = 1; |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE FLUSH; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
ROLLBACK; |
|||
BACKUP STAGE END; |
|||
#---- |
|||
INSERT INTO t1 SET col1 = 1; |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE FLUSH; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
ROLLBACK; |
|||
BACKUP STAGE END; |
|||
#---- |
|||
INSERT INTO t1 SET col1 = 1; |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE FLUSH; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
BACKUP STAGE END; |
|||
ROLLBACK; |
|||
SELECT COUNT(*) = 5 AS expect_1 FROM t1; |
|||
expect_1 |
|||
1 |
|||
# Show the impact of not yet committed INSERT before sequence start |
|||
# and a COMMIT sliding through the sequence. |
|||
SET AUTOCOMMIT = 0; |
|||
INSERT INTO t1 SET col1 = 1; |
|||
BACKUP STAGE START; |
|||
COMMIT; |
|||
BACKUP STAGE END; |
|||
#---- |
|||
INSERT INTO t1 SET col1 = 1; |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE FLUSH; |
|||
COMMIT; |
|||
BACKUP STAGE END; |
|||
#---- |
|||
INSERT INTO t1 SET col1 = 1; |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE FLUSH; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
COMMIT; |
|||
BACKUP STAGE END; |
|||
#---- |
|||
INSERT INTO t1 SET col1 = 1; |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE FLUSH; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
COMMIT; |
|||
BACKUP STAGE END; |
|||
#---- |
|||
INSERT INTO t1 SET col1 = 1; |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE FLUSH; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
BACKUP STAGE END; |
|||
COMMIT; |
|||
SELECT COUNT(*) = 10 AS expect_1 FROM t1; |
|||
expect_1 |
|||
1 |
|||
DELETE FROM t1; |
|||
COMMIT; |
|||
drop table t1; |
|||
# |
|||
# CHECK: RO transaction under BACKUP STAGE is a potential deadlock |
|||
# OTOH we most probably allow them under FTWRL as well |
|||
# |
|||
CREATE TABLE t1 (col1 INT) ENGINE = InnoDB; |
|||
insert into t1 values (1); |
|||
backup stage start; |
|||
backup stage block_commit; |
|||
begin; |
|||
select * from t1; |
|||
col1 |
|||
1 |
|||
select lock_mode from information_schema.metadata_lock_info; |
|||
lock_mode |
|||
MDL_BACKUP_WAIT_COMMIT |
|||
MDL_SHARED_READ |
|||
backup stage end; |
|||
select lock_mode from information_schema.metadata_lock_info; |
|||
lock_mode |
|||
drop table t1; |
|||
# |
|||
# Check that handler are closed by backup stage block_ddl |
|||
# |
|||
create table t1 (a int, key a (a)); |
|||
insert into t1 (a) values (1), (2), (3), (4), (5); |
|||
handler t1 open; |
|||
handler t1 read a prev; |
|||
a |
|||
5 |
|||
backup stage start; |
|||
handler t1 read a prev; |
|||
a |
|||
4 |
|||
backup stage flush; |
|||
backup stage block_ddl; |
|||
handler t1 read a prev; |
|||
a |
|||
5 |
|||
backup stage block_commit; |
|||
handler t1 read a prev; |
|||
a |
|||
4 |
|||
backup stage end; |
|||
handler t1 close; |
|||
drop table t1; |
|||
# Show the fate and impact of some SELECT /HANDLER ... READ |
|||
# sliding through the sequence. |
|||
CREATE TABLE t1_innodb (col1 INT) ENGINE = InnoDB; |
|||
INSERT INTO t1_innodb values (1),(2),(3); |
|||
COMMIT; |
|||
CREATE TABLE t1_myisam (col1 INT) ENGINE = MyISAM; |
|||
INSERT INTO t1_myisam values (1),(2),(3); |
|||
BACKUP STAGE START; |
|||
SELECT COUNT(*) FROM t1_innodb; |
|||
COUNT(*) |
|||
3 |
|||
SELECT * FROM t1_innodb; |
|||
col1 |
|||
1 |
|||
2 |
|||
3 |
|||
HANDLER t1_innodb OPEN; |
|||
HANDLER t1_innodb READ FIRST; |
|||
col1 |
|||
1 |
|||
HANDLER t1_innodb CLOSE; |
|||
SELECT COUNT(*) FROM t1_myisam; |
|||
COUNT(*) |
|||
3 |
|||
HANDLER t1_myisam OPEN; |
|||
HANDLER t1_myisam READ FIRST; |
|||
col1 |
|||
1 |
|||
HANDLER t1_myisam CLOSE; |
|||
BACKUP STAGE FLUSH; |
|||
SELECT COUNT(*) FROM t1_innodb; |
|||
COUNT(*) |
|||
3 |
|||
HANDLER t1_innodb OPEN; |
|||
HANDLER t1_innodb READ FIRST; |
|||
col1 |
|||
1 |
|||
HANDLER t1_innodb CLOSE; |
|||
SELECT COUNT(*) FROM t1_myisam; |
|||
COUNT(*) |
|||
3 |
|||
HANDLER t1_myisam OPEN; |
|||
HANDLER t1_myisam READ FIRST; |
|||
col1 |
|||
1 |
|||
HANDLER t1_myisam CLOSE; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
SELECT COUNT(*) FROM t1_innodb; |
|||
COUNT(*) |
|||
3 |
|||
HANDLER t1_innodb OPEN; |
|||
HANDLER t1_innodb READ FIRST; |
|||
col1 |
|||
1 |
|||
HANDLER t1_innodb CLOSE; |
|||
SELECT COUNT(*) FROM t1_myisam; |
|||
COUNT(*) |
|||
3 |
|||
HANDLER t1_myisam OPEN; |
|||
HANDLER t1_myisam READ FIRST; |
|||
col1 |
|||
1 |
|||
HANDLER t1_myisam CLOSE; |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
SELECT COUNT(*) FROM t1_innodb; |
|||
COUNT(*) |
|||
3 |
|||
HANDLER t1_innodb OPEN; |
|||
HANDLER t1_innodb READ FIRST; |
|||
col1 |
|||
1 |
|||
HANDLER t1_innodb CLOSE; |
|||
SELECT COUNT(*) FROM t1_myisam; |
|||
COUNT(*) |
|||
3 |
|||
HANDLER t1_myisam OPEN; |
|||
HANDLER t1_myisam READ FIRST; |
|||
col1 |
|||
1 |
|||
HANDLER t1_myisam CLOSE; |
|||
BACKUP STAGE END; |
|||
drop table t1_innodb,t1_myisam; |
|||
# Show the fate and impact of some SET GLOBAL tx_read_only = 1/0 |
|||
# sliding through the sequence. |
|||
BACKUP STAGE START; |
|||
SET GLOBAL tx_read_only = 1; |
|||
SET GLOBAL tx_read_only = 0; |
|||
BACKUP STAGE FLUSH; |
|||
SET GLOBAL tx_read_only = 1; |
|||
SET GLOBAL tx_read_only = 0; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
SET GLOBAL tx_read_only = 1; |
|||
SET GLOBAL tx_read_only = 0; |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
SET GLOBAL tx_read_only = 1; |
|||
SET GLOBAL tx_read_only = 0; |
|||
BACKUP STAGE END; |
|||
# Show the fate and impact of some SET SESSION sql_log_bin = 0/1 |
|||
# sliding through the sequence. |
|||
COMMIT; |
|||
SET SESSION sql_log_bin = 1; |
|||
BACKUP STAGE START; |
|||
SET SESSION sql_log_bin = 0; |
|||
SET SESSION sql_log_bin = 1; |
|||
BACKUP STAGE FLUSH; |
|||
SET SESSION sql_log_bin = 0; |
|||
SET SESSION sql_log_bin = 1; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
SET SESSION sql_log_bin = 0; |
|||
SET SESSION sql_log_bin = 1; |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
SET SESSION sql_log_bin = 0; |
|||
SET SESSION sql_log_bin = 1; |
|||
BACKUP STAGE END; |
|||
#---- |
|||
SET SESSION sql_log_bin = 0; |
|||
BACKUP STAGE START; |
|||
SET SESSION sql_log_bin = 1; |
|||
SET SESSION sql_log_bin = 0; |
|||
BACKUP STAGE FLUSH; |
|||
SET SESSION sql_log_bin = 1; |
|||
SET SESSION sql_log_bin = 0; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
SET SESSION sql_log_bin = 1; |
|||
SET SESSION sql_log_bin = 0; |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
SET SESSION sql_log_bin = 1; |
|||
SET SESSION sql_log_bin = 0; |
|||
BACKUP STAGE END; |
|||
SET SESSION sql_log_bin = 1; |
|||
#----------------------------------------------------------------------- |
|||
# BACKUP STAGE statements are not allowed in stored routines |
|||
#----------------------------------------------------------------------- |
|||
CREATE TABLE t1 (col1 INT); |
|||
CREATE PROCEDURE p1() |
|||
BEGIN |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE FLUSH; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
BACKUP STAGE END; |
|||
END| |
|||
ERROR 0A000: BACKUP STAGE is not allowed in stored procedures |
|||
CREATE FUNCTION f1 (s CHAR(20)) RETURNS INT DETERMINISTIC |
|||
BEGIN |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE FLUSH; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
BACKUP STAGE END; |
|||
RETURN 1; |
|||
END| |
|||
ERROR 0A000: BACKUP STAGE is not allowed in stored procedures |
|||
CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW |
|||
BEGIN |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE FLUSH; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
BACKUP STAGE END; |
|||
END| |
|||
ERROR 0A000: BACKUP STAGE is not allowed in stored procedures |
|||
DROP TABLE t1; |
|||
#----------------------------------------------------------------------- |
|||
# Check BACKUP status variables |
|||
#----------------------------------------------------------------------- |
|||
SET SESSION lock_wait_timeout = 1; |
|||
FLUSH STATUS; |
|||
# Show how the status variable 'Com_backup' changes after BACKUP STAGE .. |
|||
SHOW STATUS LIKE 'Com_backup'; |
|||
Variable_name Value |
|||
Com_backup 0 |
|||
BACKUP STAGE START; |
|||
SHOW STATUS LIKE 'Com_backup'; |
|||
Variable_name Value |
|||
Com_backup 1 |
|||
BACKUP STAGE START; |
|||
ERROR HY000: Backup stage 'START' is same or before current backup stage 'START' |
|||
SHOW STATUS LIKE 'Com_backup'; |
|||
Variable_name Value |
|||
Com_backup 2 |
|||
BACKUP STAGE FLUSH; |
|||
SHOW STATUS LIKE 'Com_backup'; |
|||
Variable_name Value |
|||
Com_backup 3 |
|||
BACKUP STAGE BLOCK_DDL; |
|||
SHOW STATUS LIKE 'Com_backup'; |
|||
Variable_name Value |
|||
Com_backup 4 |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
SHOW STATUS LIKE 'Com_backup'; |
|||
Variable_name Value |
|||
Com_backup 5 |
|||
BACKUP STAGE END; |
|||
# In case the backup lock is taken by the current connection than |
|||
# - DML modifying some permanent table is not allowed |
|||
CREATE TABLE t1_innodb (col1 INT) ENGINE = InnoDB; |
|||
CREATE TABLE t1_myisam (col1 INT) ENGINE = MyISAM; |
|||
BACKUP STAGE START; |
|||
SET AUTOCOMMIT = 0; |
|||
INSERT INTO t1_innodb SET col1 = 1; |
|||
ERROR HY000: Can't execute the command as you have a BACKUP STAGE active |
|||
SET AUTOCOMMIT = 1; |
|||
INSERT INTO t1_innodb SET col1 = 1; |
|||
ERROR HY000: Can't execute the command as you have a BACKUP STAGE active |
|||
INSERT INTO t1_myisam SET col1 = 1; |
|||
ERROR HY000: Can't execute the command as you have a BACKUP STAGE active |
|||
# - DDL creating or renaming a permanent table or a procedure etc. |
|||
# is not allowed. |
|||
CREATE TABLE throw_away (col1 INT) ENGINE = InnoDB; |
|||
ERROR HY000: Can't execute the command as you have a BACKUP STAGE active |
|||
RENAME TABLE t1_innodb To throw_away; |
|||
ERROR HY000: Can't execute the command as you have a BACKUP STAGE active |
|||
CREATE PROCEDURE p1() SELECT 13; |
|||
ERROR HY000: Can't execute the command as you have a BACKUP STAGE active |
|||
CREATE PROCEDURE p1() SELECT 13; |
|||
ERROR HY000: Can't execute the command as you have a BACKUP STAGE active |
|||
BACKUP STAGE END; |
|||
DROP TABLE t1_innodb; |
|||
DROP TABLE t1_myisam; |
|||
# |
|||
# Creating and modifying TEMPORARY TABLES are allowed |
|||
# |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
CREATE TEMPORARY TABLE tmp (col1 INT); |
|||
DROP TEMPORARY TABLE tmp; |
|||
CREATE TEMPORARY TABLE t_temporary_innodb (col1 INT) ENGINE = InnoDB; |
|||
CREATE TEMPORARY TABLE t_temporary_myisam (col1 INT) ENGINE = MyISAM; |
|||
# - DML modifying that temporary table is allowed. |
|||
INSERT INTO t_temporary_innodb SET col1 = 1; |
|||
SELECT COUNT(*) FROM t_temporary_innodb; |
|||
COUNT(*) |
|||
1 |
|||
INSERT INTO t_temporary_myisam SET col1 = 1; |
|||
SELECT COUNT(*) FROM t_temporary_myisam; |
|||
COUNT(*) |
|||
1 |
|||
BACKUP STAGE END; |
|||
# Show the fate and impact of some auto committed INSERT into temporary |
|||
# table sliding through the sequence. |
|||
SET AUTOCOMMIT = 1; |
|||
BACKUP STAGE START; |
|||
INSERT INTO t_temporary_innodb SET col1 = 1; |
|||
INSERT INTO t_temporary_myisam SET col1 = 1; |
|||
BACKUP STAGE FLUSH; |
|||
INSERT INTO t_temporary_innodb SET col1 = 1; |
|||
INSERT INTO t_temporary_myisam SET col1 = 1; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
INSERT INTO t_temporary_innodb SET col1 = 1; |
|||
INSERT INTO t_temporary_myisam SET col1 = 1; |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
INSERT INTO t_temporary_innodb SET col1 = 1; |
|||
INSERT INTO t_temporary_myisam SET col1 = 1; |
|||
BACKUP STAGE END; |
|||
SELECT COUNT(*) FROM t_temporary_innodb; |
|||
COUNT(*) |
|||
5 |
|||
# Show the fate and impact of some DROP/CREATE TEMPORARY TABLE sliding |
|||
# through the sequence. |
|||
SET AUTOCOMMIT = 1; |
|||
BACKUP STAGE START; |
|||
DROP TEMPORARY TABLE t_temporary_innodb; |
|||
CREATE TEMPORARY TABLE t_temporary_innodb (col1 INT) ENGINE = InnoDB; |
|||
BACKUP STAGE FLUSH; |
|||
DROP TEMPORARY TABLE t_temporary_innodb; |
|||
CREATE TEMPORARY TABLE t_temporary_innodb (col1 INT) ENGINE = InnoDB; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
DROP TEMPORARY TABLE t_temporary_innodb; |
|||
CREATE TEMPORARY TABLE t_temporary_innodb (col1 INT) ENGINE = InnoDB; |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
DROP TEMPORARY TABLE t_temporary_innodb; |
|||
CREATE TEMPORARY TABLE t_temporary_innodb (col1 INT) ENGINE = InnoDB; |
|||
BACKUP STAGE END; |
|||
# Show that even more DDL on the temporary table is allowed. |
|||
BACKUP STAGE START; |
|||
TRUNCATE t_temporary_innodb; |
|||
ALTER TABLE t_temporary_innodb ADD COLUMN col2 INT; |
|||
ALTER TABLE t_temporary_innodb ADD KEY idx(col2); |
|||
BACKUP STAGE END; |
@ -0,0 +1,503 @@ |
|||
######################################################################## |
|||
# Tests how BACKUP STAGE interacts with other commands (MDEV-5336) |
|||
######################################################################## |
|||
|
|||
--source include/have_innodb.inc |
|||
--source include/have_metadata_lock_info.inc |
|||
|
|||
--echo # |
|||
--echo # Check backup and FTWRL |
|||
--echo # |
|||
|
|||
flush tables with read lock; |
|||
--error ER_CANT_UPDATE_WITH_READLOCK |
|||
backup stage start; |
|||
unlock tables; |
|||
backup stage start; |
|||
--error ER_BACKUP_LOCK_IS_ACTIVE |
|||
flush tables with read lock; |
|||
backup stage end; |
|||
|
|||
--echo # |
|||
--echo # Check backup and FLUSH TABLES |
|||
--echo # |
|||
|
|||
flush tables; |
|||
backup stage start; |
|||
flush tables; |
|||
backup stage end; |
|||
|
|||
--echo # |
|||
--echo # Check BACKUP STAGE under lock tables |
|||
--echo # |
|||
|
|||
create table t1 (a int); |
|||
lock table t1 write; |
|||
--error ER_LOCK_OR_ACTIVE_TRANSACTION |
|||
backup stage start; |
|||
--error ER_BACKUP_NOT_RUNNING |
|||
backup stage end; |
|||
unlock tables; |
|||
|
|||
lock table t1 read; |
|||
--error ER_LOCK_OR_ACTIVE_TRANSACTION |
|||
backup stage start; |
|||
--error ER_BACKUP_NOT_RUNNING |
|||
backup stage end; |
|||
unlock tables; |
|||
|
|||
|
|||
--echo # |
|||
--echo # Check lock tables under BACKUP STAGE |
|||
--echo # |
|||
backup stage start; |
|||
unlock tables; |
|||
select lock_mode from information_schema.metadata_lock_info; |
|||
|
|||
--error ER_BACKUP_LOCK_IS_ACTIVE |
|||
lock table t1 write; |
|||
--error ER_BACKUP_LOCK_IS_ACTIVE |
|||
lock table t1 read; |
|||
unlock tables; |
|||
backup stage end; |
|||
drop table t1; |
|||
|
|||
|
|||
--echo # |
|||
--echo # Check setting readonly under BACKUP STAGE |
|||
--echo # |
|||
backup stage start; |
|||
--error ER_LOCK_OR_ACTIVE_TRANSACTION |
|||
set @@global.read_only=1; |
|||
backup stage end; |
|||
|
|||
--echo # also make sure going back from read-only mode is not allowed |
|||
set @@global.read_only=1; |
|||
backup stage start; |
|||
--error ER_LOCK_OR_ACTIVE_TRANSACTION |
|||
set @@global.read_only=0; |
|||
backup stage end; |
|||
set @@global.read_only=0; |
|||
|
|||
--echo # |
|||
--echo # Check BACKUP STAGE under read_only |
|||
--echo # |
|||
|
|||
set @@global.read_only=1; |
|||
backup stage start; |
|||
backup stage end; |
|||
set @@global.read_only=0; |
|||
|
|||
--echo # |
|||
--echo # Check that we can't create tables during backup |
|||
--echo # |
|||
|
|||
backup stage start; |
|||
--error ER_BACKUP_LOCK_IS_ACTIVE |
|||
create table t1 (a int); |
|||
backup stage end; |
|||
|
|||
--echo # also make sure we can't write to a table during backup |
|||
create table t1(a INT); |
|||
backup stage start; |
|||
--error ER_BACKUP_LOCK_IS_ACTIVE |
|||
insert into t1 values(1); |
|||
--error ER_BACKUP_LOCK_IS_ACTIVE |
|||
insert delayed into t1 values(1); |
|||
--error ER_BACKUP_LOCK_IS_ACTIVE |
|||
update t1 set a=1; |
|||
--error ER_BACKUP_LOCK_IS_ACTIVE |
|||
delete from t1; |
|||
--error ER_BACKUP_LOCK_IS_ACTIVE |
|||
truncate table t1; |
|||
--error ER_BACKUP_LOCK_IS_ACTIVE |
|||
drop table t1; |
|||
backup stage end; |
|||
drop table t1; |
|||
|
|||
--echo # |
|||
--echo # BACKUP STAGE performs implicit commits |
|||
--echo # |
|||
create table t1(a int) engine=InnoDB; |
|||
begin; |
|||
insert into t1 values(1); |
|||
select lock_mode from information_schema.metadata_lock_info; |
|||
backup stage start; |
|||
select lock_mode from information_schema.metadata_lock_info; |
|||
backup stage block_commit; |
|||
commit; |
|||
backup stage end; |
|||
drop table t1; |
|||
|
|||
--echo # Ensure that BACKUP STAGE ... does AUTOCOMMIT like most DDL. |
|||
--echo # Sideeffect: |
|||
--echo # Show the impact of not yet committed INSERT before sequence start |
|||
--echo # and ROLLBACK sliding through the sequence. |
|||
|
|||
CREATE TABLE t1 (col1 INT) ENGINE = InnoDB; |
|||
SET AUTOCOMMIT = 0; |
|||
INSERT INTO t1 SET col1 = 1; |
|||
BACKUP STAGE START; |
|||
ROLLBACK; |
|||
BACKUP STAGE END; |
|||
--echo #---- |
|||
INSERT INTO t1 SET col1 = 1; |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE FLUSH; |
|||
ROLLBACK; |
|||
BACKUP STAGE END; |
|||
--echo #---- |
|||
INSERT INTO t1 SET col1 = 1; |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE FLUSH; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
ROLLBACK; |
|||
BACKUP STAGE END; |
|||
--echo #---- |
|||
INSERT INTO t1 SET col1 = 1; |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE FLUSH; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
ROLLBACK; |
|||
BACKUP STAGE END; |
|||
--echo #---- |
|||
INSERT INTO t1 SET col1 = 1; |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE FLUSH; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
BACKUP STAGE END; |
|||
ROLLBACK; |
|||
SELECT COUNT(*) = 5 AS expect_1 FROM t1; |
|||
|
|||
--echo # Show the impact of not yet committed INSERT before sequence start |
|||
--echo # and a COMMIT sliding through the sequence. |
|||
|
|||
SET AUTOCOMMIT = 0; |
|||
INSERT INTO t1 SET col1 = 1; |
|||
BACKUP STAGE START; |
|||
COMMIT; |
|||
BACKUP STAGE END; |
|||
--echo #---- |
|||
INSERT INTO t1 SET col1 = 1; |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE FLUSH; |
|||
COMMIT; |
|||
BACKUP STAGE END; |
|||
--echo #---- |
|||
INSERT INTO t1 SET col1 = 1; |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE FLUSH; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
COMMIT; |
|||
BACKUP STAGE END; |
|||
--echo #---- |
|||
INSERT INTO t1 SET col1 = 1; |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE FLUSH; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
COMMIT; |
|||
BACKUP STAGE END; |
|||
--echo #---- |
|||
INSERT INTO t1 SET col1 = 1; |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE FLUSH; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
BACKUP STAGE END; |
|||
COMMIT; |
|||
SELECT COUNT(*) = 10 AS expect_1 FROM t1; |
|||
DELETE FROM t1; |
|||
COMMIT; |
|||
drop table t1; |
|||
|
|||
--echo # |
|||
--echo # CHECK: RO transaction under BACKUP STAGE is a potential deadlock |
|||
--echo # OTOH we most probably allow them under FTWRL as well |
|||
--echo # |
|||
|
|||
CREATE TABLE t1 (col1 INT) ENGINE = InnoDB; |
|||
insert into t1 values (1); |
|||
backup stage start; |
|||
backup stage block_commit; |
|||
begin; |
|||
select * from t1; |
|||
select lock_mode from information_schema.metadata_lock_info; |
|||
backup stage end; |
|||
select lock_mode from information_schema.metadata_lock_info; |
|||
drop table t1; |
|||
|
|||
--echo # |
|||
--echo # Check that handler are closed by backup stage block_ddl |
|||
--echo # |
|||
|
|||
create table t1 (a int, key a (a)); |
|||
insert into t1 (a) values (1), (2), (3), (4), (5); |
|||
handler t1 open; |
|||
handler t1 read a prev; |
|||
backup stage start; |
|||
handler t1 read a prev; |
|||
backup stage flush; |
|||
backup stage block_ddl; |
|||
handler t1 read a prev; |
|||
backup stage block_commit; |
|||
handler t1 read a prev; |
|||
backup stage end; |
|||
handler t1 close; |
|||
drop table t1; |
|||
|
|||
--echo # Show the fate and impact of some SELECT /HANDLER ... READ |
|||
--echo # sliding through the sequence. |
|||
|
|||
CREATE TABLE t1_innodb (col1 INT) ENGINE = InnoDB; |
|||
INSERT INTO t1_innodb values (1),(2),(3); |
|||
COMMIT; |
|||
CREATE TABLE t1_myisam (col1 INT) ENGINE = MyISAM; |
|||
INSERT INTO t1_myisam values (1),(2),(3); |
|||
BACKUP STAGE START; |
|||
SELECT COUNT(*) FROM t1_innodb; |
|||
SELECT * FROM t1_innodb; |
|||
HANDLER t1_innodb OPEN; |
|||
HANDLER t1_innodb READ FIRST; |
|||
HANDLER t1_innodb CLOSE; |
|||
SELECT COUNT(*) FROM t1_myisam; |
|||
HANDLER t1_myisam OPEN; |
|||
HANDLER t1_myisam READ FIRST; |
|||
HANDLER t1_myisam CLOSE; |
|||
BACKUP STAGE FLUSH; |
|||
SELECT COUNT(*) FROM t1_innodb; |
|||
HANDLER t1_innodb OPEN; |
|||
HANDLER t1_innodb READ FIRST; |
|||
HANDLER t1_innodb CLOSE; |
|||
SELECT COUNT(*) FROM t1_myisam; |
|||
HANDLER t1_myisam OPEN; |
|||
HANDLER t1_myisam READ FIRST; |
|||
HANDLER t1_myisam CLOSE; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
SELECT COUNT(*) FROM t1_innodb; |
|||
HANDLER t1_innodb OPEN; |
|||
HANDLER t1_innodb READ FIRST; |
|||
HANDLER t1_innodb CLOSE; |
|||
SELECT COUNT(*) FROM t1_myisam; |
|||
HANDLER t1_myisam OPEN; |
|||
HANDLER t1_myisam READ FIRST; |
|||
HANDLER t1_myisam CLOSE; |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
SELECT COUNT(*) FROM t1_innodb; |
|||
HANDLER t1_innodb OPEN; |
|||
HANDLER t1_innodb READ FIRST; |
|||
HANDLER t1_innodb CLOSE; |
|||
SELECT COUNT(*) FROM t1_myisam; |
|||
HANDLER t1_myisam OPEN; |
|||
HANDLER t1_myisam READ FIRST; |
|||
HANDLER t1_myisam CLOSE; |
|||
BACKUP STAGE END; |
|||
drop table t1_innodb,t1_myisam; |
|||
|
|||
--echo # Show the fate and impact of some SET GLOBAL tx_read_only = 1/0 |
|||
--echo # sliding through the sequence. |
|||
|
|||
BACKUP STAGE START; |
|||
SET GLOBAL tx_read_only = 1; |
|||
SET GLOBAL tx_read_only = 0; |
|||
BACKUP STAGE FLUSH; |
|||
SET GLOBAL tx_read_only = 1; |
|||
SET GLOBAL tx_read_only = 0; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
SET GLOBAL tx_read_only = 1; |
|||
SET GLOBAL tx_read_only = 0; |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
SET GLOBAL tx_read_only = 1; |
|||
SET GLOBAL tx_read_only = 0; |
|||
BACKUP STAGE END; |
|||
|
|||
--echo # Show the fate and impact of some SET SESSION sql_log_bin = 0/1 |
|||
--echo # sliding through the sequence. |
|||
COMMIT; |
|||
SET SESSION sql_log_bin = 1; |
|||
BACKUP STAGE START; |
|||
SET SESSION sql_log_bin = 0; |
|||
SET SESSION sql_log_bin = 1; |
|||
BACKUP STAGE FLUSH; |
|||
SET SESSION sql_log_bin = 0; |
|||
SET SESSION sql_log_bin = 1; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
SET SESSION sql_log_bin = 0; |
|||
SET SESSION sql_log_bin = 1; |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
SET SESSION sql_log_bin = 0; |
|||
SET SESSION sql_log_bin = 1; |
|||
BACKUP STAGE END; |
|||
|
|||
--echo #---- |
|||
SET SESSION sql_log_bin = 0; |
|||
BACKUP STAGE START; |
|||
SET SESSION sql_log_bin = 1; |
|||
SET SESSION sql_log_bin = 0; |
|||
BACKUP STAGE FLUSH; |
|||
SET SESSION sql_log_bin = 1; |
|||
SET SESSION sql_log_bin = 0; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
SET SESSION sql_log_bin = 1; |
|||
SET SESSION sql_log_bin = 0; |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
SET SESSION sql_log_bin = 1; |
|||
SET SESSION sql_log_bin = 0; |
|||
BACKUP STAGE END; |
|||
SET SESSION sql_log_bin = 1; |
|||
|
|||
--echo #----------------------------------------------------------------------- |
|||
--echo # BACKUP STAGE statements are not allowed in stored routines |
|||
--echo #----------------------------------------------------------------------- |
|||
|
|||
CREATE TABLE t1 (col1 INT); |
|||
|
|||
delimiter |; |
|||
--error ER_SP_BADSTATEMENT |
|||
CREATE PROCEDURE p1() |
|||
BEGIN |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE FLUSH; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
BACKUP STAGE END; |
|||
END| |
|||
|
|||
--error ER_SP_BADSTATEMENT |
|||
CREATE FUNCTION f1 (s CHAR(20)) RETURNS INT DETERMINISTIC |
|||
BEGIN |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE FLUSH; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
BACKUP STAGE END; |
|||
RETURN 1; |
|||
END| |
|||
|
|||
--error ER_SP_BADSTATEMENT |
|||
CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW |
|||
BEGIN |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE FLUSH; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
BACKUP STAGE END; |
|||
END| |
|||
|
|||
delimiter ;| |
|||
DROP TABLE t1; |
|||
|
|||
--echo #----------------------------------------------------------------------- |
|||
--echo # Check BACKUP status variables |
|||
--echo #----------------------------------------------------------------------- |
|||
|
|||
SET SESSION lock_wait_timeout = 1; |
|||
|
|||
FLUSH STATUS; |
|||
|
|||
# MDEV-5336 introduces the status variable Com_backup |
|||
--echo # Show how the status variable 'Com_backup' changes after BACKUP STAGE .. |
|||
|
|||
SHOW STATUS LIKE 'Com_backup'; |
|||
BACKUP STAGE START; |
|||
SHOW STATUS LIKE 'Com_backup'; |
|||
--error ER_BACKUP_WRONG_STAGE |
|||
BACKUP STAGE START; |
|||
SHOW STATUS LIKE 'Com_backup'; |
|||
BACKUP STAGE FLUSH; |
|||
SHOW STATUS LIKE 'Com_backup'; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
SHOW STATUS LIKE 'Com_backup'; |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
SHOW STATUS LIKE 'Com_backup'; |
|||
BACKUP STAGE END; |
|||
|
|||
--echo # In case the backup lock is taken by the current connection than |
|||
--echo # - DML modifying some permanent table is not allowed |
|||
|
|||
CREATE TABLE t1_innodb (col1 INT) ENGINE = InnoDB; |
|||
CREATE TABLE t1_myisam (col1 INT) ENGINE = MyISAM; |
|||
|
|||
BACKUP STAGE START; |
|||
SET AUTOCOMMIT = 0; |
|||
--error ER_BACKUP_LOCK_IS_ACTIVE |
|||
INSERT INTO t1_innodb SET col1 = 1; |
|||
SET AUTOCOMMIT = 1; |
|||
--error ER_BACKUP_LOCK_IS_ACTIVE |
|||
INSERT INTO t1_innodb SET col1 = 1; |
|||
--error ER_BACKUP_LOCK_IS_ACTIVE |
|||
INSERT INTO t1_myisam SET col1 = 1; |
|||
--echo # - DDL creating or renaming a permanent table or a procedure etc. |
|||
--echo # is not allowed. |
|||
--error ER_BACKUP_LOCK_IS_ACTIVE |
|||
CREATE TABLE throw_away (col1 INT) ENGINE = InnoDB; |
|||
--error ER_BACKUP_LOCK_IS_ACTIVE |
|||
RENAME TABLE t1_innodb To throw_away; |
|||
--error ER_BACKUP_LOCK_IS_ACTIVE |
|||
CREATE PROCEDURE p1() SELECT 13; |
|||
--error ER_BACKUP_LOCK_IS_ACTIVE |
|||
CREATE PROCEDURE p1() SELECT 13; |
|||
BACKUP STAGE END; |
|||
DROP TABLE t1_innodb; |
|||
DROP TABLE t1_myisam; |
|||
|
|||
--echo # |
|||
--echo # Creating and modifying TEMPORARY TABLES are allowed |
|||
--echo # |
|||
|
|||
BACKUP STAGE START; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
CREATE TEMPORARY TABLE tmp (col1 INT); |
|||
DROP TEMPORARY TABLE tmp; |
|||
|
|||
CREATE TEMPORARY TABLE t_temporary_innodb (col1 INT) ENGINE = InnoDB; |
|||
CREATE TEMPORARY TABLE t_temporary_myisam (col1 INT) ENGINE = MyISAM; |
|||
--echo # - DML modifying that temporary table is allowed. |
|||
INSERT INTO t_temporary_innodb SET col1 = 1; |
|||
SELECT COUNT(*) FROM t_temporary_innodb; |
|||
INSERT INTO t_temporary_myisam SET col1 = 1; |
|||
SELECT COUNT(*) FROM t_temporary_myisam; |
|||
BACKUP STAGE END; |
|||
|
|||
--echo # Show the fate and impact of some auto committed INSERT into temporary |
|||
--echo # table sliding through the sequence. |
|||
SET AUTOCOMMIT = 1; |
|||
BACKUP STAGE START; |
|||
INSERT INTO t_temporary_innodb SET col1 = 1; |
|||
INSERT INTO t_temporary_myisam SET col1 = 1; |
|||
BACKUP STAGE FLUSH; |
|||
INSERT INTO t_temporary_innodb SET col1 = 1; |
|||
INSERT INTO t_temporary_myisam SET col1 = 1; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
INSERT INTO t_temporary_innodb SET col1 = 1; |
|||
INSERT INTO t_temporary_myisam SET col1 = 1; |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
INSERT INTO t_temporary_innodb SET col1 = 1; |
|||
INSERT INTO t_temporary_myisam SET col1 = 1; |
|||
BACKUP STAGE END; |
|||
SELECT COUNT(*) FROM t_temporary_innodb; |
|||
|
|||
--echo # Show the fate and impact of some DROP/CREATE TEMPORARY TABLE sliding |
|||
--echo # through the sequence. |
|||
SET AUTOCOMMIT = 1; |
|||
BACKUP STAGE START; |
|||
DROP TEMPORARY TABLE t_temporary_innodb; |
|||
CREATE TEMPORARY TABLE t_temporary_innodb (col1 INT) ENGINE = InnoDB; |
|||
BACKUP STAGE FLUSH; |
|||
DROP TEMPORARY TABLE t_temporary_innodb; |
|||
CREATE TEMPORARY TABLE t_temporary_innodb (col1 INT) ENGINE = InnoDB; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
DROP TEMPORARY TABLE t_temporary_innodb; |
|||
CREATE TEMPORARY TABLE t_temporary_innodb (col1 INT) ENGINE = InnoDB; |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
DROP TEMPORARY TABLE t_temporary_innodb; |
|||
CREATE TEMPORARY TABLE t_temporary_innodb (col1 INT) ENGINE = InnoDB; |
|||
BACKUP STAGE END; |
|||
--echo # Show that even more DDL on the temporary table is allowed. |
|||
BACKUP STAGE START; |
|||
TRUNCATE t_temporary_innodb; |
|||
ALTER TABLE t_temporary_innodb ADD COLUMN col2 INT; |
|||
ALTER TABLE t_temporary_innodb ADD KEY idx(col2); |
|||
BACKUP STAGE END; |
@ -0,0 +1,221 @@ |
|||
# |
|||
# Testing which locks we get from all stages |
|||
# |
|||
BACKUP STAGE START; |
|||
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; |
|||
LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME |
|||
MDL_BACKUP_START Backup lock |
|||
BACKUP STAGE FLUSH; |
|||
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; |
|||
LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME |
|||
MDL_BACKUP_FLUSH Backup lock |
|||
BACKUP STAGE BLOCK_DDL; |
|||
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; |
|||
LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME |
|||
MDL_BACKUP_WAIT_DDL Backup lock |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; |
|||
LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME |
|||
MDL_BACKUP_WAIT_COMMIT Backup lock |
|||
BACKUP STAGE END; |
|||
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; |
|||
LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME |
|||
# |
|||
# testing BACKUP STAGE LOCK's |
|||
# |
|||
connect con1,localhost,root,,; |
|||
connect con2,localhost,root,,; |
|||
connection default; |
|||
# |
|||
# testing if BACKUP STAGE FLUSH causes deadlocks with ALTER TABLE |
|||
# |
|||
create table t1 (a int) engine=innodb; |
|||
start transaction; |
|||
insert into t1 values (1); |
|||
connection con1; |
|||
alter table t1 add column (j int), algorithm copy; |
|||
connection con2; |
|||
backup stage start; |
|||
backup stage flush; |
|||
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; |
|||
LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME |
|||
MDL_BACKUP_DDL Backup lock |
|||
MDL_BACKUP_FLUSH Backup lock |
|||
MDL_SHARED_WRITE Table metadata lock test t1 |
|||
MDL_SHARED_UPGRADABLE Table metadata lock test t1 |
|||
MDL_INTENTION_EXCLUSIVE Schema metadata lock test |
|||
SET STATEMENT max_statement_time=1 FOR backup stage block_ddl; |
|||
ERROR 70100: Query execution was interrupted (max_statement_time exceeded) |
|||
backup stage block_ddl; |
|||
connection default; |
|||
commit; |
|||
SELECT * FROM t1; |
|||
a |
|||
1 |
|||
SET STATEMENT lock_wait_timeout=0 FOR INSERT INTO t1 values (2); |
|||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction |
|||
INSERT INTO t1 values (2,0);; |
|||
connection con2; |
|||
backup stage end; |
|||
connection con1; |
|||
connection default; |
|||
select * from t1; |
|||
a j |
|||
1 NULL |
|||
2 0 |
|||
drop table t1; |
|||
# Test with inline alter table, which doesn't block block_commit |
|||
create table t1 (a int) engine=innodb; |
|||
start transaction; |
|||
insert into t1 values (1); |
|||
connection con1; |
|||
alter table t1 add column (j int); |
|||
connection con2; |
|||
backup stage start; |
|||
backup stage flush; |
|||
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; |
|||
LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME |
|||
MDL_BACKUP_ALTER_COPY Backup lock |
|||
MDL_BACKUP_FLUSH Backup lock |
|||
MDL_SHARED_WRITE Table metadata lock test t1 |
|||
MDL_SHARED_UPGRADABLE Table metadata lock test t1 |
|||
MDL_INTENTION_EXCLUSIVE Schema metadata lock test |
|||
backup stage block_ddl; |
|||
backup stage block_commit; |
|||
connection default; |
|||
SELECT * FROM t1; |
|||
a |
|||
1 |
|||
commit; |
|||
connection con2; |
|||
backup stage end; |
|||
connection con1; |
|||
connection default; |
|||
drop table t1; |
|||
# |
|||
# testing if BACKUP STAGE FLUSH causes deadlocks with DROP TABLE |
|||
# |
|||
create table t1 (a int) engine=innodb; |
|||
start transaction; |
|||
insert into t1 values (1); |
|||
connection con1; |
|||
SET STATEMENT lock_wait_timeout=0 FOR DROP TABLE t1; |
|||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction |
|||
DROP TABLE t1; |
|||
connection con2; |
|||
backup stage start; |
|||
backup stage flush; |
|||
SET STATEMENT lock_wait_timeout=0 FOR SELECT * FROM t1; |
|||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction |
|||
SET STATEMENT lock_wait_timeout=0 FOR backup stage block_ddl; |
|||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction |
|||
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; |
|||
LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME |
|||
MDL_BACKUP_DDL Backup lock |
|||
MDL_BACKUP_FLUSH Backup lock |
|||
MDL_SHARED_WRITE Table metadata lock test t1 |
|||
MDL_INTENTION_EXCLUSIVE Schema metadata lock test |
|||
backup stage end; |
|||
connection default; |
|||
commit; |
|||
connection con1; |
|||
connection default; |
|||
# |
|||
# Check if backup stage block_dll + concurrent drop table blocks select |
|||
# |
|||
create table t1 (a int) engine=innodb; |
|||
backup stage start; |
|||
backup stage block_ddl; |
|||
connection con1; |
|||
DROP TABLE t1; |
|||
connection con2; |
|||
connection con2; |
|||
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; |
|||
LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME |
|||
MDL_BACKUP_WAIT_DDL Backup lock |
|||
SELECT * FROM t1; |
|||
a |
|||
connection default; |
|||
backup stage end; |
|||
connection con1; |
|||
connection default; |
|||
# |
|||
# Check if backup stage block_dll overrides ddl lock for drop table |
|||
# |
|||
create table t1 (a int) engine=innodb; |
|||
start transaction; |
|||
insert into t1 values (1); |
|||
connection con1; |
|||
SET STATEMENT lock_wait_timeout=0 FOR DROP TABLE t1; |
|||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction |
|||
DROP TABLE t1; |
|||
connection con2; |
|||
backup stage start; |
|||
backup stage flush; |
|||
backup stage block_ddl; |
|||
connection default; |
|||
commit; |
|||
connection con2; |
|||
backup stage end; |
|||
connection con1; |
|||
connection default; |
|||
# |
|||
# Check if BACKUP STAGE BLOCK_COMMIT blocks commit |
|||
# |
|||
create table t1 (a int) engine=innodb; |
|||
start transaction; |
|||
insert into t1 values (1); |
|||
connection con1; |
|||
backup stage start; |
|||
backup stage block_commit; |
|||
connection default; |
|||
commit; |
|||
connection con1; |
|||
backup stage end; |
|||
connection default; |
|||
select * from t1; |
|||
a |
|||
1 |
|||
drop table t1; |
|||
disconnect con1; |
|||
disconnect con2; |
|||
# |
|||
# Test backup stage and flush tables |
|||
# |
|||
BACKUP STAGE START ; |
|||
BACKUP STAGE BLOCK_DDL ; |
|||
FLUSH TABLES; |
|||
CREATE TEMPORARY TABLE t12345678_tmp (col1 INT); |
|||
drop table t12345678_tmp; |
|||
BACKUP STAGE END; |
|||
# |
|||
# Test BACKUP STAGES with lock timeouts |
|||
# |
|||
SET GLOBAL lock_wait_timeout=0; |
|||
CREATE TABLE t_permanent_innodb (col1 INT) ENGINE = InnoDB; |
|||
CREATE TABLE t_permanent_myisam (col1 INT) ENGINE = MyISAM; |
|||
INSERT INTO t_permanent_innodb SET col1 = 1; |
|||
INSERT INTO t_permanent_myisam SET col1 = 1; |
|||
CREATE TABLE t_con1_innodb (col1 INT) ENGINE = InnoDB; |
|||
CREATE TABLE t_con1_myisam (col1 INT) ENGINE = MyISAM; |
|||
connect con1,localhost,root,,; |
|||
SET AUTOCOMMIT = 0; |
|||
connection default; |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE FLUSH; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
connection con1; |
|||
UPDATE t_permanent_innodb SET col1 = 8; |
|||
UPDATE t_permanent_myisam SET col1 = 8; |
|||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction |
|||
DROP TABLE t_con1_innodb; |
|||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction |
|||
DROP TABLE t_con1_myisam; |
|||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction |
|||
connection default; |
|||
BACKUP STAGE END; |
|||
DROP TABLE t_permanent_myisam, t_permanent_innodb; |
|||
DROP TABLE t_con1_innodb, t_con1_myisam; |
|||
disconnect con1; |
|||
set global lock_wait_timeout=default; |
@ -0,0 +1,290 @@ |
|||
######################################################################## |
|||
# Tests BACKUP STAGE locking |
|||
######################################################################## |
|||
|
|||
--source include/have_innodb.inc |
|||
--source include/have_metadata_lock_info.inc |
|||
--source include/not_embedded.inc |
|||
|
|||
--echo # |
|||
--echo # Testing which locks we get from all stages |
|||
--echo # |
|||
|
|||
BACKUP STAGE START; |
|||
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; |
|||
BACKUP STAGE FLUSH; |
|||
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; |
|||
BACKUP STAGE END; |
|||
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; |
|||
|
|||
--echo # |
|||
--echo # testing BACKUP STAGE LOCK's |
|||
--echo # |
|||
|
|||
# Following connections are used in a few of the following tests |
|||
connect (con1,localhost,root,,); |
|||
connect (con2,localhost,root,,); |
|||
connection default; |
|||
|
|||
--echo # |
|||
--echo # testing if BACKUP STAGE FLUSH causes deadlocks with ALTER TABLE |
|||
--echo # |
|||
|
|||
create table t1 (a int) engine=innodb; |
|||
|
|||
start transaction; |
|||
# Acquires MDL lock |
|||
insert into t1 values (1); |
|||
|
|||
connection con1; |
|||
# Waits on MDL |
|||
--send alter table t1 add column (j int), algorithm copy |
|||
|
|||
connection con2; |
|||
let $wait_condition= |
|||
select count(*) = 1 from information_schema.processlist |
|||
where state = "Waiting for table metadata lock"; |
|||
--source include/wait_condition.inc |
|||
backup stage start; |
|||
backup stage flush; |
|||
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; |
|||
# |
|||
# Do first test with max_statement_time, other tests later are done with |
|||
# lock_wait_timeout. This is mostly to ensure that both methods works |
|||
# |
|||
--error ER_STATEMENT_TIMEOUT |
|||
SET STATEMENT max_statement_time=1 FOR backup stage block_ddl; |
|||
--send backup stage block_ddl |
|||
|
|||
connection default; |
|||
let $wait_condition= |
|||
select count(*) = 1 from information_schema.processlist |
|||
where state = "Waiting for backup lock"; |
|||
--source include/wait_condition.inc |
|||
commit; |
|||
# The following select works because alter table is waiting for DDL lock |
|||
SELECT * FROM t1; |
|||
--error ER_LOCK_WAIT_TIMEOUT |
|||
SET STATEMENT lock_wait_timeout=0 FOR INSERT INTO t1 values (2); |
|||
--send INSERT INTO t1 values (2,0); |
|||
connection con2; |
|||
--reap # BLOCK_DDL |
|||
backup stage end; |
|||
connection con1; |
|||
--reap # ALTER TABLE |
|||
connection default; |
|||
--reap # INSERT |
|||
select * from t1; |
|||
drop table t1; |
|||
|
|||
--echo # Test with inline alter table, which doesn't block block_commit |
|||
|
|||
create table t1 (a int) engine=innodb; |
|||
|
|||
start transaction; |
|||
# Acquires MDL lock |
|||
insert into t1 values (1); |
|||
|
|||
connection con1; |
|||
# Waits on MDL |
|||
--send alter table t1 add column (j int) |
|||
|
|||
connection con2; |
|||
let $wait_condition= |
|||
select count(*) = 1 from information_schema.processlist |
|||
where state = "Waiting for table metadata lock"; |
|||
--source include/wait_condition.inc |
|||
backup stage start; |
|||
backup stage flush; |
|||
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; |
|||
backup stage block_ddl; |
|||
backup stage block_commit; |
|||
connection default; |
|||
SELECT * FROM t1; |
|||
--send commit |
|||
connection con2; |
|||
let $wait_condition= |
|||
select count(*) = 1 from information_schema.processlist |
|||
where state = "Waiting for backup lock"; |
|||
backup stage end; |
|||
connection con1; |
|||
--reap # ALTER TABLE |
|||
connection default; |
|||
--reap # commit |
|||
drop table t1; |
|||
|
|||
--echo # |
|||
--echo # testing if BACKUP STAGE FLUSH causes deadlocks with DROP TABLE |
|||
--echo # |
|||
|
|||
create table t1 (a int) engine=innodb; |
|||
start transaction; |
|||
# Acquires MDL lock |
|||
insert into t1 values (1); |
|||
|
|||
connection con1; |
|||
# Waits on MDL |
|||
--error ER_LOCK_WAIT_TIMEOUT |
|||
SET STATEMENT lock_wait_timeout=0 FOR DROP TABLE t1; |
|||
--send DROP TABLE t1 |
|||
|
|||
connection con2; |
|||
backup stage start; |
|||
backup stage flush; |
|||
let $wait_condition= |
|||
select count(*) = 1 from information_schema.processlist |
|||
where state = "Waiting for table metadata lock"; |
|||
--source include/wait_condition.inc |
|||
--error ER_LOCK_WAIT_TIMEOUT |
|||
SET STATEMENT lock_wait_timeout=0 FOR SELECT * FROM t1; |
|||
|
|||
--error ER_LOCK_WAIT_TIMEOUT |
|||
SET STATEMENT lock_wait_timeout=0 FOR backup stage block_ddl; |
|||
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; |
|||
backup stage end; |
|||
|
|||
connection default; |
|||
commit; |
|||
connection con1; |
|||
--reap # DROP TABLE |
|||
connection default; |
|||
|
|||
--echo # |
|||
--echo # Check if backup stage block_dll + concurrent drop table blocks select |
|||
--echo # |
|||
|
|||
create table t1 (a int) engine=innodb; |
|||
backup stage start; |
|||
backup stage block_ddl; |
|||
connection con1; |
|||
--send DROP TABLE t1 |
|||
connection con2; |
|||
let $wait_condition= |
|||
select count(*) = 1 from information_schema.processlist |
|||
where state = "Waiting for backup lock"; |
|||
--source include/wait_condition.inc |
|||
connection con2; |
|||
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; |
|||
# Check that select's are not blocked |
|||
SELECT * FROM t1; |
|||
connection default; |
|||
backup stage end; |
|||
connection con1; |
|||
--reap |
|||
connection default; |
|||
|
|||
--echo # |
|||
--echo # Check if backup stage block_dll overrides ddl lock for drop table |
|||
--echo # |
|||
|
|||
create table t1 (a int) engine=innodb; |
|||
start transaction; |
|||
# Acquires MDL lock |
|||
insert into t1 values (1); |
|||
|
|||
connection con1; |
|||
# Waits on MDL |
|||
--error ER_LOCK_WAIT_TIMEOUT |
|||
SET STATEMENT lock_wait_timeout=0 FOR DROP TABLE t1; |
|||
--send DROP TABLE t1 |
|||
|
|||
connection con2; |
|||
backup stage start; |
|||
backup stage flush; |
|||
--send backup stage block_ddl |
|||
connection default; |
|||
let $wait_condition= |
|||
select count(*) = 1 from information_schema.processlist |
|||
where state = "Waiting for backup lock"; |
|||
--source include/wait_condition.inc |
|||
commit; |
|||
connection con2; |
|||
--reap |
|||
backup stage end; |
|||
connection con1; |
|||
--reap # DROP TABLE |
|||
connection default; |
|||
|
|||
--echo # |
|||
--echo # Check if BACKUP STAGE BLOCK_COMMIT blocks commit |
|||
--echo # |
|||
|
|||
create table t1 (a int) engine=innodb; |
|||
start transaction; |
|||
# Acquires MDL lock |
|||
insert into t1 values (1); |
|||
|
|||
connection con1; |
|||
backup stage start; |
|||
backup stage block_commit; |
|||
connection default; |
|||
--send commit |
|||
connection con1; |
|||
let $wait_condition= |
|||
select count(*) = 1 from information_schema.processlist |
|||
where state = "Waiting for backup lock"; |
|||
backup stage end; |
|||
connection default; |
|||
--reap # commit |
|||
select * from t1; |
|||
drop table t1; |
|||
|
|||
# |
|||
# End of tests using con1 and con2 |
|||
# |
|||
disconnect con1; |
|||
disconnect con2; |
|||
|
|||
--echo # |
|||
--echo # Test backup stage and flush tables |
|||
--echo # |
|||
|
|||
BACKUP STAGE START ; |
|||
BACKUP STAGE BLOCK_DDL ; |
|||
FLUSH TABLES; |
|||
CREATE TEMPORARY TABLE t12345678_tmp (col1 INT); |
|||
drop table t12345678_tmp; |
|||
BACKUP STAGE END; |
|||
|
|||
--echo # |
|||
--echo # Test BACKUP STAGES with lock timeouts |
|||
--echo # |
|||
|
|||
SET GLOBAL lock_wait_timeout=0; |
|||
CREATE TABLE t_permanent_innodb (col1 INT) ENGINE = InnoDB; |
|||
CREATE TABLE t_permanent_myisam (col1 INT) ENGINE = MyISAM; |
|||
INSERT INTO t_permanent_innodb SET col1 = 1; |
|||
|
|||
INSERT INTO t_permanent_myisam SET col1 = 1; |
|||
CREATE TABLE t_con1_innodb (col1 INT) ENGINE = InnoDB; |
|||
CREATE TABLE t_con1_myisam (col1 INT) ENGINE = MyISAM; |
|||
|
|||
--connect(con1,localhost,root,,) |
|||
SET AUTOCOMMIT = 0; |
|||
|
|||
--connection default |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE FLUSH; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
|
|||
--connection con1 |
|||
UPDATE t_permanent_innodb SET col1 = 8; |
|||
--error ER_LOCK_WAIT_TIMEOUT |
|||
UPDATE t_permanent_myisam SET col1 = 8; |
|||
--error ER_LOCK_WAIT_TIMEOUT |
|||
DROP TABLE t_con1_innodb; |
|||
|
|||
--error ER_LOCK_WAIT_TIMEOUT |
|||
DROP TABLE t_con1_myisam; |
|||
|
|||
--connection default |
|||
BACKUP STAGE END; |
|||
DROP TABLE t_permanent_myisam, t_permanent_innodb; |
|||
DROP TABLE t_con1_innodb, t_con1_myisam; |
|||
--disconnect con1 |
|||
set global lock_wait_timeout=default; |
@ -0,0 +1,40 @@ |
|||
# |
|||
# Test privileges for BACKUP STAGES |
|||
# |
|||
set sql_mode=""; |
|||
GRANT RELOAD ON *.* TO user1@localhost; |
|||
GRANT CREATE, DROP ON *.* TO user2@localhost; |
|||
connect con1, localhost, user1; |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE END; |
|||
# change_user must release backup lock |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE FLUSH; |
|||
SELECT lock_mode FROM information_schema.metadata_lock_info WHERE lock_type='Backup lock'; |
|||
lock_mode |
|||
MDL_BACKUP_FLUSH |
|||
SELECT lock_mode FROM information_schema.metadata_lock_info WHERE lock_type='Backup lock'; |
|||
lock_mode |
|||
disconnect con1; |
|||
connection default; |
|||
# A very low privileged user (-> con4) cannot acquire the backup lock |
|||
connect con1, localhost, user2; |
|||
BACKUP STAGE START; |
|||
ERROR 42000: Access denied; you need (at least one of) the RELOAD privilege(s) for this operation |
|||
BACKUP STAGE FLUSH; |
|||
ERROR 42000: Access denied; you need (at least one of) the RELOAD privilege(s) for this operation |
|||
BACKUP STAGE BLOCK_DDL; |
|||
ERROR 42000: Access denied; you need (at least one of) the RELOAD privilege(s) for this operation |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
ERROR 42000: Access denied; you need (at least one of) the RELOAD privilege(s) for this operation |
|||
BACKUP STAGE END; |
|||
ERROR 42000: Access denied; you need (at least one of) the RELOAD privilege(s) for this operation |
|||
disconnect con1; |
|||
connection default; |
|||
DROP USER user1@localhost, user2@localhost; |
|||
# |
|||
# Test using BACKUP STAGES in a SP |
|||
# |
|||
create procedure foo42() |
|||
BACKUP STAGE START; |
|||
ERROR 0A000: BACKUP STAGE is not allowed in stored procedures |
@ -0,0 +1,52 @@ |
|||
--source include/have_innodb.inc |
|||
--source include/not_embedded.inc |
|||
--source include/have_metadata_lock_info.inc |
|||
|
|||
--echo # |
|||
--echo # Test privileges for BACKUP STAGES |
|||
--echo # |
|||
|
|||
set sql_mode=""; |
|||
|
|||
GRANT RELOAD ON *.* TO user1@localhost; |
|||
GRANT CREATE, DROP ON *.* TO user2@localhost; |
|||
|
|||
--connect(con1, localhost, user1) |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE END; |
|||
--echo # change_user must release backup lock |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE FLUSH; |
|||
SELECT lock_mode FROM information_schema.metadata_lock_info WHERE lock_type='Backup lock'; |
|||
change_user user2; |
|||
SELECT lock_mode FROM information_schema.metadata_lock_info WHERE lock_type='Backup lock'; |
|||
--disconnect con1 |
|||
--source include/wait_until_disconnected.inc |
|||
--connection default |
|||
|
|||
--echo # A very low privileged user (-> con4) cannot acquire the backup lock |
|||
|
|||
--connect(con1, localhost, user2) |
|||
--error ER_SPECIFIC_ACCESS_DENIED_ERROR |
|||
BACKUP STAGE START; |
|||
--error ER_SPECIFIC_ACCESS_DENIED_ERROR |
|||
BACKUP STAGE FLUSH; |
|||
--error ER_SPECIFIC_ACCESS_DENIED_ERROR |
|||
BACKUP STAGE BLOCK_DDL; |
|||
--error ER_SPECIFIC_ACCESS_DENIED_ERROR |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
--error ER_SPECIFIC_ACCESS_DENIED_ERROR |
|||
BACKUP STAGE END; |
|||
--disconnect con1 |
|||
--source include/wait_until_disconnected.inc |
|||
|
|||
--connection default |
|||
DROP USER user1@localhost, user2@localhost; |
|||
|
|||
--echo # |
|||
--echo # Test using BACKUP STAGES in a SP |
|||
--echo # |
|||
|
|||
--error ER_SP_BADSTATEMENT |
|||
create procedure foo42() |
|||
BACKUP STAGE START; |
@ -0,0 +1,335 @@ |
|||
#----------------------------------------------------------------------- |
|||
# Multi-threaded tests |
|||
#----------------------------------------------------------------------- |
|||
# Show that only one connection can hold the backup lock. |
|||
connection default; |
|||
BACKUP STAGE START; |
|||
connect con1,localhost,root,,; |
|||
SET STATEMENT lock_wait_timeout=0 FOR BACKUP STAGE START; |
|||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction |
|||
BACKUP STAGE START; |
|||
connection default; |
|||
# Show that the connection con1 has to wait for the backup lock and the |
|||
# corresponding representation within the processlist. |
|||
SET @con1_id = <con1_id>; |
|||
SELECT ID, USER, COMMAND, STATE, INFO, STAGE, MAX_STAGE, INFO_BINARY |
|||
FROM information_schema.processlist WHERE id = @con1_id; |
|||
ID USER COMMAND STATE INFO STAGE MAX_STAGE INFO_BINARY |
|||
<con1_id> root Query Waiting for backup lock BACKUP STAGE START 0 0 BACKUP STAGE START |
|||
BACKUP STAGE END; |
|||
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; |
|||
LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME |
|||
MDL_BACKUP_START Backup lock |
|||
connection con1; |
|||
# The connection default has removed the backup lock. |
|||
# And so the current connection con1 can reap for its BACKUP STAGE START |
|||
connect con2,localhost,root,,; |
|||
# The connection con2 cannot continue the work of con1 by setting the |
|||
# next BACKUP STAGE FLUSH. |
|||
BACKUP STAGE FLUSH; |
|||
ERROR HY000: You must start backup with "BACKUP STAGE START" |
|||
BACKUP STAGE START; |
|||
connection default; |
|||
SET @con2_id = <con2_id>; |
|||
# Connection con2 waits for the backup lock held by con1. |
|||
SELECT ID, USER, COMMAND, STATE, INFO, STAGE, MAX_STAGE, INFO_BINARY |
|||
FROM information_schema.processlist WHERE id = @con2_id; |
|||
ID USER COMMAND STATE INFO STAGE MAX_STAGE INFO_BINARY |
|||
<con2_id> root Query Waiting for backup lock BACKUP STAGE START 0 0 BACKUP STAGE START |
|||
disconnect con1; |
|||
connection con2; |
|||
# Connection con1 frees the backup lock held by disconnecting. |
|||
# So connection con2 gets the backup lock. |
|||
connect con3,localhost,root,,; |
|||
BACKUP STAGE START; |
|||
connection default; |
|||
SET @con3_id = <con3_id>; |
|||
# Connection con3 waits for the backup lock held by con2. |
|||
SELECT ID, USER, COMMAND, STATE, INFO, STAGE, MAX_STAGE, INFO_BINARY |
|||
FROM information_schema.processlist WHERE id = @con3_id; |
|||
ID USER COMMAND STATE INFO STAGE MAX_STAGE INFO_BINARY |
|||
<con3_id> root Query Waiting for backup lock BACKUP STAGE START 0 0 BACKUP STAGE START |
|||
KILL CONNECTION @con2_id; |
|||
connection con3; |
|||
# Connection con2 frees the backup lock held by getting killed. |
|||
# So connection con3 gets the backup lock. |
|||
BACKUP STAGE END; |
|||
disconnect con3; |
|||
connection default; |
|||
CREATE TABLE t_permanent_innodb (col1 INT) ENGINE = InnoDB; |
|||
INSERT INTO t_permanent_innodb SET col1 = 1; |
|||
CREATE TABLE t_permanent_myisam (col1 INT) ENGINE = MyISAM; |
|||
INSERT INTO t_permanent_myisam SET col1 = 1; |
|||
connect backup,localhost,root,,; |
|||
connect con11,localhost,root,,; |
|||
SET AUTOCOMMIT = 0; |
|||
set session lock_wait_timeout=0; |
|||
connect con12,localhost,root,,; |
|||
SET AUTOCOMMIT = 1; |
|||
# Between (connection default) BACKUP STAGE START and FLUSH |
|||
# no restrictions for concurrent sessions regarding DDL or DML |
|||
# affecting transactional/non transactional permanent tables. |
|||
connection backup; |
|||
BACKUP STAGE START; |
|||
connection con11; |
|||
UPDATE t_permanent_innodb SET col1 = 2; |
|||
UPDATE t_permanent_myisam SET col1 = 2; |
|||
SELECT COUNT(*) FROM t_permanent_innodb; |
|||
COUNT(*) |
|||
1 |
|||
HANDLER t_permanent_innodb OPEN; |
|||
HANDLER t_permanent_innodb READ FIRST; |
|||
col1 |
|||
2 |
|||
HANDLER t_permanent_innodb CLOSE; |
|||
SELECT COUNT(*) FROM t_permanent_myisam; |
|||
COUNT(*) |
|||
1 |
|||
HANDLER t_permanent_myisam OPEN; |
|||
HANDLER t_permanent_myisam READ FIRST; |
|||
col1 |
|||
2 |
|||
HANDLER t_permanent_myisam CLOSE; |
|||
CREATE TABLE t_con1_innodb (col1 INT) ENGINE = InnoDB; |
|||
CREATE TABLE t_con1_myisam (col1 INT) ENGINE = InnoDB; |
|||
ALTER TABLE t_permanent_innodb ADD COLUMN col2 INT; |
|||
ALTER TABLE t_permanent_myisam ADD COLUMN col2 INT; |
|||
CREATE OR REPLACE VIEW v_some_view AS SELECT * FROM t_permanent_innodb; |
|||
CREATE OR REPLACE VIEW v_some_view AS SELECT * FROM t_permanent_myisam; |
|||
connection con12; |
|||
UPDATE t_permanent_innodb SET col1 = 3; |
|||
UPDATE t_permanent_myisam SET col1 = 3; |
|||
# Between (connection default) BACKUP STAGE FLUSH and BLOCK_DDL |
|||
# concurrent sessions |
|||
# - can change transactional permanent tables with DDL and DML |
|||
# - can run DROP/CREATE transactional/non transactional TABLE |
|||
# - cannot modify non transactional permanent tables with DDL or DML |
|||
connection backup; |
|||
BACKUP STAGE FLUSH; |
|||
connection con11; |
|||
UPDATE t_permanent_innodb SET col1 = 4; |
|||
SET STATEMENT lock_wait_timeout=0 FOR UPDATE t_permanent_myisam SET col1 = 4; |
|||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction |
|||
SELECT COUNT(*) FROM t_permanent_innodb; |
|||
COUNT(*) |
|||
1 |
|||
HANDLER t_permanent_innodb OPEN; |
|||
HANDLER t_permanent_innodb READ FIRST; |
|||
col1 col2 |
|||
4 NULL |
|||
HANDLER t_permanent_innodb CLOSE; |
|||
SELECT COUNT(*) FROM t_permanent_myisam; |
|||
COUNT(*) |
|||
1 |
|||
HANDLER t_permanent_myisam OPEN; |
|||
HANDLER t_permanent_myisam READ FIRST; |
|||
col1 col2 |
|||
3 NULL |
|||
HANDLER t_permanent_myisam CLOSE; |
|||
DROP TABLE t_con1_innodb; |
|||
DROP TABLE t_con1_myisam; |
|||
CREATE TABLE t_con1_innodb (col1 INT) ENGINE = InnoDB; |
|||
CREATE TABLE t_con1_myisam (col1 INT) ENGINE = InnoDB; |
|||
ALTER TABLE t_permanent_innodb ADD COLUMN col3 INT; |
|||
SET STATEMENT lock_wait_timeout=0 FOR ALTER TABLE t_permanent_myisam ADD COLUMN col3 INT; |
|||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction |
|||
CREATE OR REPLACE VIEW v_some_view AS SELECT * FROM t_permanent_innodb; |
|||
CREATE OR REPLACE VIEW v_some_view AS SELECT * FROM t_permanent_myisam; |
|||
connection con12; |
|||
UPDATE t_permanent_innodb SET col1 = 5; |
|||
# Between (connection default) BACKUP STAGE BLOCK_DDL and BLOCK_COMMIT |
|||
# concurrent sessions |
|||
# - can change transactional permanent tables with DML |
|||
# - cannot run DDL |
|||
# - cannot change non transactional permanent tables with DML |
|||
connection backup; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
connection con11; |
|||
UPDATE t_permanent_innodb SET col1 = 6; |
|||
UPDATE t_permanent_myisam SET col1 = 6; |
|||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction |
|||
SELECT COUNT(*) FROM t_permanent_innodb; |
|||
COUNT(*) |
|||
1 |
|||
HANDLER t_permanent_innodb OPEN; |
|||
HANDLER t_permanent_innodb READ FIRST; |
|||
col1 col2 col3 |
|||
6 NULL NULL |
|||
HANDLER t_permanent_innodb CLOSE; |
|||
SELECT COUNT(*) FROM t_permanent_myisam; |
|||
COUNT(*) |
|||
1 |
|||
HANDLER t_permanent_myisam OPEN; |
|||
HANDLER t_permanent_myisam READ FIRST; |
|||
col1 col2 |
|||
3 NULL |
|||
HANDLER t_permanent_myisam CLOSE; |
|||
DROP TABLE t_con1_innodb; |
|||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction |
|||
CREATE TABLE throw_away (col1 INT) ENGINE = InnoDB; |
|||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction |
|||
ALTER TABLE t_permanent_innodb ADD COLUMN col4 INT; |
|||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction |
|||
CREATE OR REPLACE VIEW v_some_view AS SELECT * FROM t_permanent_innodb; |
|||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction |
|||
CREATE OR REPLACE VIEW v_some_view AS SELECT * FROM t_permanent_myisam; |
|||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction |
|||
connection con12; |
|||
UPDATE t_permanent_innodb SET col1 = 7; |
|||
# Between (connection default) BACKUP STAGE BLOCK_COMMIT and END |
|||
# concurrent sessions |
|||
# - can change transactional permanent tables with DML |
|||
# - cannot run DDL |
|||
# - cannot change non transactional permanent tables with DML |
|||
connection backup; |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
connection con11; |
|||
UPDATE t_permanent_innodb SET col1 = 8; |
|||
UPDATE t_permanent_myisam SET col1 = 8; |
|||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction |
|||
SELECT COUNT(*) FROM t_permanent_innodb; |
|||
COUNT(*) |
|||
1 |
|||
HANDLER t_permanent_innodb OPEN; |
|||
HANDLER t_permanent_innodb READ FIRST; |
|||
col1 col2 col3 |
|||
8 NULL NULL |
|||
HANDLER t_permanent_innodb CLOSE; |
|||
SELECT COUNT(*) FROM t_permanent_myisam; |
|||
COUNT(*) |
|||
1 |
|||
HANDLER t_permanent_myisam OPEN; |
|||
HANDLER t_permanent_myisam READ FIRST; |
|||
col1 col2 |
|||
3 NULL |
|||
HANDLER t_permanent_myisam CLOSE; |
|||
DROP TABLE t_con1_innodb; |
|||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction |
|||
DROP TABLE t_con1_myisam; |
|||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction |
|||
connection con12; |
|||
SET STATEMENT lock_wait_timeout=0 FOR UPDATE t_permanent_innodb SET col1 = 9; |
|||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction |
|||
connection backup; |
|||
BACKUP STAGE END; |
|||
connection con11; |
|||
COMMIT; |
|||
SELECT * FROM t_permanent_innodb ORDER BY col1; |
|||
col1 col2 col3 |
|||
7 NULL NULL |
|||
SELECT * FROM t_permanent_myisam ORDER BY col1; |
|||
col1 col2 |
|||
3 NULL |
|||
SET AUTOCOMMIT = 0; |
|||
SET GLOBAL tx_read_only = 1; |
|||
connection con12; |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE END; |
|||
SET GLOBAL tx_read_only = 0; |
|||
DROP VIEW v_some_view; |
|||
DROP TABLE t_con1_innodb; |
|||
DROP TABLE t_con1_myisam; |
|||
# Connection backup holds the backup log and is on some stage. |
|||
# Connection con11 tries to LOCK TABLEs or to set read_only. |
|||
connection backup; |
|||
BACKUP STAGE START; |
|||
connection con11; |
|||
# Between BACKUP STAGE START and FLUSH: |
|||
# No restrictions for other connection around LOCK TABLES or read-only. |
|||
LOCK TABLES t_permanent_innodb READ; |
|||
LOCK TABLES t_permanent_myisam READ; |
|||
LOCK TABLES t_permanent_innodb WRITE; |
|||
LOCK TABLES t_permanent_myisam WRITE; |
|||
UNLOCK TABLES; |
|||
SET GLOBAL tx_read_only = 1; |
|||
SET GLOBAL tx_read_only = 0; |
|||
connection backup; |
|||
BACKUP STAGE FLUSH; |
|||
connection con11; |
|||
# Between BACKUP STAGE FLUSH and BLOCK_COMMIT: |
|||
# Connection con11 not holding the backup lock cannot |
|||
# LOCK WRITE non transactional table. |
|||
LOCK TABLES t_permanent_innodb READ; |
|||
LOCK TABLES t_permanent_myisam READ; |
|||
LOCK TABLES t_permanent_innodb WRITE; |
|||
LOCK TABLES t_permanent_myisam WRITE; |
|||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction |
|||
UNLOCK TABLES; |
|||
SET GLOBAL tx_read_only = 1; |
|||
SET GLOBAL tx_read_only = 0; |
|||
connection backup; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
connection con11; |
|||
# Between BACKUP STAGE FLUSH and BLOCK_COMMIT: |
|||
# Connection con11 not holding the backup lock cannot |
|||
# LOCK WRITE transactional or non transactional table. |
|||
LOCK TABLES t_permanent_innodb READ; |
|||
LOCK TABLES t_permanent_myisam READ; |
|||
LOCK TABLES t_permanent_innodb WRITE; |
|||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction |
|||
LOCK TABLES t_permanent_myisam WRITE; |
|||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction |
|||
UNLOCK TABLES; |
|||
SET GLOBAL tx_read_only = 1; |
|||
SET GLOBAL tx_read_only = 0; |
|||
connection backup; |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
connection con11; |
|||
# Between BACKUP BLOCK_COMMIT FLUSH and END: |
|||
# Connection con11 not holding the backup lock cannot |
|||
# LOCK WRITE transactional or non transactional table. |
|||
LOCK TABLES t_permanent_innodb READ; |
|||
LOCK TABLES t_permanent_myisam READ; |
|||
LOCK TABLES t_permanent_innodb WRITE; |
|||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction |
|||
LOCK TABLES t_permanent_myisam WRITE; |
|||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction |
|||
UNLOCK TABLES; |
|||
SET GLOBAL tx_read_only = 1; |
|||
SET GLOBAL tx_read_only = 0; |
|||
connection backup; |
|||
BACKUP STAGE END; |
|||
DROP TABLE t_permanent_innodb; |
|||
DROP TABLE t_permanent_myisam; |
|||
# |
|||
# Log tables |
|||
# |
|||
connection backup; |
|||
SET @old_general_log = @@general_log; |
|||
SET @old_slow_query_log = @@slow_query_log; |
|||
SET @old_log_output = @@log_output; |
|||
SET GLOBAL log_output = 'TABLE'; |
|||
SET GLOBAL general_log = ON; |
|||
SET GLOBAL slow_query_log = ON; |
|||
connection con11; |
|||
SET @old_long_query_time = @@SESSION.long_query_time; |
|||
SET SESSION long_query_time = 0; |
|||
connection backup; |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE FLUSH; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
connection con11; |
|||
SELECT 1; |
|||
1 |
|||
1 |
|||
connection backup; |
|||
SELECT 1; |
|||
1 |
|||
1 |
|||
connection con11; |
|||
SET SESSION long_query_time = @old_long_query_time; |
|||
connection backup; |
|||
BACKUP STAGE END; |
|||
SET GLOBAL log_output = @old_log_output; |
|||
SET GLOBAL slow_query_log = @old_slow_query_log; |
|||
SET GLOBAL general_log = @old_general_log; |
|||
#----------------------------------------------------------------------- |
|||
# Cleanup |
|||
#----------------------------------------------------------------------- |
|||
SET GLOBAL lock_wait_timeout = <old_lock_wait_timeout>; |
|||
disconnect con2; |
|||
disconnect con11; |
|||
disconnect con12; |
|||
disconnect backup; |
|||
connection default; |
@ -0,0 +1,385 @@ |
|||
######################################################################## |
|||
# Test what is locked in each stage for LOCK FOR BACKUP (MDEV-5336) |
|||
######################################################################## |
|||
|
|||
--source include/not_embedded.inc |
|||
# A transactional engine |
|||
--source include/have_innodb.inc |
|||
--source include/have_metadata_lock_info.inc |
|||
# As non transactional engine we have MyISAM anyway. |
|||
|
|||
# Save the initial number of concurrent sessions. |
|||
--source include/count_sessions.inc |
|||
|
|||
let $old_lock_wait_timeout = `SELECT @@global.lock_wait_timeout`; |
|||
|
|||
--echo #----------------------------------------------------------------------- |
|||
--echo # Multi-threaded tests |
|||
--echo #----------------------------------------------------------------------- |
|||
--echo # Show that only one connection can hold the backup lock. |
|||
|
|||
--connection default |
|||
let $default_id= `SELECT CONNECTION_ID()`; |
|||
BACKUP STAGE START; |
|||
|
|||
# con1, root high privileged user |
|||
--connect(con1,localhost,root,,) |
|||
let $con1_id= `SELECT CONNECTION_ID()`; |
|||
--error ER_LOCK_WAIT_TIMEOUT |
|||
SET STATEMENT lock_wait_timeout=0 FOR BACKUP STAGE START; |
|||
send BACKUP STAGE START; |
|||
--connection default |
|||
|
|||
--echo # Show that the connection con1 has to wait for the backup lock and the |
|||
--echo # corresponding representation within the processlist. |
|||
|
|||
--replace_result $con1_id <con1_id> |
|||
|
|||
eval SET @con1_id = $con1_id; |
|||
# Output expected here is |
|||
# ID USER COMMAND STATE INFO INFO_BINARY |
|||
# <con1_id> root Query Waiting for backup lock BACKUP STAGE START BACKUP STAGE START |
|||
let $wait_condition= |
|||
SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST |
|||
WHERE STATE = "Waiting for backup lock" and INFO = "BACKUP STAGE START"; |
|||
--source include/wait_condition.inc |
|||
--replace_column 1 <con1_id> |
|||
eval |
|||
SELECT ID, USER, COMMAND, STATE, INFO, STAGE, MAX_STAGE, INFO_BINARY |
|||
FROM information_schema.processlist WHERE id = @con1_id; |
|||
# con1 uses @@global.lock_wait_timeout |
|||
|
|||
BACKUP STAGE END; |
|||
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; |
|||
|
|||
--connection con1 |
|||
--echo # The connection default has removed the backup lock. |
|||
--echo # And so the current connection con1 can reap for its BACKUP STAGE START |
|||
--reap |
|||
|
|||
# con2, root high privileged user |
|||
--connect(con2,localhost,root,,) |
|||
let $con2_id= `SELECT CONNECTION_ID()`; |
|||
--echo # The connection con2 cannot continue the work of con1 by setting the |
|||
--echo # next BACKUP STAGE FLUSH. |
|||
--error ER_BACKUP_NOT_RUNNING |
|||
BACKUP STAGE FLUSH; |
|||
send |
|||
BACKUP STAGE START; |
|||
|
|||
--connection default |
|||
--replace_result $con2_id <con2_id> |
|||
eval SET @con2_id = $con2_id; |
|||
--echo # Connection con2 waits for the backup lock held by con1. |
|||
--source include/wait_condition.inc |
|||
--replace_column 1 <con2_id> |
|||
eval |
|||
SELECT ID, USER, COMMAND, STATE, INFO, STAGE, MAX_STAGE, INFO_BINARY |
|||
FROM information_schema.processlist WHERE id = @con2_id; |
|||
|
|||
--disconnect con1 |
|||
|
|||
--connection con2 |
|||
--echo # Connection con1 frees the backup lock held by disconnecting. |
|||
--echo # So connection con2 gets the backup lock. |
|||
--reap |
|||
|
|||
--connect(con3,localhost,root,,) |
|||
let $con3_id= `SELECT CONNECTION_ID()`; |
|||
send |
|||
BACKUP STAGE START; |
|||
|
|||
--connection default |
|||
--replace_result $con3_id <con3_id> |
|||
eval SET @con3_id = $con3_id; |
|||
--echo # Connection con3 waits for the backup lock held by con2. |
|||
--source include/wait_condition.inc |
|||
--replace_column 1 <con3_id> |
|||
eval |
|||
SELECT ID, USER, COMMAND, STATE, INFO, STAGE, MAX_STAGE, INFO_BINARY |
|||
FROM information_schema.processlist WHERE id = @con3_id; |
|||
KILL CONNECTION @con2_id; |
|||
|
|||
--connection con3 |
|||
--echo # Connection con2 frees the backup lock held by getting killed. |
|||
--echo # So connection con3 gets the backup lock. |
|||
--reap |
|||
BACKUP STAGE END; |
|||
disconnect con3; |
|||
--connection default |
|||
|
|||
CREATE TABLE t_permanent_innodb (col1 INT) ENGINE = InnoDB; |
|||
INSERT INTO t_permanent_innodb SET col1 = 1; |
|||
CREATE TABLE t_permanent_myisam (col1 INT) ENGINE = MyISAM; |
|||
INSERT INTO t_permanent_myisam SET col1 = 1; |
|||
|
|||
# backup : Try the BACKUP STAGE sequence |
|||
# con11 : Try DDL + DML with AUTOCOMMIT = 0 |
|||
# con12 : Try DML with AUTOCOMMIT = 1 |
|||
--connect(backup,localhost,root,,) |
|||
--connect(con11,localhost,root,,) |
|||
SET AUTOCOMMIT = 0; |
|||
set session lock_wait_timeout=0; |
|||
--connect(con12,localhost,root,,) |
|||
SET AUTOCOMMIT = 1; |
|||
|
|||
--echo # Between (connection default) BACKUP STAGE START and FLUSH |
|||
--echo # no restrictions for concurrent sessions regarding DDL or DML |
|||
--echo # affecting transactional/non transactional permanent tables. |
|||
|
|||
--connection backup |
|||
BACKUP STAGE START; |
|||
--connection con11 |
|||
UPDATE t_permanent_innodb SET col1 = 2; |
|||
UPDATE t_permanent_myisam SET col1 = 2; |
|||
SELECT COUNT(*) FROM t_permanent_innodb; |
|||
HANDLER t_permanent_innodb OPEN; |
|||
HANDLER t_permanent_innodb READ FIRST; |
|||
HANDLER t_permanent_innodb CLOSE; |
|||
SELECT COUNT(*) FROM t_permanent_myisam; |
|||
HANDLER t_permanent_myisam OPEN; |
|||
HANDLER t_permanent_myisam READ FIRST; |
|||
HANDLER t_permanent_myisam CLOSE; |
|||
CREATE TABLE t_con1_innodb (col1 INT) ENGINE = InnoDB; |
|||
CREATE TABLE t_con1_myisam (col1 INT) ENGINE = InnoDB; |
|||
ALTER TABLE t_permanent_innodb ADD COLUMN col2 INT; |
|||
ALTER TABLE t_permanent_myisam ADD COLUMN col2 INT; |
|||
CREATE OR REPLACE VIEW v_some_view AS SELECT * FROM t_permanent_innodb; |
|||
CREATE OR REPLACE VIEW v_some_view AS SELECT * FROM t_permanent_myisam; |
|||
--connection con12 |
|||
UPDATE t_permanent_innodb SET col1 = 3; |
|||
UPDATE t_permanent_myisam SET col1 = 3; |
|||
|
|||
--echo # Between (connection default) BACKUP STAGE FLUSH and BLOCK_DDL |
|||
--echo # concurrent sessions |
|||
--echo # - can change transactional permanent tables with DDL and DML |
|||
--echo # - can run DROP/CREATE transactional/non transactional TABLE |
|||
--echo # - cannot modify non transactional permanent tables with DDL or DML |
|||
|
|||
--connection backup |
|||
BACKUP STAGE FLUSH; |
|||
--connection con11 |
|||
UPDATE t_permanent_innodb SET col1 = 4; |
|||
--error ER_LOCK_WAIT_TIMEOUT |
|||
SET STATEMENT lock_wait_timeout=0 FOR UPDATE t_permanent_myisam SET col1 = 4; |
|||
SELECT COUNT(*) FROM t_permanent_innodb; |
|||
HANDLER t_permanent_innodb OPEN; |
|||
HANDLER t_permanent_innodb READ FIRST; |
|||
HANDLER t_permanent_innodb CLOSE; |
|||
SELECT COUNT(*) FROM t_permanent_myisam; |
|||
HANDLER t_permanent_myisam OPEN; |
|||
HANDLER t_permanent_myisam READ FIRST; |
|||
HANDLER t_permanent_myisam CLOSE; |
|||
DROP TABLE t_con1_innodb; |
|||
DROP TABLE t_con1_myisam; |
|||
CREATE TABLE t_con1_innodb (col1 INT) ENGINE = InnoDB; |
|||
CREATE TABLE t_con1_myisam (col1 INT) ENGINE = InnoDB; |
|||
ALTER TABLE t_permanent_innodb ADD COLUMN col3 INT; |
|||
--error ER_LOCK_WAIT_TIMEOUT |
|||
SET STATEMENT lock_wait_timeout=0 FOR ALTER TABLE t_permanent_myisam ADD COLUMN col3 INT; |
|||
CREATE OR REPLACE VIEW v_some_view AS SELECT * FROM t_permanent_innodb; |
|||
CREATE OR REPLACE VIEW v_some_view AS SELECT * FROM t_permanent_myisam; |
|||
--connection con12 |
|||
UPDATE t_permanent_innodb SET col1 = 5; |
|||
|
|||
|
|||
--echo # Between (connection default) BACKUP STAGE BLOCK_DDL and BLOCK_COMMIT |
|||
--echo # concurrent sessions |
|||
--echo # - can change transactional permanent tables with DML |
|||
--echo # - cannot run DDL |
|||
--echo # - cannot change non transactional permanent tables with DML |
|||
|
|||
--connection backup |
|||
BACKUP STAGE BLOCK_DDL; |
|||
--connection con11 |
|||
|
|||
UPDATE t_permanent_innodb SET col1 = 6; |
|||
--error ER_LOCK_WAIT_TIMEOUT |
|||
UPDATE t_permanent_myisam SET col1 = 6; |
|||
SELECT COUNT(*) FROM t_permanent_innodb; |
|||
HANDLER t_permanent_innodb OPEN; |
|||
HANDLER t_permanent_innodb READ FIRST; |
|||
HANDLER t_permanent_innodb CLOSE; |
|||
SELECT COUNT(*) FROM t_permanent_myisam; |
|||
HANDLER t_permanent_myisam OPEN; |
|||
HANDLER t_permanent_myisam READ FIRST; |
|||
HANDLER t_permanent_myisam CLOSE; |
|||
--error ER_LOCK_WAIT_TIMEOUT |
|||
DROP TABLE t_con1_innodb; |
|||
--error ER_LOCK_WAIT_TIMEOUT |
|||
CREATE TABLE throw_away (col1 INT) ENGINE = InnoDB; |
|||
--error ER_LOCK_WAIT_TIMEOUT |
|||
ALTER TABLE t_permanent_innodb ADD COLUMN col4 INT; |
|||
--error ER_LOCK_WAIT_TIMEOUT |
|||
CREATE OR REPLACE VIEW v_some_view AS SELECT * FROM t_permanent_innodb; |
|||
--error ER_LOCK_WAIT_TIMEOUT |
|||
CREATE OR REPLACE VIEW v_some_view AS SELECT * FROM t_permanent_myisam; |
|||
--connection con12 |
|||
UPDATE t_permanent_innodb SET col1 = 7; |
|||
|
|||
|
|||
--echo # Between (connection default) BACKUP STAGE BLOCK_COMMIT and END |
|||
--echo # concurrent sessions |
|||
--echo # - can change transactional permanent tables with DML |
|||
--echo # - cannot run DDL |
|||
--echo # - cannot change non transactional permanent tables with DML |
|||
|
|||
--connection backup |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
--connection con11 |
|||
UPDATE t_permanent_innodb SET col1 = 8; |
|||
--error ER_LOCK_WAIT_TIMEOUT |
|||
UPDATE t_permanent_myisam SET col1 = 8; |
|||
SELECT COUNT(*) FROM t_permanent_innodb; |
|||
HANDLER t_permanent_innodb OPEN; |
|||
HANDLER t_permanent_innodb READ FIRST; |
|||
HANDLER t_permanent_innodb CLOSE; |
|||
SELECT COUNT(*) FROM t_permanent_myisam; |
|||
HANDLER t_permanent_myisam OPEN; |
|||
HANDLER t_permanent_myisam READ FIRST; |
|||
HANDLER t_permanent_myisam CLOSE; |
|||
--error ER_LOCK_WAIT_TIMEOUT |
|||
DROP TABLE t_con1_innodb; |
|||
--error ER_LOCK_WAIT_TIMEOUT |
|||
DROP TABLE t_con1_myisam; |
|||
--connection con12 |
|||
--error ER_LOCK_WAIT_TIMEOUT |
|||
SET STATEMENT lock_wait_timeout=0 FOR UPDATE t_permanent_innodb SET col1 = 9; |
|||
|
|||
--connection backup |
|||
BACKUP STAGE END; |
|||
--connection con11 |
|||
COMMIT; |
|||
SELECT * FROM t_permanent_innodb ORDER BY col1; |
|||
SELECT * FROM t_permanent_myisam ORDER BY col1; |
|||
SET AUTOCOMMIT = 0; |
|||
SET GLOBAL tx_read_only = 1; |
|||
--connection con12 |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE END; |
|||
SET GLOBAL tx_read_only = 0; |
|||
DROP VIEW v_some_view; |
|||
DROP TABLE t_con1_innodb; |
|||
DROP TABLE t_con1_myisam; |
|||
|
|||
--echo # Connection backup holds the backup log and is on some stage. |
|||
--echo # Connection con11 tries to LOCK TABLEs or to set read_only. |
|||
|
|||
--connection backup |
|||
BACKUP STAGE START; |
|||
--connection con11 |
|||
--echo # Between BACKUP STAGE START and FLUSH: |
|||
--echo # No restrictions for other connection around LOCK TABLES or read-only. |
|||
LOCK TABLES t_permanent_innodb READ; |
|||
LOCK TABLES t_permanent_myisam READ; |
|||
LOCK TABLES t_permanent_innodb WRITE; |
|||
LOCK TABLES t_permanent_myisam WRITE; |
|||
UNLOCK TABLES; |
|||
SET GLOBAL tx_read_only = 1; |
|||
SET GLOBAL tx_read_only = 0; |
|||
--connection backup |
|||
BACKUP STAGE FLUSH; |
|||
--connection con11 |
|||
--echo # Between BACKUP STAGE FLUSH and BLOCK_COMMIT: |
|||
--echo # Connection con11 not holding the backup lock cannot |
|||
--echo # LOCK WRITE non transactional table. |
|||
LOCK TABLES t_permanent_innodb READ; |
|||
LOCK TABLES t_permanent_myisam READ; |
|||
LOCK TABLES t_permanent_innodb WRITE; |
|||
--error ER_LOCK_WAIT_TIMEOUT |
|||
LOCK TABLES t_permanent_myisam WRITE; |
|||
UNLOCK TABLES; |
|||
SET GLOBAL tx_read_only = 1; |
|||
SET GLOBAL tx_read_only = 0; |
|||
--connection backup |
|||
BACKUP STAGE BLOCK_DDL; |
|||
--connection con11 |
|||
--echo # Between BACKUP STAGE FLUSH and BLOCK_COMMIT: |
|||
--echo # Connection con11 not holding the backup lock cannot |
|||
--echo # LOCK WRITE transactional or non transactional table. |
|||
LOCK TABLES t_permanent_innodb READ; |
|||
LOCK TABLES t_permanent_myisam READ; |
|||
--error ER_LOCK_WAIT_TIMEOUT |
|||
LOCK TABLES t_permanent_innodb WRITE; |
|||
--error ER_LOCK_WAIT_TIMEOUT |
|||
LOCK TABLES t_permanent_myisam WRITE; |
|||
UNLOCK TABLES; |
|||
SET GLOBAL tx_read_only = 1; |
|||
SET GLOBAL tx_read_only = 0; |
|||
--connection backup |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
--connection con11 |
|||
--echo # Between BACKUP BLOCK_COMMIT FLUSH and END: |
|||
--echo # Connection con11 not holding the backup lock cannot |
|||
--echo # LOCK WRITE transactional or non transactional table. |
|||
LOCK TABLES t_permanent_innodb READ; |
|||
LOCK TABLES t_permanent_myisam READ; |
|||
--error ER_LOCK_WAIT_TIMEOUT |
|||
LOCK TABLES t_permanent_innodb WRITE; |
|||
--error ER_LOCK_WAIT_TIMEOUT |
|||
LOCK TABLES t_permanent_myisam WRITE; |
|||
UNLOCK TABLES; |
|||
SET GLOBAL tx_read_only = 1; |
|||
SET GLOBAL tx_read_only = 0; |
|||
--connection backup |
|||
BACKUP STAGE END; |
|||
|
|||
DROP TABLE t_permanent_innodb; |
|||
DROP TABLE t_permanent_myisam; |
|||
|
|||
--echo # |
|||
--echo # Log tables |
|||
--echo # |
|||
|
|||
--connection backup |
|||
|
|||
SET @old_general_log = @@general_log; |
|||
SET @old_slow_query_log = @@slow_query_log; |
|||
SET @old_log_output = @@log_output; |
|||
|
|||
SET GLOBAL log_output = 'TABLE'; |
|||
SET GLOBAL general_log = ON; |
|||
SET GLOBAL slow_query_log = ON; |
|||
|
|||
|
|||
--connection con11 |
|||
SET @old_long_query_time = @@SESSION.long_query_time; |
|||
SET SESSION long_query_time = 0; |
|||
|
|||
--connection backup |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE FLUSH; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
|
|||
--connection con11 |
|||
SELECT 1; |
|||
|
|||
--connection backup |
|||
SELECT 1; |
|||
|
|||
--connection con11 |
|||
SET SESSION long_query_time = @old_long_query_time; |
|||
|
|||
--connection backup |
|||
BACKUP STAGE END; |
|||
|
|||
SET GLOBAL log_output = @old_log_output; |
|||
SET GLOBAL slow_query_log = @old_slow_query_log; |
|||
SET GLOBAL general_log = @old_general_log; |
|||
|
|||
--echo #----------------------------------------------------------------------- |
|||
--echo # Cleanup |
|||
--echo #----------------------------------------------------------------------- |
|||
|
|||
--replace_result $old_lock_wait_timeout <old_lock_wait_timeout> |
|||
eval |
|||
SET GLOBAL lock_wait_timeout = $old_lock_wait_timeout; |
|||
|
|||
--disconnect con2 |
|||
--disconnect con11 |
|||
--disconnect con12 |
|||
--disconnect backup |
|||
|
|||
--connection default |
|||
--source include/wait_until_count_sessions.inc |
@ -0,0 +1,163 @@ |
|||
#----------------------------------------------------------------------- |
|||
# Basic syntax checks |
|||
#----------------------------------------------------------------------- |
|||
# Check existing BACKUP STAGE statements in the sequence to be used. |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE FLUSH; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
BACKUP STAGE END; |
|||
# Check invalid variants of BACKUP .... syntax. |
|||
BACKUP LOG; |
|||
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'LOG' at line 1 |
|||
BACKUP LOCK; |
|||
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'LOCK' at line 1 |
|||
BACKUP STAGE; |
|||
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '' at line 1 |
|||
BACKUP STAGE LOCK; |
|||
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'LOCK' at line 1 |
|||
BACKUP STAGE not_existing; |
|||
ERROR HY000: Unknown backup stage: 'not_existing'. Stage should be one of START, FLUSH, BLOCK_DDL, BLOCK_COMMIT or END |
|||
#----------------------------------------------------------------------- |
|||
# BACKUP STAGE statements in various orders. |
|||
#----------------------------------------------------------------------- |
|||
# All BACKUP STAGE statements != 'BACKUP STAGE START' expect that a |
|||
# backup lock (generated by BACKUP STAGE START) already exists. |
|||
# |
|||
backup stage start; |
|||
backup stage flush; |
|||
backup stage start; |
|||
ERROR HY000: Backup stage 'START' is same or before current backup stage 'FLUSH' |
|||
backup stage start; |
|||
ERROR HY000: Backup stage 'START' is same or before current backup stage 'FLUSH' |
|||
backup stage block_commit; |
|||
backup stage flush; |
|||
ERROR HY000: Backup stage 'FLUSH' is same or before current backup stage 'BLOCK_COMMIT' |
|||
backup stage flush; |
|||
ERROR HY000: Backup stage 'FLUSH' is same or before current backup stage 'BLOCK_COMMIT' |
|||
backup stage end; |
|||
backup stage flush; |
|||
ERROR HY000: You must start backup with "BACKUP STAGE START" |
|||
BACKUP STAGE END; |
|||
ERROR HY000: You must start backup with "BACKUP STAGE START" |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
ERROR HY000: You must start backup with "BACKUP STAGE START" |
|||
BACKUP STAGE BLOCK_DDL; |
|||
ERROR HY000: You must start backup with "BACKUP STAGE START" |
|||
BACKUP STAGE FLUSH; |
|||
ERROR HY000: You must start backup with "BACKUP STAGE START" |
|||
# Ordered "give up" with 'BACKUP STAGE END' because of whatever reason. |
|||
# Some existing backup lock assumed a 'BACKUP STAGE END' is allowed in |
|||
# every situation. |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE END; |
|||
#---- |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE FLUSH; |
|||
BACKUP STAGE END; |
|||
#---- |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE FLUSH; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
BACKUP STAGE END; |
|||
# Orders with BACKUP STAGE FLUSH omitted. |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
BACKUP STAGE END; |
|||
#---- |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
BACKUP STAGE END; |
|||
# Orders with BACKUP STAGE BLOCK_DDL omitted. |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE FLUSH; |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
BACKUP STAGE END; |
|||
# Orders with BACKUP STAGE BLOCK_COMMIT omitted. |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE FLUSH; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
BACKUP STAGE END; |
|||
# Orders with doubled BACKUP STAGE statements. |
|||
# We get an error but that seems to have no bad impact on the state. |
|||
# And so we are allowed to go on with BACKUP STAGE statements. |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE START; |
|||
ERROR HY000: Backup stage 'START' is same or before current backup stage 'START' |
|||
BACKUP STAGE FLUSH; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
BACKUP STAGE END; |
|||
#---- |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE FLUSH; |
|||
BACKUP STAGE FLUSH; |
|||
ERROR HY000: Backup stage 'FLUSH' is same or before current backup stage 'FLUSH' |
|||
BACKUP STAGE END; |
|||
#---- |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE FLUSH; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
ERROR HY000: Backup stage 'BLOCK_DDL' is same or before current backup stage 'BLOCK_DDL' |
|||
BACKUP STAGE END; |
|||
#---- |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE FLUSH; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
ERROR HY000: Backup stage 'BLOCK_COMMIT' is same or before current backup stage 'BLOCK_COMMIT' |
|||
BACKUP STAGE END; |
|||
# Scrambled orders. |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE FLUSH; |
|||
BACKUP STAGE START; |
|||
ERROR HY000: Backup stage 'START' is same or before current backup stage 'FLUSH' |
|||
BACKUP STAGE BLOCK_DDL; |
|||
BACKUP STAGE START; |
|||
ERROR HY000: Backup stage 'START' is same or before current backup stage 'BLOCK_DDL' |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
BACKUP STAGE START; |
|||
ERROR HY000: Backup stage 'START' is same or before current backup stage 'BLOCK_COMMIT' |
|||
BACKUP STAGE END; |
|||
#---- |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE FLUSH; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
BACKUP STAGE FLUSH; |
|||
ERROR HY000: Backup stage 'FLUSH' is same or before current backup stage 'BLOCK_DDL' |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
BACKUP STAGE FLUSH; |
|||
ERROR HY000: Backup stage 'FLUSH' is same or before current backup stage 'BLOCK_COMMIT' |
|||
BACKUP STAGE END; |
|||
#---- |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE FLUSH; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
ERROR HY000: Backup stage 'BLOCK_DDL' is same or before current backup stage 'BLOCK_COMMIT' |
|||
BACKUP STAGE END; |
|||
#---- |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
BACKUP STAGE FLUSH; |
|||
ERROR HY000: Backup stage 'FLUSH' is same or before current backup stage 'BLOCK_DDL' |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
BACKUP STAGE END; |
|||
#---- |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE FLUSH; |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
ERROR HY000: Backup stage 'BLOCK_DDL' is same or before current backup stage 'BLOCK_COMMIT' |
|||
BACKUP STAGE END; |
|||
# |
|||
# Check Oracle syntax |
|||
# |
|||
set SQL_MODE=Oracle; |
|||
backup stage start; |
|||
backup stage end; |
|||
set SQL_MODE=default; |
@ -0,0 +1,181 @@ |
|||
######################################################################## |
|||
# Tests things releated to syntax of BACKUP STAGE (MDEV-5336) |
|||
######################################################################## |
|||
|
|||
--source include/have_innodb.inc |
|||
--source include/have_metadata_lock_info.inc |
|||
|
|||
--echo #----------------------------------------------------------------------- |
|||
--echo # Basic syntax checks |
|||
--echo #----------------------------------------------------------------------- |
|||
|
|||
--echo # Check existing BACKUP STAGE statements in the sequence to be used. |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE FLUSH; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
BACKUP STAGE END; |
|||
|
|||
--echo # Check invalid variants of BACKUP .... syntax. |
|||
--error ER_PARSE_ERROR |
|||
BACKUP LOG; |
|||
--error ER_PARSE_ERROR |
|||
BACKUP LOCK; |
|||
--error ER_PARSE_ERROR |
|||
BACKUP STAGE; |
|||
--error ER_PARSE_ERROR |
|||
BACKUP STAGE LOCK; |
|||
--error ER_BACKUP_UNKNOWN_STAGE |
|||
BACKUP STAGE not_existing; |
|||
|
|||
--echo #----------------------------------------------------------------------- |
|||
--echo # BACKUP STAGE statements in various orders. |
|||
--echo #----------------------------------------------------------------------- |
|||
--echo # All BACKUP STAGE statements != 'BACKUP STAGE START' expect that a |
|||
--echo # backup lock (generated by BACKUP STAGE START) already exists. |
|||
--echo # |
|||
|
|||
backup stage start; |
|||
backup stage flush; |
|||
--error ER_BACKUP_WRONG_STAGE |
|||
backup stage start; |
|||
--error ER_BACKUP_WRONG_STAGE |
|||
backup stage start; |
|||
backup stage block_commit; |
|||
--error ER_BACKUP_WRONG_STAGE |
|||
backup stage flush; |
|||
--error ER_BACKUP_WRONG_STAGE |
|||
backup stage flush; |
|||
backup stage end; |
|||
--error ER_BACKUP_NOT_RUNNING |
|||
backup stage flush; |
|||
--error ER_BACKUP_NOT_RUNNING |
|||
BACKUP STAGE END; |
|||
--error ER_BACKUP_NOT_RUNNING |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
--error ER_BACKUP_NOT_RUNNING |
|||
BACKUP STAGE BLOCK_DDL; |
|||
--error ER_BACKUP_NOT_RUNNING |
|||
BACKUP STAGE FLUSH; |
|||
|
|||
--echo # Ordered "give up" with 'BACKUP STAGE END' because of whatever reason. |
|||
--echo # Some existing backup lock assumed a 'BACKUP STAGE END' is allowed in |
|||
--echo # every situation. |
|||
|
|||
BACKUP STAGE START; |
|||
BACKUP STAGE END; |
|||
--echo #---- |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE FLUSH; |
|||
BACKUP STAGE END; |
|||
--echo #---- |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE FLUSH; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
BACKUP STAGE END; |
|||
--echo # Orders with BACKUP STAGE FLUSH omitted. |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
BACKUP STAGE END; |
|||
--echo #---- |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
BACKUP STAGE END; |
|||
--echo # Orders with BACKUP STAGE BLOCK_DDL omitted. |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE FLUSH; |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
BACKUP STAGE END; |
|||
--echo # Orders with BACKUP STAGE BLOCK_COMMIT omitted. |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE FLUSH; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
BACKUP STAGE END; |
|||
|
|||
--echo # Orders with doubled BACKUP STAGE statements. |
|||
--echo # We get an error but that seems to have no bad impact on the state. |
|||
--echo # And so we are allowed to go on with BACKUP STAGE statements. |
|||
|
|||
BACKUP STAGE START; |
|||
--error ER_BACKUP_WRONG_STAGE |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE FLUSH; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
BACKUP STAGE END; |
|||
--echo #---- |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE FLUSH; |
|||
--error ER_BACKUP_WRONG_STAGE |
|||
BACKUP STAGE FLUSH; |
|||
BACKUP STAGE END; |
|||
--echo #---- |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE FLUSH; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
--error ER_BACKUP_WRONG_STAGE |
|||
BACKUP STAGE BLOCK_DDL; |
|||
BACKUP STAGE END; |
|||
--echo #---- |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE FLUSH; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
--error ER_BACKUP_WRONG_STAGE |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
BACKUP STAGE END; |
|||
|
|||
--echo # Scrambled orders. |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE FLUSH; |
|||
--error ER_BACKUP_WRONG_STAGE |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
--error ER_BACKUP_WRONG_STAGE |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
--error ER_BACKUP_WRONG_STAGE |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE END; |
|||
--echo #---- |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE FLUSH; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
--error ER_BACKUP_WRONG_STAGE |
|||
BACKUP STAGE FLUSH; |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
--error ER_BACKUP_WRONG_STAGE |
|||
BACKUP STAGE FLUSH; |
|||
BACKUP STAGE END; |
|||
--echo #---- |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE FLUSH; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
--error ER_BACKUP_WRONG_STAGE |
|||
BACKUP STAGE BLOCK_DDL; |
|||
BACKUP STAGE END; |
|||
--echo #---- |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE BLOCK_DDL; |
|||
--error ER_BACKUP_WRONG_STAGE |
|||
BACKUP STAGE FLUSH; |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
BACKUP STAGE END; |
|||
--echo #---- |
|||
BACKUP STAGE START; |
|||
BACKUP STAGE FLUSH; |
|||
BACKUP STAGE BLOCK_COMMIT; |
|||
--error ER_BACKUP_WRONG_STAGE |
|||
BACKUP STAGE BLOCK_DDL; |
|||
BACKUP STAGE END; |
|||
|
|||
--echo # |
|||
--echo # Check Oracle syntax |
|||
--echo # |
|||
|
|||
set SQL_MODE=Oracle; |
|||
backup stage start; |
|||
backup stage end; |
|||
set SQL_MODE=default; |
@ -0,0 +1,356 @@ |
|||
/* Copyright (c) 2018, MariaDB Corporation
|
|||
This program is free software; you can redistribute it and/or modify |
|||
it under the terms of the GNU General Public License as published by |
|||
the Free Software Foundation; version 2 of the License. |
|||
|
|||
This program is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
GNU General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU General Public License |
|||
along with this program; if not, write to the Free Software |
|||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ |
|||
|
|||
/*
|
|||
Implementation of BACKUP STAGE, an interface for external backup tools. |
|||
|
|||
TODO: |
|||
- At backup_start() we call ha_prepare_for_backup() for all active |
|||
storage engines. If someone tries to load a new storage engine |
|||
that requires prepare_for_backup() for it to work, that storage |
|||
engines has to be blocked from loading until backup finishes. |
|||
As we currently don't have any loadable storage engine that |
|||
requires this and we have not implemented that part. |
|||
This can easily be done by adding a |
|||
PLUGIN_CANT_BE_LOADED_WHILE_BACKUP_IS_RUNNING flag to |
|||
maria_declare_plugin and check this before calling |
|||
plugin_initialize() |
|||
*/ |
|||
|
|||
#include "mariadb.h"
|
|||
#include "sql_class.h"
|
|||
#include "sql_base.h" // flush_tables
|
|||
#include "sql_insert.h" // kill_delayed_threads
|
|||
#include "sql_handler.h" // mysql_ha_cleanup_no_free
|
|||
#include <my_sys.h>
|
|||
|
|||
static const char *stage_names[]= |
|||
{"START", "FLUSH", "BLOCK_DDL", "BLOCK_COMMIT", "END", 0}; |
|||
|
|||
TYPELIB backup_stage_names= |
|||
{ array_elements(stage_names)-1, "", stage_names, 0 }; |
|||
|
|||
static MDL_ticket *backup_flush_ticket; |
|||
|
|||
static bool backup_start(THD *thd); |
|||
static bool backup_flush(THD *thd); |
|||
static bool backup_block_ddl(THD *thd); |
|||
static bool backup_block_commit(THD *thd); |
|||
|
|||
/**
|
|||
Run next stage of backup |
|||
*/ |
|||
|
|||
void backup_init() |
|||
{ |
|||
backup_flush_ticket= 0; |
|||
} |
|||
|
|||
bool run_backup_stage(THD *thd, backup_stages stage) |
|||
{ |
|||
backup_stages next_stage; |
|||
DBUG_ENTER("run_backup_stage"); |
|||
|
|||
if (thd->current_backup_stage == BACKUP_FINISHED) |
|||
{ |
|||
if (stage != BACKUP_START) |
|||
{ |
|||
my_error(ER_BACKUP_NOT_RUNNING, MYF(0)); |
|||
DBUG_RETURN(1); |
|||
} |
|||
next_stage= BACKUP_START; |
|||
} |
|||
else |
|||
{ |
|||
if ((uint) thd->current_backup_stage >= (uint) stage) |
|||
{ |
|||
my_error(ER_BACKUP_WRONG_STAGE, MYF(0), stage_names[stage], |
|||
stage_names[thd->current_backup_stage]); |
|||
DBUG_RETURN(1); |
|||
} |
|||
if (stage == BACKUP_END) |
|||
{ |
|||
/*
|
|||
If end is given, jump directly to stage end. This is to allow one |
|||
to abort backup quickly. |
|||
*/ |
|||
next_stage= stage; |
|||
} |
|||
else |
|||
{ |
|||
/* Go trough all not used stages until we reach 'stage' */ |
|||
next_stage= (backup_stages) ((uint) thd->current_backup_stage + 1); |
|||
} |
|||
} |
|||
|
|||
do |
|||
{ |
|||
bool res; |
|||
backup_stages previous_stage= thd->current_backup_stage; |
|||
thd->current_backup_stage= next_stage; |
|||
switch (next_stage) { |
|||
case BACKUP_START: |
|||
if (!(res= backup_start(thd))) |
|||
break; |
|||
/* Reset backup stage to start for next backup try */ |
|||
previous_stage= BACKUP_FINISHED; |
|||
break; |
|||
case BACKUP_FLUSH: |
|||
res= backup_flush(thd); |
|||
break; |
|||
case BACKUP_WAIT_FOR_FLUSH: |
|||
res= backup_block_ddl(thd); |
|||
break; |
|||
case BACKUP_LOCK_COMMIT: |
|||
res= backup_block_commit(thd); |
|||
break; |
|||
case BACKUP_END: |
|||
res= backup_end(thd); |
|||
break; |
|||
case BACKUP_FINISHED: |
|||
DBUG_ASSERT(0); |
|||
res= 0; |
|||
} |
|||
if (res) |
|||
{ |
|||
thd->current_backup_stage= previous_stage; |
|||
my_error(ER_BACKUP_STAGE_FAILED, MYF(0), stage_names[(uint) stage]); |
|||
DBUG_RETURN(1); |
|||
} |
|||
next_stage= (backup_stages) ((uint) next_stage + 1); |
|||
} while ((uint) next_stage <= (uint) stage); |
|||
|
|||
DBUG_RETURN(0); |
|||
} |
|||
|
|||
|
|||
/**
|
|||
Start the backup |
|||
|
|||
- Wait for previous backup to stop running |
|||
- Start service to log changed tables (TODO) |
|||
- Block purge of redo files (Required at least for Aria) |
|||
- An handler can optionally do a checkpoint of all tables, |
|||
to speed up the recovery stage of the backup. |
|||
*/ |
|||
|
|||
static bool backup_start(THD *thd) |
|||
{ |
|||
MDL_request mdl_request; |
|||
DBUG_ENTER("backup_start"); |
|||
|
|||
thd->current_backup_stage= BACKUP_FINISHED; // For next test
|
|||
if (thd->has_read_only_protection()) |
|||
DBUG_RETURN(1); |
|||
thd->current_backup_stage= BACKUP_START; |
|||
|
|||
if (thd->locked_tables_mode) |
|||
{ |
|||
my_error(ER_LOCK_OR_ACTIVE_TRANSACTION, MYF(0)); |
|||
DBUG_RETURN(1); |
|||
} |
|||
|
|||
mdl_request.init(MDL_key::BACKUP, "", "", MDL_BACKUP_START, MDL_EXPLICIT); |
|||
if (thd->mdl_context.acquire_lock(&mdl_request, |
|||
thd->variables.lock_wait_timeout)) |
|||
DBUG_RETURN(1); |
|||
|
|||
backup_flush_ticket= mdl_request.ticket; |
|||
|
|||
ha_prepare_for_backup(); |
|||
DBUG_RETURN(0); |
|||
} |
|||
|
|||
/**
|
|||
backup_flush() |
|||
|
|||
- FLUSH all changes for not active non transactional tables, except |
|||
for statistics and log tables. Close the tables, to ensure they |
|||
are marked as closed after backup. |
|||
|
|||
- BLOCK all NEW write locks for all non transactional tables |
|||
(except statistics and log tables). Already granted locks are |
|||
not affected (Running statements with non transaction tables will |
|||
continue running). |
|||
|
|||
- The following DDL's doesn't have to be blocked as they can't set |
|||
the table in a non consistent state: |
|||
CREATE, RENAME, DROP |
|||
*/ |
|||
|
|||
static bool backup_flush(THD *thd) |
|||
{ |
|||
DBUG_ENTER("backup_flush"); |
|||
/*
|
|||
Lock all non transactional normal tables to be used in new DML's |
|||
*/ |
|||
if (thd->mdl_context.upgrade_shared_lock(backup_flush_ticket, |
|||
MDL_BACKUP_FLUSH, |
|||
thd->variables.lock_wait_timeout)) |
|||
DBUG_RETURN(1); |
|||
|
|||
/*
|
|||
Free unused tables and table shares so that mariabackup knows what |
|||
is safe to copy |
|||
*/ |
|||
tc_purge(false); |
|||
tdc_purge(true); |
|||
|
|||
DBUG_RETURN(0); |
|||
} |
|||
|
|||
/**
|
|||
backup_block_ddl() |
|||
|
|||
- Kill all insert delay handlers, to ensure that all non transactional |
|||
tables are closed (can be improved in the future). |
|||
|
|||
- Close handlers as other threads may wait for these, which can cause deadlocks. |
|||
|
|||
- Wait for all statements using write locked non-transactional tables to end. |
|||
|
|||
- Mark all not used active non transactional tables (except |
|||
statistics and log tables) to be closed with |
|||
handler->extra(HA_EXTRA_FLUSH) |
|||
|
|||
- Block TRUNCATE TABLE, CREATE TABLE, DROP TABLE and RENAME |
|||
TABLE. Block also start of a new ALTER TABLE and the final rename |
|||
phase of ALTER TABLE. Running ALTER TABLES are not blocked. Both normal |
|||
and inline ALTER TABLE'S should be blocked when copying is completed but |
|||
before final renaming of the tables / new table is activated. |
|||
This will probably require a callback from the InnoDB code. |
|||
*/ |
|||
|
|||
static bool backup_block_ddl(THD *thd) |
|||
{ |
|||
DBUG_ENTER("backup_block_ddl"); |
|||
|
|||
kill_delayed_threads(); |
|||
mysql_ha_cleanup_no_free(thd); |
|||
|
|||
/* Wait until all non trans statements has ended */ |
|||
if (thd->mdl_context.upgrade_shared_lock(backup_flush_ticket, |
|||
MDL_BACKUP_WAIT_FLUSH, |
|||
thd->variables.lock_wait_timeout)) |
|||
DBUG_RETURN(1); |
|||
|
|||
/*
|
|||
Remove not used tables from the table share. Flush all changes to |
|||
non transaction tables and mark those that are not in use in write |
|||
operations as closed. From backup purposes it's not critical if |
|||
flush_tables() returns an error. It's ok to continue with next |
|||
backup stage even if we got an error. |
|||
*/ |
|||
(void) flush_tables(thd, FLUSH_NON_TRANS_TABLES); |
|||
|
|||
/*
|
|||
block new DDL's, in addition to all previous blocks |
|||
We didn't do this lock above, as we wanted DDL's to be executed while |
|||
we wait for non transactional tables (which may take a while). |
|||
*/ |
|||
if (thd->mdl_context.upgrade_shared_lock(backup_flush_ticket, |
|||
MDL_BACKUP_WAIT_DDL, |
|||
thd->variables.lock_wait_timeout)) |
|||
{ |
|||
/*
|
|||
Could be a timeout. Downgrade lock to what is was before this function |
|||
was called so that this function can be called again |
|||
*/ |
|||
backup_flush_ticket->downgrade_lock(MDL_BACKUP_FLUSH); |
|||
DBUG_RETURN(1); |
|||
} |
|||
DBUG_RETURN(0); |
|||
} |
|||
|
|||
/**
|
|||
backup_block_commit() |
|||
|
|||
Block commits, writes to log and statistics tables and binary log |
|||
*/ |
|||
|
|||
static bool backup_block_commit(THD *thd) |
|||
{ |
|||
DBUG_ENTER("backup_block_commit"); |
|||
if (thd->mdl_context.upgrade_shared_lock(backup_flush_ticket, |
|||
MDL_BACKUP_WAIT_COMMIT, |
|||
thd->variables.lock_wait_timeout)) |
|||
DBUG_RETURN(1); |
|||
flush_tables(thd, FLUSH_SYS_TABLES); |
|||
DBUG_RETURN(0); |
|||
} |
|||
|
|||
/**
|
|||
backup_end() |
|||
|
|||
Safe to run, even if backup has not been run by this thread. |
|||
This is for example the case when a THD ends. |
|||
*/ |
|||
|
|||
bool backup_end(THD *thd) |
|||
{ |
|||
DBUG_ENTER("backup_end"); |
|||
|
|||
if (thd->current_backup_stage != BACKUP_FINISHED) |
|||
{ |
|||
ha_end_backup(); |
|||
thd->current_backup_stage= BACKUP_FINISHED; |
|||
thd->mdl_context.release_lock(backup_flush_ticket); |
|||
} |
|||
DBUG_RETURN(0); |
|||
} |
|||
|
|||
|
|||
/**
|
|||
backup_set_alter_copy_lock() |
|||
|
|||
@param thd |
|||
@param table From table that is part of ALTER TABLE. This is only used |
|||
for the assert to ensure we use this function correctly. |
|||
|
|||
Downgrades the MDL_BACKUP_DDL lock to MDL_BACKUP_ALTER_COPY to allow |
|||
copy of altered table to proceed under MDL_BACKUP_WAIT_DDL |
|||
|
|||
Note that in some case when using non transactional tables, |
|||
the lock may be of type MDL_BACKUP_DML. |
|||
*/ |
|||
|
|||
void backup_set_alter_copy_lock(THD *thd, TABLE *table) |
|||
{ |
|||
MDL_ticket *ticket= thd->mdl_backup_ticket; |
|||
|
|||
/* Ticket maybe NULL in case of LOCK TABLES or for temporary tables*/ |
|||
DBUG_ASSERT(ticket || thd->locked_tables_mode || |
|||
table->s->tmp_table != NO_TMP_TABLE); |
|||
if (ticket) |
|||
ticket->downgrade_lock(MDL_BACKUP_ALTER_COPY); |
|||
} |
|||
|
|||
/**
|
|||
backup_reset_alter_copy_lock |
|||
|
|||
Upgrade the lock of the original ALTER table MDL_BACKUP_DDL |
|||
Can fail if MDL lock was killed |
|||
*/ |
|||
|
|||
bool backup_reset_alter_copy_lock(THD *thd) |
|||
{ |
|||
bool res= 0; |
|||
MDL_ticket *ticket= thd->mdl_backup_ticket; |
|||
|
|||
/* Ticket maybe NULL in case of LOCK TABLES or for temporary tables*/ |
|||
if (ticket) |
|||
res= thd->mdl_context.upgrade_shared_lock(ticket, MDL_BACKUP_DDL, |
|||
thd->variables.lock_wait_timeout); |
|||
return res; |
|||
} |
@ -0,0 +1,31 @@ |
|||
#ifndef BACKUP_INCLUDED |
|||
#define BACKUP_INCLUDED |
|||
/* Copyright (c) 2018, MariaDB Corporation |
|||
|
|||
This program is free software; you can redistribute it and/or modify |
|||
it under the terms of the GNU General Public License as published by |
|||
the Free Software Foundation; version 2 of the License. |
|||
|
|||
This program is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
GNU General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU General Public License |
|||
along with this program; if not, write to the Free Software |
|||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ |
|||
|
|||
enum backup_stages |
|||
{ |
|||
BACKUP_START, BACKUP_FLUSH, BACKUP_WAIT_FOR_FLUSH, BACKUP_LOCK_COMMIT, |
|||
BACKUP_END, BACKUP_FINISHED |
|||
}; |
|||
|
|||
extern TYPELIB backup_stage_names; |
|||
|
|||
void backup_init(); |
|||
bool run_backup_stage(THD *thd, backup_stages stage); |
|||
bool backup_end(THD *thd); |
|||
void backup_set_alter_copy_lock(THD *thd, TABLE *altered_table); |
|||
bool backup_reset_alter_copy_lock(THD *thd); |
|||
#endif /* BACKUP_INCLUDED */ |
Write
Preview
Loading…
Cancel
Save
Reference in new issue