Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
10f3acb
WIP MDEV-14992 BACKUP SERVER
dr-m Jun 8, 2026
10539aa
WIP MDEV-39092, and back up non-InnoDB files
dr-m Jun 8, 2026
ef91938
fixup! 10f3acb01596ce664b8e7a96498eb05ca2385dd5
dr-m Jun 9, 2026
dec5d45
fixup! ef9193898a5071bd44a098bb527ebf70f8655973
dr-m Jun 9, 2026
b868d24
fixup! dec5d45424898517aa053d6b73d3e6edb9ac20b8
dr-m Jun 9, 2026
75ff32f
fixup! b868d24c7fb9d1409dd4cb25fc737b219ee84154
dr-m Jun 9, 2026
f257584
squash! 10f3acb01596ce664b8e7a96498eb05ca2385dd5
dr-m Jun 9, 2026
bd50329
Revert "fixup! b868d24c7fb9d1409dd4cb25fc737b219ee84154"
dr-m Jun 9, 2026
7cd70f4
fixup! f257584af9db2d2d435bdb2696515c54311663bc
dr-m Jun 9, 2026
7f48935
fixup! f257584af9db2d2d435bdb2696515c54311663bc
dr-m Jun 10, 2026
6c1d7e0
squash! 10539aa463aceed07c0c08b52d944a0d5e054525
dr-m Jun 10, 2026
8077134
Multi-threaded backup and stub of streaming backup
dr-m Jun 11, 2026
17ce1be
fixup! 8077134777e3d3fda875413b45f440873c46e358
dr-m Jun 11, 2026
e454e30
Implement table and file copy using backup_step
mariadb-andrzejjarzabek May 28, 2026
ece2446
Fix Aria "crashed table" message on restore. Fix Windows build issue.
mariadb-andrzejjarzabek Jun 9, 2026
c02b69b
Incorporate changes from code review.
mariadb-andrzejjarzabek Jun 9, 2026
a59ddcd
Fix Windows crash. Enable backup_server_restore for Windows.
mariadb-andrzejjarzabek Jun 10, 2026
828b9ed
Make the backup singleton reside in statically allocated memory.
mariadb-andrzejjarzabek Jun 10, 2026
8b1c81b
Add a test for Aria concurrent backup with many tables
mariadb-andrzejjarzabek Jun 12, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions libmysqld/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ SET(SQL_EMBEDDED_SOURCES emb_qcache.cc libmysqld.c lib_sql.cc
../sql/opt_hints.cc ../sql/opt_hints.h
../sql/opt_trace_ddl_info.cc ../sql/opt_trace_ddl_info.h
../sql/sql_path.cc
../sql/sql_backup.cc
${GEN_SOURCES}
${MYSYS_LIBWRAP_SOURCE}
)
Expand Down
1 change: 1 addition & 0 deletions mysql-test/collections/buildbot_suites.bat
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ innodb,^
versioning,^
plugins,^
mariabackup,^
backup,^
roles,^
auth_gssapi,^
mysql_sha2,^
Expand Down
6 changes: 6 additions & 0 deletions mysql-test/main/backup_server.result
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
BACKUP SERVER TO '$datadir/some_directory';
ERROR HY000: Incorrect arguments to BACKUP SERVER TO
BACKUP SERVER TO '$MYSQLTEST_VARDIR/some_directory';
BACKUP SERVER TO '$MYSQLTEST_VARDIR/some_directory';
ERROR HY000: Can't create directory 'MYSQLTEST_VARDIR/some_directory' (Errcode: 17 "File exists")
BACKUP SERVER TO '$MYSQLTEST_VARDIR/some_directory';
10 changes: 10 additions & 0 deletions mysql-test/main/backup_server.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
--let $datadir=`select @@datadir`
--error ER_WRONG_ARGUMENTS
evalp BACKUP SERVER TO '$datadir/some_directory';
evalp BACKUP SERVER TO '$MYSQLTEST_VARDIR/some_directory';
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
--error 21
evalp BACKUP SERVER TO '$MYSQLTEST_VARDIR/some_directory';
--rmdir $MYSQLTEST_VARDIR/some_directory
evalp BACKUP SERVER TO '$MYSQLTEST_VARDIR/some_directory';
--rmdir $MYSQLTEST_VARDIR/some_directory
17 changes: 17 additions & 0 deletions mysql-test/main/backup_server_locking.result
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
BACKUP SERVER TO '$MYSQLTEST_VARDIR/some_directory';
ERROR HY000: Can't create directory 'MYSQLTEST_VARDIR/some_directory' (Errcode: 17 "File exists")
BACKUP STAGE START;
connect backup,localhost,root;
SET STATEMENT max_statement_time=0.1 FOR
BACKUP SERVER TO '$MYSQLTEST_VARDIR/some_directory';
ERROR 70100: Query was interrupted: execution time limit 0.1 sec exceeded
connection default;
BACKUP SERVER TO '$MYSQLTEST_VARDIR/some_directory';
ERROR HY000: Can't execute the command as you have a BACKUP STAGE active
BACKUP STAGE END;
connection backup;
SET STATEMENT max_statement_time=0.1 FOR
BACKUP SERVER TO '$MYSQLTEST_VARDIR/some_directory';
ERROR HY000: Can't create directory 'MYSQLTEST_VARDIR/some_directory' (Errcode: 17 "File exists")
disconnect backup;
connection default;
31 changes: 31 additions & 0 deletions mysql-test/main/backup_server_locking.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
--source include/not_embedded.inc
--source include/count_sessions.inc

