Skip to content

Commit aad0165

Browse files
committed
Added support for BACKUP LOCK / BACKUP UNLOCK
1 parent 3975e22 commit aad0165

File tree

11 files changed

+186
-10
lines changed

11 files changed

+186
-10
lines changed

mysql-test/main/backup_locks.result

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#
2+
# Test lock taken
3+
#
4+
BACKUP LOCK test.t1;
5+
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info;
6+
LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME
7+
MDL_SHARED_HIGH_PRIO Table metadata lock test t1
8+
BACKUP UNLOCK;
9+
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info;
10+
LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME
11+
BACKUP LOCK t1;
12+
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info;
13+
LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME
14+
MDL_SHARED_HIGH_PRIO Table metadata lock test t1
15+
BACKUP UNLOCK;
16+
BACKUP LOCK non_existing.t1;
17+
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info;
18+
LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME
19+
MDL_SHARED_HIGH_PRIO Table metadata lock non_existing t1
20+
BACKUP UNLOCK;
21+
#
22+
# Test that backup lock protects against ddl
23+
#
24+
connect con1,localhost,root,,;
25+
connection default;
26+
create table t1 (a int) engine=innodb;
27+
insert into t1 values (1);
28+
backup lock t1;
29+
select * from t1;
30+
a
31+
1
32+
connection con1;
33+
drop table t1;
34+
connection default;
35+
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info;
36+
LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME
37+
MDL_SHARED_HIGH_PRIO Table metadata lock test t1
38+
MDL_INTENTION_EXCLUSIVE Schema metadata lock test
39+
select * from t1;
40+
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
41+
backup unlock;
42+
connection con1;
43+
connection default;
44+
disconnect con1;
45+
show tables;
46+
Tables_in_test

mysql-test/main/backup_locks.test

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
########################################################################
2+
# Tests BACKUP STAGE locking
3+
########################################################################
4+
5+
--source include/have_innodb.inc
6+
--source include/have_metadata_lock_info.inc
7+
--source include/not_embedded.inc
8+
9+
--echo #
10+
--echo # Test lock taken
11+
--echo #
12+
13+
BACKUP LOCK test.t1;
14+
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info;
15+
BACKUP UNLOCK;
16+
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info;
17+
BACKUP LOCK t1;
18+
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info;
19+
BACKUP UNLOCK;
20+
BACKUP LOCK non_existing.t1;
21+
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info;
22+
BACKUP UNLOCK;
23+
24+
--echo #
25+
--echo # Test that backup lock protects against ddl
26+
--echo #
27+
28+
connect (con1,localhost,root,,);
29+
30+
connection default;
31+
create table t1 (a int) engine=innodb;
32+
insert into t1 values (1);
33+
backup lock t1;
34+
select * from t1;
35+
connection con1;
36+
--send drop table t1
37+
connection default;
38+
let $wait_condition=
39+
select count(*) = 1 from information_schema.processlist
40+
where state = "Waiting for table metadata lock";
41+
--source include/wait_condition.inc
42+
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info;
43+
--error ER_LOCK_DEADLOCK
44+
select * from t1;
45+
backup unlock;
46+
connection con1;
47+
--reap
48+
connection default;
49+
disconnect con1;
50+
show tables;

sql/backup.cc

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,3 +354,32 @@ bool backup_reset_alter_copy_lock(THD *thd)
354354
thd->variables.lock_wait_timeout);
355355
return res;
356356
}
357+
358+
359+
/*****************************************************************************
360+
Backup locks
361+
These functions are used by maria_backup to ensure that there are no active
362+
ddl's on the object the backup is going to copy
363+
*****************************************************************************/
364+
365+
366+
bool backup_lock(THD *thd, TABLE_LIST *table)
367+
{
368+
backup_unlock(thd);
369+
table->mdl_request.duration= MDL_EXPLICIT;
370+
if (thd->mdl_context.acquire_lock(&table->mdl_request,
371+
thd->variables.lock_wait_timeout))
372+
return 1;
373+
thd->mdl_backup_lock= table->mdl_request.ticket;
374+
return 0;
375+
}
376+
377+
378+
/* Release old backup lock if it exists */
379+
380+
void backup_unlock(THD *thd)
381+
{
382+
if (thd->mdl_backup_lock)
383+
thd->mdl_context.release_lock(thd->mdl_backup_lock);
384+
thd->mdl_backup_lock= 0;
385+
}

sql/backup.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,7 @@ bool run_backup_stage(THD *thd, backup_stages stage);
2828
bool backup_end(THD *thd);
2929
void backup_set_alter_copy_lock(THD *thd, TABLE *altered_table);
3030
bool backup_reset_alter_copy_lock(THD *thd);
31+
32+
bool backup_lock(THD *thd, TABLE_LIST *table);
33+
void backup_unlock(THD *thd);
3134
#endif /* BACKUP_INCLUDED */

