Skip to content

Commit 8f37343

Browse files
MDEV-39092 Improve BACKUP SERVER of ENGINE=Aria
On top of the provisional Aria backup solution provisionally incorporated into MDEV-14992, the following improvements have been made: Aria data and index files are copied under DDL-locked lock level instead of commit-locked, making the backup operation less disruptive. Only log files are copied in the commit-locked phase. Writes to non-transactional Aria tables are blocked in the DDL-locked phase, while writes to transactional tables are written to the log file, allowing consistent point-in-time backup at the time of acquiring the commit lock. Data, index and log files are now copied as a "step" action rather than "end phase" action, allowing them to be copied in parallel using the CONCURRENT option. Non-Aria files, including common SQL-layer metadata and files from other storage engines are copied by the SQL layer rather than the Aria plugin. Note these files are at this time not copied concurrently when the concurrent option is used.
1 parent 5235e7a commit 8f37343

10 files changed

Lines changed: 1078 additions & 298 deletions
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
15 30 7500
2+
Back up the database
3+
BACKUP SERVER TO '$target_directory' 4 CONCURRENT;
4+
Restore the database
5+
# restart: --datadir=MYSQLTEST_VARDIR/some_directory
6+
Check contents after restore
7+
SELECT COUNT(*) FROM table_checks;
8+
COUNT(*)
9+
400
10+
SELECT * FROM table_checks WHERE sum_id <> 15;
11+
tbl_name sum_id str_len blob_len num_rows
12+
SELECT * FROM table_checks WHERE str_len <> 30;
13+
tbl_name sum_id str_len blob_len num_rows
14+
SELECT * FROM table_checks WHERE blob_len <> 7500;
15+
tbl_name sum_id str_len blob_len num_rows
16+
SELECT * FROM table_checks WHERE num_rows <> 5;
17+
tbl_name sum_id str_len blob_len num_rows
18+
Restart database in original data directory
19+
# restart
20+
Clean up
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
2+
--source include/have_aria.inc
3+
4+
--disable_query_log
5+
6+
7+
DELIMITER //;
8+
CREATE PROCEDURE populate_data(IN t_name VARCHAR(64), IN num_rows INT)
9+
BEGIN
10+
DECLARE i INT DEFAULT 1;
11+
SET @query = CONCAT('INSERT INTO ', t_name, ' (id, str_val, blob_val) VALUES (?, ?, ?)');
12+
PREPARE stmt FROM @query;
13+
14+
WHILE i <= num_rows DO
15+
SET @str = CONCAT('_row_', i);
16+
# Generate a predictable but repeating blob based on the row index
17+
SET @blb = REPEAT(CHAR(97 + (i % 26)), 1500);
18+
EXECUTE stmt USING i, @str, @blb;
19+
SET i = i + 1;
20+
END WHILE;
21+
22+
DEALLOCATE PREPARE stmt;
23+
END//
24+
DELIMITER ;//
25+
26+
# Create this many tables transactional and non-transactional each
27+
let $tab_num= 200;
28+
let $num_rows= 5;
29+
30+
let $i = 1;
31+
while ($i <= $tab_num) {
32+
33+
let $tr=0;
34+
while ($tr <= 1) {
35+
36+
let $suff= _$i;
37+
let $table_name= ta_tr$tr$suff;
38+
39+
eval CREATE TABLE $table_name (
40+
id INT PRIMARY KEY,
41+
str_val VARCHAR(255),
42+
blob_val BLOB,
43+
INDEX idx_str (str_val)
44+
) ENGINE=Aria TRANSACTIONAL=$tr;
45+
46+
eval CALL populate_data('$table_name', $num_rows);
47+
48+
inc $tr;
49+
}
50+
51+
inc $i;
52+
}
53+
54+
--enable_query_log
55+
56+
# All tables have the same data, so we query only one for reference
57+
58+
let $sum_id= `SELECT SUM(id) FROM ta_tr0_1`;
59+
let $str_len= `SELECT SUM(LENGTH(str_val)) FROM ta_tr0_1`;
60+
let $blob_len= `SELECT SUM(LENGTH(blob_val)) FROM ta_tr0_1`;
61+
62+
echo $sum_id $str_len $blob_len;
63+
64+
--let $target_directory=$MYSQLTEST_VARDIR/some_directory
65+
66+
# Clean up after a previous failed test, in case we are retrying.
67+
--error 0,1
68+
--rmdir $target_directory
69+
70+
--echo Back up the database
71+
evalp BACKUP SERVER TO '$target_directory' 4 CONCURRENT;
72+
73+
--echo Restore the database
74+
--let $restart_parameters=--datadir=$target_directory
75+
--source include/restart_mysqld.inc
76+
77+
--echo Check contents after restore
78+
79+
--disable_query_log
80+
CREATE TEMPORARY TABLE table_checks (
81+
tbl_name VARCHAR(64),
82+
sum_id INT,
83+
str_len INT,
84+
blob_len INT,
85+
num_rows INT
86+
) ENGINE=MEMORY;
87+
88+
let $i = 1;
89+
while ($i <= $tab_num) {
90+
let $tr=0;
91+
while ($tr <= 1) {
92+
93+
let $suff= _$i;
94+
let $table_name= ta_tr$tr$suff;
95+
96+
let $r_sum_id= `SELECT SUM(id) FROM $table_name`;
97+
let $r_str_len= `SELECT SUM(LENGTH(str_val)) FROM $table_name`;
98+
let $r_blob_len= `SELECT SUM(LENGTH(blob_val)) FROM $table_name`;
99+
let $r_num_rows= `SELECT COUNT(*) FROM $table_name`;
100+
101+
eval INSERT INTO table_checks VALUES ('$table_name', $r_sum_id, $r_str_len, $r_blob_len, $r_num_rows);
102+
103+
inc $tr;
104+
}
105+
inc $i;
106+
}
107+
108+
--enable_query_log
109+
110+
SELECT COUNT(*) FROM table_checks;
111+
112+
# We expect results in the table to always match the results captured before the BACKUP
113+
# Returned rowsets should be empty
114+
eval SELECT * FROM table_checks WHERE sum_id <> $sum_id;
115+
eval SELECT * FROM table_checks WHERE str_len <> $str_len;
116+
eval SELECT * FROM table_checks WHERE blob_len <> $blob_len;
117+
eval SELECT * FROM table_checks WHERE num_rows <> $num_rows;
118+
119+
--echo Restart database in original data directory
120+
--let $restart_parameters=
121+
--source include/restart_mysqld.inc
122+
123+
--echo Clean up
124+
125+
--disable_query_log
126+
127+
let $i = 1;
128+
while ($i <= $tab_num) {
129+
let $tr=0;
130+
while ($tr <= 1) {
131+
let $suff= _$i;
132+
let $table_name= ta_tr$tr$suff;
133+
eval DROP TABLE $table_name;
134+
inc $tr;
135+
}
136+
inc $i;
137+
}
138+
139+
DROP PROCEDURE populate_data;
140+
141+
--enable_query_log
142+
143+
--rmdir $target_directory
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# restart: --aria-log-dir-path=MYSQLTEST_VARDIR/log_directory
2+
CREATE TABLE t (
3+
id INT PRIMARY KEY,
4+
str_val VARCHAR(255),
5+
blob_val BLOB,
6+
INDEX idx_str (str_val)
7+
) ENGINE=Aria TRANSACTIONAL=1;
8+
CREATE PROCEDURE populate_data(IN num_rows INT)
9+
BEGIN
10+
DECLARE i INT DEFAULT 0;
11+
WHILE i < num_rows DO
12+
SET @str = CONCAT('_row_', i);
13+
SET @blb = REPEAT(CHAR(97 + (i % 26)), 1500);
14+
INSERT INTO t (id, str_val, blob_val) VALUES (i, @str, @blb);
15+
SET i = i + 1;
16+
END WHILE;
17+
END//
18+
CALL populate_data(10000);
19+
SELECT COUNT(*) from t;
20+
COUNT(*)
21+
10000
22+
SELECT SUM(id) FROM t;
23+
SUM(id)
24+
49995000
25+
SELECT SUM(LENGTH(str_val)) FROM t;
26+
SUM(LENGTH(str_val))
27+
88890
28+
SELECT SUM(LENGTH(blob_val)) FROM t;
29+
SUM(LENGTH(blob_val))
30+
15000000
31+
Back up the database
32+
BACKUP SERVER TO '$target_directory';
33+
Restore the database
34+
# restart: --datadir=MYSQLTEST_VARDIR/some_directory
35+
Check contents after restore
36+
SELECT COUNT(*) from t;
37+
COUNT(*)
38+
10000
39+
SELECT SUM(id) FROM t;
40+
SUM(id)
41+
49995000
42+
SELECT SUM(LENGTH(str_val)) FROM t;
43+
SUM(LENGTH(str_val))
44+
88890
45+
SELECT SUM(LENGTH(blob_val)) FROM t;
46+
SUM(LENGTH(blob_val))
47+
15000000
48+
Restart database in original log and data directories
49+
# restart: --aria-log-dir-path=MYSQLTEST_VARDIR/log_directory
50+
Clean up
51+
DROP PROCEDURE populate_data;
52+
DROP TABLE t;
53+
# restart
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
--source include/have_aria.inc
2+
3+
--let $log_directory=$MYSQLTEST_VARDIR/log_directory
4+
--let $target_directory=$MYSQLTEST_VARDIR/some_directory
5+
6+
# Clean up after a previous failed test, in case we are retrying.
7+
--error 0,1
8+
--rmdir $log_directory
9+
--error 0,1
10+
--rmdir $target_directory
11+
12+
--mkdir $log_directory
13+
14+
--let $orig_restart_parameters=--aria-log-dir-path=$log_directory
15+
--let $restart_parameters=$orig_restart_parameters
16+
--source include/restart_mysqld.inc
17+
18+
CREATE TABLE t (
19+
id INT PRIMARY KEY,
20+
str_val VARCHAR(255),
21+
blob_val BLOB,
22+
INDEX idx_str (str_val)
23+
) ENGINE=Aria TRANSACTIONAL=1;
24+
25+
--disable_warnings
26+
DELIMITER //;
27+
CREATE PROCEDURE populate_data(IN num_rows INT)
28+
BEGIN
29+
DECLARE i INT DEFAULT 0;
30+
WHILE i < num_rows DO
31+
SET @str = CONCAT('_row_', i);
32+
SET @blb = REPEAT(CHAR(97 + (i % 26)), 1500);
33+
INSERT INTO t (id, str_val, blob_val) VALUES (i, @str, @blb);
34+
SET i = i + 1;
35+
END WHILE;
36+
END//
37+
DELIMITER ;//
38+
--enable_warnings
39+
40+
CALL populate_data(10000);
41+
42+
SELECT COUNT(*) from t;
43+
SELECT SUM(id) FROM t;
44+
SELECT SUM(LENGTH(str_val)) FROM t;
45+
SELECT SUM(LENGTH(blob_val)) FROM t;
46+
47+
--echo Back up the database
48+
evalp BACKUP SERVER TO '$target_directory';
49+
50+
--echo Restore the database
51+
--let $restart_parameters=--datadir=$target_directory
52+
--source include/restart_mysqld.inc
53+
54+
--echo Check contents after restore
55+
56+
SELECT COUNT(*) from t;
57+
SELECT SUM(id) FROM t;
58+
SELECT SUM(LENGTH(str_val)) FROM t;
59+
SELECT SUM(LENGTH(blob_val)) FROM t;
60+
61+
--echo Restart database in original log and data directories
62+
--let $restart_parameters=$orig_restart_parameters
63+
--source include/restart_mysqld.inc
64+
65+
--echo Clean up
66+
67+
DROP PROCEDURE populate_data;
68+
DROP TABLE t;
69+
70+
--let $restart_parameters=
71+
--source include/restart_mysqld.inc
72+
73+
--rmdir $target_directory
74+
--rmdir $log_directory
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
CREATE TABLE t_archive (id int unsigned) ENGINE=ARCHIVE;
2+
INSERT INTO t_archive VALUES (2), (3), (5), (7), (11);
3+
CREATE DATABASE d;
4+
CREATE TABLE d.t_csv (id int unsigned NOT NULL) ENGINE=CSV;
5+
INSERT INTO d.t_csv VALUES (4), (26), (41), (60), (83), (109);
6+
CREATE TABLE t_myisam1 (id int unsigned) ENGINE=MyISAM;
7+
INSERT INTO t_myisam1 VALUES (1), (1), (2), (3), (5), (8);
8+
CREATE TABLE t_myisam2 (id int unsigned) ENGINE=MyISAM;
9+
INSERT INTO t_myisam2 VALUES (13), (21), (34), (55), (89), (144);
10+
CREATE TABLE t_mrg (id int unsigned) ENGINE=MRG_MyISAM UNION=(t_myisam1, t_myisam2);
11+
BACKUP SERVER TO '$target_directory';
12+
# restart: --datadir=MYSQLTEST_VARDIR/some_directory
13+
SELECT * FROM t_archive ORDER BY id;
14+
id
15+
2
16+
3
17+
5
18+
7
19+
11
20+
SELECT * FROM d.t_csv ORDER BY id;
21+
id
22+
4
23+
26
24+
41
25+
60
26+
83
27+
109
28+
SELECT * FROM t_myisam1 ORDER BY id;
29+
id
30+
1
31+
1
32+
2
33+
3
34+
5
35+
8
36+
SELECT * FROM t_mrg ORDER BY id;
37+
id
38+
1
39+
1
40+
2
41+
3
42+
5
43+
8
44+
13
45+
21
46+
34
47+
55
48+
89
49+
144
50+
# restart
51+
DROP TABLE t_archive;
52+
DROP TABLE d.t_csv;
53+
DROP TABLE t_myisam1;
54+
DROP TABLE t_myisam2;
55+
DROP TABLE t_mrg;
56+
DROP DATABASE d;
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
--source include/have_csv.inc
2+
--source include/have_archive.inc
3+
4+
CREATE TABLE t_archive (id int unsigned) ENGINE=ARCHIVE;
5+
INSERT INTO t_archive VALUES (2), (3), (5), (7), (11);
6+
7+
CREATE DATABASE d;
8+
CREATE TABLE d.t_csv (id int unsigned NOT NULL) ENGINE=CSV;
9+
INSERT INTO d.t_csv VALUES (4), (26), (41), (60), (83), (109);
10+
11+
CREATE TABLE t_myisam1 (id int unsigned) ENGINE=MyISAM;
12+
INSERT INTO t_myisam1 VALUES (1), (1), (2), (3), (5), (8);
13+
14+
CREATE TABLE t_myisam2 (id int unsigned) ENGINE=MyISAM;
15+
INSERT INTO t_myisam2 VALUES (13), (21), (34), (55), (89), (144);
16+
17+
CREATE TABLE t_mrg (id int unsigned) ENGINE=MRG_MyISAM UNION=(t_myisam1, t_myisam2);
18+
19+
--let $target_directory=$MYSQLTEST_VARDIR/some_directory
20+
21+
# Clean up after a previous failed test, in case we are retrying.
22+
--error 0,1
23+
--rmdir $target_directory
24+
25+
evalp BACKUP SERVER TO '$target_directory';
26+
27+
--let $restart_parameters=--datadir=$target_directory
28+
--source include/restart_mysqld.inc
29+
30+
SELECT * FROM t_archive ORDER BY id;
31+
SELECT * FROM d.t_csv ORDER BY id;
32+
SELECT * FROM t_myisam1 ORDER BY id;
33+
SELECT * FROM t_mrg ORDER BY id;
34+
35+
--let $restart_parameters=
36+
--source include/restart_mysqld.inc
37+
38+
DROP TABLE t_archive;
39+
DROP TABLE d.t_csv;
40+
DROP TABLE t_myisam1;
41+
DROP TABLE t_myisam2;
42+
DROP TABLE t_mrg;
43+
DROP DATABASE d;
44+
45+
--rmdir $target_directory

0 commit comments

Comments
 (0)