--mkdir $MYSQLTEST_VARDIR/some_directory
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
--error 21
evalp BACKUP SERVER TO '$MYSQLTEST_VARDIR/some_directory';

BACKUP STAGE START;
--connect (backup,localhost,root)
--error ER_STATEMENT_TIMEOUT
evalp SET STATEMENT max_statement_time=0.1 FOR
BACKUP SERVER TO '$MYSQLTEST_VARDIR/some_directory';

--connection default

--error ER_BACKUP_LOCK_IS_ACTIVE
evalp BACKUP SERVER TO '$MYSQLTEST_VARDIR/some_directory';

BACKUP STAGE END;
--connection backup
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
--error 21
evalp SET STATEMENT max_statement_time=0.1 FOR
BACKUP SERVER TO '$MYSQLTEST_VARDIR/some_directory';
--disconnect backup
--connection default

--rmdir $MYSQLTEST_VARDIR/some_directory

--source include/wait_until_count_sessions.inc
27 changes: 27 additions & 0 deletions mysql-test/main/grant_backup_server.result
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
CREATE USER user1@localhost IDENTIFIED BY '';
connect con1,localhost,user1;
BACKUP SERVER TO 'some_directory';
ERROR 42000: Access denied; you need (at least one of) the RELOAD privilege(s) for this operation
disconnect con1;
connection default;
GRANT SELECT ON test.* TO user1@localhost;
connect con1,localhost,user1;
BACKUP SERVER TO 'some_directory';
ERROR 42000: Access denied; you need (at least one of) the RELOAD privilege(s) for this operation
disconnect con1;
connection default;
GRANT RELOAD ON test.* TO user1@localhost;
ERROR HY000: Incorrect usage of DB GRANT and GLOBAL PRIVILEGES
GRANT RELOAD ON *.* TO user1@localhost;
connect con1,localhost,user1;
BACKUP SERVER TO 'some_directory';
ERROR 42000: Access denied; you need (at least one of) the SELECT privilege(s) for this operation
disconnect con1;
connection default;
GRANT SELECT ON *.* TO user1@localhost;
connect con1,localhost,user1;
BACKUP SERVER TO '$datadir/some_directory';
ERROR HY000: Incorrect arguments to BACKUP SERVER TO
disconnect con1;
connection default;
DROP USER user1@localhost;
29 changes: 29 additions & 0 deletions mysql-test/main/grant_backup_server.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
--source include/not_embedded.inc
CREATE USER user1@localhost IDENTIFIED BY '';
--connect con1,localhost,user1
--error ER_SPECIFIC_ACCESS_DENIED_ERROR
BACKUP SERVER TO 'some_directory';
--disconnect con1
--connection default
GRANT SELECT ON test.* TO user1@localhost;
--connect con1,localhost,user1
--error ER_SPECIFIC_ACCESS_DENIED_ERROR
BACKUP SERVER TO 'some_directory';
--disconnect con1
--connection default
--error ER_WRONG_USAGE
GRANT RELOAD ON test.* TO user1@localhost;
GRANT RELOAD ON *.* TO user1@localhost;
--connect con1,localhost,user1
--error ER_SPECIFIC_ACCESS_DENIED_ERROR
BACKUP SERVER TO 'some_directory';
--disconnect con1
--connection default
GRANT SELECT ON *.* TO user1@localhost;
--connect con1,localhost,user1
--let $datadir=`select @@datadir`
--error ER_WRONG_ARGUMENTS
evalp BACKUP SERVER TO '$datadir/some_directory';
--disconnect con1
--connection default
DROP USER user1@localhost;
2 changes: 1 addition & 1 deletion mysql-test/main/mysqld--help.result
Original file line number Diff line number Diff line change
Expand Up @@ -2053,7 +2053,7 @@ performance-schema-max-socket-classes 10
performance-schema-max-socket-instances -1
performance-schema-max-sql-text-length 1024
performance-schema-max-stage-classes 170
performance-schema-max-statement-classes 227
performance-schema-max-statement-classes 228
performance-schema-max-statement-stack 10
performance-schema-max-table-handles -1
performance-schema-max-table-instances -1
Expand Down
1 change: 1 addition & 0 deletions mysql-test/mariadb-test-run.pl
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ END
main-
archive-
atomic-
backup-
binlog-
binlog_encryption-
binlog_in_engine-
Expand Down
20 changes: 20 additions & 0 deletions mysql-test/suite/backup/backup_aria_concurrent.result
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
15 30 7500
Back up the database
BACKUP SERVER TO '$target_directory' 4 CONCURRENT;
Restore the database
# restart: --datadir=MYSQLTEST_VARDIR/some_directory
Check contents after restore
SELECT COUNT(*) FROM table_checks;
COUNT(*)
400
SELECT * FROM table_checks WHERE sum_id <> 15;
tbl_name sum_id str_len blob_len num_rows
SELECT * FROM table_checks WHERE str_len <> 30;
tbl_name sum_id str_len blob_len num_rows
SELECT * FROM table_checks WHERE blob_len <> 7500;
tbl_name sum_id str_len blob_len num_rows
SELECT * FROM table_checks WHERE num_rows <> 5;
tbl_name sum_id str_len blob_len num_rows
Restart database in original data directory
# restart
Clean up
145 changes: 145 additions & 0 deletions mysql-test/suite/backup/backup_aria_concurrent.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@