sql/mysqld.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3667,6 +3667,7 @@ SHOW_VAR com_status_vars[]= {
36673667
{"analyze", STMT_STATUS(SQLCOM_ANALYZE)},
36683668
{"assign_to_keycache", STMT_STATUS(SQLCOM_ASSIGN_TO_KEYCACHE)},
36693669
{"backup", STMT_STATUS(SQLCOM_BACKUP)},
3670+
{"backup_lock", STMT_STATUS(SQLCOM_BACKUP_LOCK)},
36703671
{"begin", STMT_STATUS(SQLCOM_BEGIN)},
36713672
{"binlog", STMT_STATUS(SQLCOM_BINLOG_BASE64_EVENT)},
36723673
{"call_procedure", STMT_STATUS(SQLCOM_CALL)},

sql/sql_class.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -667,6 +667,7 @@ THD::THD(my_thread_id id, bool is_wsrep_applier, bool skip_global_sys_var_lock)
667667
main_da.init();
668668

669669
mdl_context.init(this);
670+
mdl_backup_lock= 0;
670671

671672
/*
672673
Pass nominal parameters to init_alloc_root only to ensure that
@@ -1488,6 +1489,8 @@ void THD::cleanup(void)
14881489
mdl_context.release_transactional_locks();
14891490

14901491
backup_end(this);
1492+
backup_unlock(this);
1493+
14911494
/* Release the global read lock, if acquired. */
14921495
if (global_read_lock.is_acquired())
14931496
global_read_lock.unlock_global_read_lock(this);

sql/sql_class.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2179,7 +2179,7 @@ class THD :public Statement,
21792179
rpl_io_thread_info *rpl_io_info;
21802180
rpl_sql_thread_info *rpl_sql_info;
21812181
} system_thread_info;
2182-
MDL_ticket *mdl_backup_ticket;
2182+
MDL_ticket *mdl_backup_ticket, *mdl_backup_lock;
21832183

21842184
void reset_for_next_command(bool do_clear_errors= 1);
21852185
/*

sql/sql_cmd.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ enum enum_sql_command {
108108
SQLCOM_SHOW_STATUS_PACKAGE,
109109
SQLCOM_SHOW_STATUS_PACKAGE_BODY,
110110
SQLCOM_SHOW_PACKAGE_BODY_CODE,
111-
SQLCOM_BACKUP,
111+
SQLCOM_BACKUP, SQLCOM_BACKUP_LOCK,
112112

113113
/*
114114
When a command is added here, be sure it's also added in mysqld.cc

sql/sql_parse.cc

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -772,6 +772,7 @@ void init_update_queries(void)
772772
sql_command_flags[SQLCOM_ALTER_SERVER]= CF_AUTO_COMMIT_TRANS;
773773
sql_command_flags[SQLCOM_DROP_SERVER]= CF_AUTO_COMMIT_TRANS;
774774
sql_command_flags[SQLCOM_BACKUP]= CF_AUTO_COMMIT_TRANS;
775+
sql_command_flags[SQLCOM_BACKUP_LOCK]= 0;
775776

776777
/*
777778
The following statements can deal with temporary tables,
@@ -5233,6 +5234,17 @@ mysql_execute_command(THD *thd)
52335234
if (!(res= run_backup_stage(thd, lex->backup_stage)))
52345235
my_ok(thd);
52355236
break;
5237+
case SQLCOM_BACKUP_LOCK:
5238+
if (check_global_access(thd, RELOAD_ACL))
5239+
goto error;
5240+
/* first table is set for lock. For unlock the list is empty */
5241+
if (first_table)
5242+
res= backup_lock(thd, first_table);
5243+
else
5244+
backup_unlock(thd);
5245+
if (!res)
5246+
my_ok(thd);
5247+
break;
52365248
case SQLCOM_CREATE_DB:
52375249
{
52385250
if (prepare_db_action(thd, lex->create_info.or_replace() ?

sql/sql_yacc.yy

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1999,7 +1999,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
19991999
%type <select_order> opt_order_clause order_clause order_list
20002000

20012001
%type <NONE>
2002-
analyze_stmt_command backup
2002+
analyze_stmt_command backup backup_statements
20032003
query verb_clause create change select select_into
20042004
do drop insert replace insert2
20052005
insert_values update delete truncate rename compound_statement
@@ -14510,18 +14510,34 @@ opt_table_list:
1451014510
;
1451114511

1451214512
backup:
14513-
BACKUP_SYM STAGE_SYM ident
14513+
BACKUP_SYM backup_statements {}
14514+
;
14515+
14516+
backup_statements:
14517+
STAGE_SYM ident
1451414518
{
1451514519
int type;
1451614520
if (unlikely(Lex->sphead))
1451714521
my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "BACKUP STAGE"));
14518-
if ((type= find_type($3.str, &backup_stage_names,
14522+
if ((type= find_type($2.str, &backup_stage_names,
1451914523
FIND_TYPE_NO_PREFIX)) <= 0)
14520-
my_yyabort_error((ER_BACKUP_UNKNOWN_STAGE, MYF(0), $3.str));
14524+
my_yyabort_error((ER_BACKUP_UNKNOWN_STAGE, MYF(0), $2.str));
1452114525
Lex->sql_command= SQLCOM_BACKUP;
1452214526
Lex->backup_stage= (backup_stages) (type-1);
1452314527
break;
1452414528
}
14529+
| LOCK_SYM table_ident
14530+
{
14531+
if (unlikely(!Select->add_table_to_list(thd, $2, NULL, 0,
14532+
TL_READ, MDL_SHARED_HIGH_PRIO)))
14533+
MYSQL_YYABORT;
14534+
Lex->sql_command= SQLCOM_BACKUP_LOCK;
14535+
}
14536+
| UNLOCK_SYM
14537+
{
14538+
/* Table list is empty for unlock */
14539+
Lex->sql_command= SQLCOM_BACKUP_LOCK;
14540+
}
1452514541
;
1452614542

1452714543
opt_delete_gtid_domain:

0 commit comments

Comments
 (0)