--source include/have_aria.inc

--disable_query_log


DELIMITER //;
CREATE PROCEDURE populate_data(IN t_name VARCHAR(64), IN num_rows INT)
BEGIN
DECLARE i INT DEFAULT 1;
SET @query = CONCAT('INSERT INTO ', t_name, ' (id, str_val, blob_val) VALUES (?, ?, ?)');
PREPARE stmt FROM @query;

WHILE i <= num_rows DO
SET @str = CONCAT('_row_', i);
# Generate a predictable but repeating blob based on the row index
SET @blb = REPEAT(CHAR(97 + (i % 26)), 1500);
EXECUTE stmt USING i, @str, @blb;
SET i = i + 1;
END WHILE;

DEALLOCATE PREPARE stmt;
END//
DELIMITER ;//

# Create this many tables transactional and non-transactional each
let $tab_num= 200;
let $num_rows= 5;

let $i = 1;
while ($i <= $tab_num) {

# Create Transactional Table

let $tr=0;
while ($tr <= 1) {

let $suff= _$i;
let $table_name= ta_tr$tr$suff;

eval CREATE TABLE $table_name (
id INT PRIMARY KEY,
str_val VARCHAR(255),
blob_val BLOB,
INDEX idx_str (str_val)
) ENGINE=Aria TRANSACTIONAL=$tr;

eval CALL populate_data('$table_name', $num_rows);

inc $tr;
}

inc $i;
}

--enable_query_log

# All tables have the same data, so we query only one for reference

let $sum_id= `SELECT SUM(id) FROM ta_tr0_1`;
let $str_len= `SELECT SUM(LENGTH(str_val)) FROM ta_tr0_1`;
let $blob_len= `SELECT SUM(LENGTH(blob_val)) FROM ta_tr0_1`;

echo $sum_id $str_len $blob_len;

--let $target_directory=$MYSQLTEST_VARDIR/some_directory

# Clean up after a previous failed test, in case we are retrying.
--error 0,1
--rmdir $target_directory

--echo Back up the database
evalp BACKUP SERVER TO '$target_directory' 4 CONCURRENT;

--echo Restore the database
--let $restart_parameters=--datadir=$target_directory
--source include/restart_mysqld.inc

--echo Check contents after restore

--disable_query_log
CREATE TEMPORARY TABLE table_checks (
tbl_name VARCHAR(64),
sum_id INT,
str_len INT,
blob_len INT,
num_rows INT
) ENGINE=MEMORY;

let $i = 1;
while ($i <= $tab_num) {
let $tr=0;
while ($tr <= 1) {

let $suff= _$i;
let $table_name= ta_tr$tr$suff;

let $r_sum_id= `SELECT SUM(id) FROM $table_name`;
let $r_str_len= `SELECT SUM(LENGTH(str_val)) FROM $table_name`;
let $r_blob_len= `SELECT SUM(LENGTH(blob_val)) FROM $table_name`;
let $r_num_rows= `SELECT COUNT(*) FROM $table_name`;

eval INSERT INTO table_checks VALUES ('$table_name', $r_sum_id, $r_str_len, $r_blob_len, $r_num_rows);

inc $tr;
}
inc $i;
}

--enable_query_log

SELECT COUNT(*) FROM table_checks;

# We expect results in the table to always match the results captured before the BACKUP
# Returned rowsets should be empty
eval SELECT * FROM table_checks WHERE sum_id <> $sum_id;
eval SELECT * FROM table_checks WHERE str_len <> $str_len;
eval SELECT * FROM table_checks WHERE blob_len <> $blob_len;
eval SELECT * FROM table_checks WHERE num_rows <> $num_rows;

--echo Restart database in original data directory
--let $restart_parameters=
--source include/restart_mysqld.inc

--echo Clean up

--disable_query_log

let $i = 1;
while ($i <= $tab_num) {
let $tr=0;
while ($tr <= 1) {
let $suff= _$i;
let $table_name= ta_tr$tr$suff;
eval DROP TABLE $table_name;
inc $tr;
}
inc $i;
}

DROP PROCEDURE populate_data;

--enable_query_log

--rmdir $MYSQLTEST_VARDIR/some_directory
16 changes: 16 additions & 0 deletions mysql-test/suite/backup/backup_innodb,debug.rdiff
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
--- backup_innodb.result
+++ backup_innodb,debug.result
@@ -10,7 +10,13 @@
BEGIN;
DELETE FROM t;
connect backup,localhost,root;
+SET DEBUG_SYNC='innodb_backup_start SIGNAL start WAIT_FOR resume';
BACKUP SERVER TO 'target_directory' 4 CONCURRENT;
+connection default;
+SET DEBUG_SYNC='now WAIT_FOR start';
+INSERT INTO t(a) SELECT * FROM seq_1_to_30000;
+SET DEBUG_SYNC='now SIGNAL resume';
+connection backup;
disconnect backup;
connection default;
ROLLBACK;
4 changes: 4 additions & 0 deletions mysql-test/suite/backup/backup_innodb.combinations
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[archived]
innodb_log_archive=ON
[circular]
innodb_log_archive=OFF
Loading
Loading