mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
MDEV-32932 Port backup features from ES
Added support to BACKUP STAGE to maria-backup This is a port of the code from ES 10.6 See MDEV-5336 for backup stages description. The following old options are not supported by the new code: --rsync ; This is because rsync will not work on tables that are in used. --no-backup-locks ; This is disabled as mariadb-backup will always use backup locks for better performance.
This commit is contained in:
@ -31,6 +31,7 @@ ENDIF()
|
||||
INCLUDE_DIRECTORIES(
|
||||
${CMAKE_SOURCE_DIR}/include
|
||||
${CMAKE_SOURCE_DIR}/sql
|
||||
${CMAKE_SOURCE_DIR}/storage/maria
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/quicklz
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
)
|
||||
@ -71,8 +72,12 @@ MYSQL_ADD_EXECUTABLE(mariadb-backup
|
||||
xbstream_write.cc
|
||||
backup_mysql.cc
|
||||
backup_copy.cc
|
||||
xb_plugin.cc
|
||||
encryption_plugin.cc
|
||||
${PROJECT_BINARY_DIR}/sql/sql_builtin.cc
|
||||
aria_backup_client.cc
|
||||
thread_pool.cc
|
||||
ddl_log.cc
|
||||
common_engine.cc
|
||||
${PROJECT_SOURCE_DIR}/sql/net_serv.cc
|
||||
${PROJECT_SOURCE_DIR}/libmysqld/libmysql.c
|
||||
COMPONENT backup
|
||||
@ -81,7 +86,8 @@ MYSQL_ADD_EXECUTABLE(mariadb-backup
|
||||
# Export all symbols on Unix, for better crash callstacks
|
||||
SET_TARGET_PROPERTIES(mariadb-backup PROPERTIES ENABLE_EXPORTS TRUE)
|
||||
|
||||
TARGET_LINK_LIBRARIES(mariadb-backup sql sql_builtins)
|
||||
TARGET_LINK_LIBRARIES(mariadb-backup sql sql_builtins aria)
|
||||
|
||||
IF(NOT HAVE_SYSTEM_REGEX)
|
||||
TARGET_LINK_LIBRARIES(mariadb-backup pcre2-posix)
|
||||
ENDIF()
|
||||
|
1016
extra/mariabackup/aria_backup_client.cc
Normal file
1016
extra/mariabackup/aria_backup_client.cc
Normal file
File diff suppressed because it is too large
Load Diff
38
extra/mariabackup/aria_backup_client.h
Normal file
38
extra/mariabackup/aria_backup_client.h
Normal file
@ -0,0 +1,38 @@
|
||||
#pragma once
|
||||
#include "my_global.h"
|
||||
#include "datasink.h"
|
||||
#include "backup_mysql.h"
|
||||
#include "thread_pool.h"
|
||||
#include "xtrabackup.h"
|
||||
|
||||
namespace aria {
|
||||
|
||||
bool prepare(const char *target_dir);
|
||||
|
||||
class BackupImpl;
|
||||
|
||||
class Backup {
|
||||
public:
|
||||
Backup(const char *datadir_path,
|
||||
const char *aria_log_path,
|
||||
ds_ctxt_t *datasink,
|
||||
std::vector<MYSQL *> &con_pool, ThreadPool &thread_pool);
|
||||
~Backup();
|
||||
Backup (Backup &&other) = delete;
|
||||
Backup & operator= (Backup &&other) = delete;
|
||||
Backup(const Backup &) = delete;
|
||||
Backup & operator= (const Backup &) = delete;
|
||||
bool init();
|
||||
bool start(bool no_lock);
|
||||
bool wait_for_finish();
|
||||
bool copy_offline_tables(
|
||||
const std::unordered_set<table_key_t> *exclude_tables, bool no_lock,
|
||||
bool copy_stats);
|
||||
bool finalize();
|
||||
bool copy_log_tail();
|
||||
void set_post_copy_table_hook(const post_copy_table_hook_t &hook);
|
||||
private:
|
||||
BackupImpl *m_backup_impl;
|
||||
};
|
||||
|
||||
} // namespace aria
|
@ -41,6 +41,9 @@ Street, Fifth Floor, Boston, MA 02110-1335 USA
|
||||
*******************************************************/
|
||||
|
||||
#include <my_global.h>
|
||||
#include <my_config.h>
|
||||
#include <unireg.h>
|
||||
#include <datadict.h>
|
||||
#include <os0file.h>
|
||||
#include <my_dir.h>
|
||||
#include <ut0mem.h>
|
||||
@ -66,19 +69,26 @@ Street, Fifth Floor, Boston, MA 02110-1335 USA
|
||||
#include <aclapi.h>
|
||||
#endif
|
||||
|
||||
#ifdef MYSQL_CLIENT
|
||||
#define WAS_MYSQL_CLIENT 1
|
||||
#undef MYSQL_CLIENT
|
||||
#endif
|
||||
|
||||
#include "table.h"
|
||||
|
||||
#ifdef WAS_MYSQL_CLIENT
|
||||
#define MYSQL_CLIENT 1
|
||||
#undef WAS_MYSQL_CLIENT
|
||||
#endif
|
||||
|
||||
#define ROCKSDB_BACKUP_DIR "#rocksdb"
|
||||
|
||||
/* list of files to sync for --rsync mode */
|
||||
static std::set<std::string> rsync_list;
|
||||
/* locations of tablespaces read from .isl files */
|
||||
static std::map<std::string, std::string> tablespace_locations;
|
||||
|
||||
/* Whether LOCK BINLOG FOR BACKUP has been issued during backup */
|
||||
bool binlog_locked;
|
||||
|
||||
static void rocksdb_create_checkpoint();
|
||||
static bool has_rocksdb_plugin();
|
||||
static void rocksdb_backup_checkpoint(ds_ctxt *ds_data);
|
||||
static void rocksdb_copy_back(ds_ctxt *ds_data);
|
||||
|
||||
@ -135,10 +145,6 @@ struct datadir_thread_ctxt_t {
|
||||
bool ret;
|
||||
};
|
||||
|
||||
static bool backup_files_from_datadir(ds_ctxt_t *ds_data,
|
||||
const char *dir_path,
|
||||
const char *prefix);
|
||||
|
||||
/************************************************************************
|
||||
Retirn true if character if file separator */
|
||||
bool
|
||||
@ -585,7 +591,6 @@ datafile_read(datafile_cur_t *cursor)
|
||||
Check to see if a file exists.
|
||||
Takes name of the file to check.
|
||||
@return true if file exists. */
|
||||
static
|
||||
bool
|
||||
file_exists(const char *filename)
|
||||
{
|
||||
@ -601,7 +606,6 @@ file_exists(const char *filename)
|
||||
|
||||
/************************************************************************
|
||||
Trim leading slashes from absolute path so it becomes relative */
|
||||
static
|
||||
const char *
|
||||
trim_dotslash(const char *path)
|
||||
{
|
||||
@ -634,7 +638,7 @@ ends_with(const char *str, const char *suffix)
|
||||
&& strcmp(str + str_len - suffix_len, suffix) == 0);
|
||||
}
|
||||
|
||||
static bool starts_with(const char *str, const char *prefix)
|
||||
bool starts_with(const char *str, const char *prefix)
|
||||
{
|
||||
return strncmp(str, prefix, strlen(prefix)) == 0;
|
||||
}
|
||||
@ -785,7 +789,6 @@ directory_exists_and_empty(const char *dir, const char *comment)
|
||||
/************************************************************************
|
||||
Check if file name ends with given set of suffixes.
|
||||
@return true if it does. */
|
||||
static
|
||||
bool
|
||||
filename_matches(const char *filename, const char **ext_list)
|
||||
{
|
||||
@ -800,6 +803,115 @@ filename_matches(const char *filename, const char **ext_list)
|
||||
return(false);
|
||||
}
|
||||
|
||||
// TODO: the code can be used to find storage engine of partitions
|
||||
/*
|
||||
static
|
||||
bool is_aria_frm_or_par(const char *path) {
|
||||
if (!ends_with(path, ".frm") && !ends_with(path, ".par"))
|
||||
return false;
|
||||
|
||||
const char *frm_path = path;
|
||||
if (ends_with(path, ".par")) {
|
||||
size_t frm_path_len = strlen(path);
|
||||
DBUG_ASSERT(frm_path_len > strlen("frm"));
|
||||
frm_path = strdup(path);
|
||||
strcpy(const_cast<char *>(frm_path) + frm_path_len - strlen("frm"), "frm");
|
||||
}
|
||||
|
||||
bool result = false;
|
||||
File file;
|
||||
uchar header[40];
|
||||
legacy_db_type dbt;
|
||||
|
||||
if ((file= mysql_file_open(key_file_frm, frm_path, O_RDONLY | O_SHARE, MYF(0)))
|
||||
< 0)
|
||||
goto err;
|
||||
|
||||
if (mysql_file_read(file, (uchar*) header, sizeof(header), MYF(MY_NABP)))
|
||||
goto err;
|
||||
|
||||
if (!strncmp((char*) header, "TYPE=VIEW\n", 10))
|
||||
goto err;
|
||||
|
||||
if (!is_binary_frm_header(header))
|
||||
goto err;
|
||||
|
||||
dbt = (legacy_db_type)header[3];
|
||||
|
||||
if (dbt == DB_TYPE_ARIA) {
|
||||
result = true;
|
||||
}
|
||||
else if (dbt == DB_TYPE_PARTITION_DB) {
|
||||
MY_STAT state;
|
||||
uchar *frm_image= 0;
|
||||
// uint n_length;
|
||||
|
||||
if (mysql_file_fstat(file, &state, MYF(MY_WME)))
|
||||
goto err;
|
||||
|
||||
if (mysql_file_seek(file, 0, SEEK_SET, MYF(MY_WME)))
|
||||
goto err;
|
||||
|
||||
if (read_string(file, &frm_image, (size_t)state.st_size))
|
||||
goto err;
|
||||
|
||||
dbt = (legacy_db_type)frm_image[61];
|
||||
if (dbt == DB_TYPE_ARIA) {
|
||||
result = true;
|
||||
}
|
||||
my_free(frm_image);
|
||||
}
|
||||
|
||||
err:
|
||||
if (file >= 0)
|
||||
mysql_file_close(file, MYF(MY_WME));
|
||||
if (frm_path != path)
|
||||
free(const_cast<char *>(frm_path));
|
||||
return result;
|
||||
}
|
||||
*/
|
||||
|
||||
void parse_db_table_from_file_path(
|
||||
const char *filepath, char *dbname, char *tablename) {
|
||||
dbname[0] = '\0';
|
||||
tablename[0] = '\0';
|
||||
const char *dbname_start = nullptr;
|
||||
const char *tablename_start = filepath;
|
||||
const char *const_ptr;
|
||||
while ((const_ptr = strchr(tablename_start, FN_LIBCHAR)) != NULL) {
|
||||
dbname_start = tablename_start;
|
||||
tablename_start = const_ptr + 1;
|
||||
}
|
||||
if (!dbname_start)
|
||||
return;
|
||||
size_t dbname_len = tablename_start - dbname_start - 1;
|
||||
if (dbname_len >= FN_REFLEN)
|
||||
dbname_len = FN_REFLEN-1;
|
||||
strmake(dbname, dbname_start, dbname_len);
|
||||
strmake(tablename, tablename_start, FN_REFLEN-1);
|
||||
char *ptr;
|
||||
if ((ptr = strchr(tablename, '.')))
|
||||
*ptr = '\0';
|
||||
if ((ptr = strstr(tablename, "#P#")))
|
||||
*ptr = '\0';
|
||||
}
|
||||
|
||||
bool is_system_table(const char *dbname, const char *tablename)
|
||||
{
|
||||
DBUG_ASSERT(dbname);
|
||||
DBUG_ASSERT(tablename);
|
||||
|
||||
LEX_CSTRING lex_dbname;
|
||||
LEX_CSTRING lex_tablename;
|
||||
lex_dbname.str = dbname;
|
||||
lex_dbname.length = strlen(dbname);
|
||||
lex_tablename.str = tablename;
|
||||
lex_tablename.length = strlen(tablename);
|
||||
|
||||
TABLE_CATEGORY tg = get_table_category(&lex_dbname, &lex_tablename);
|
||||
|
||||
return (tg == TABLE_CATEGORY_LOG) || (tg == TABLE_CATEGORY_SYSTEM);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Copy data file for backup. Also check if it is allowed to copy by
|
||||
@ -810,9 +922,8 @@ static
|
||||
bool
|
||||
datafile_copy_backup(ds_ctxt *ds_data, const char *filepath, uint thread_n)
|
||||
{
|
||||
const char *ext_list[] = {"frm", "isl", "MYD", "MYI", "MAD", "MAI",
|
||||
"MRG", "TRG", "TRN", "ARM", "ARZ", "CSM", "CSV", "opt", "par",
|
||||
NULL};
|
||||
const char *ext_list[] = {".frm", ".isl", ".TRG", ".TRN", ".opt", ".par",
|
||||
NULL};
|
||||
|
||||
/* Get the name and the path for the tablespace. node->name always
|
||||
contains the path (which may be absolute for remote tablespaces in
|
||||
@ -830,42 +941,7 @@ datafile_copy_backup(ds_ctxt *ds_data, const char *filepath, uint thread_n)
|
||||
|
||||
if (filename_matches(filepath, ext_list)) {
|
||||
return ds_data->copy_file(filepath, filepath, thread_n);
|
||||
}
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************
|
||||
Same as datafile_copy_backup, but put file name into the list for
|
||||
rsync command. */
|
||||
static
|
||||
bool
|
||||
datafile_rsync_backup(const char *filepath, bool save_to_list, FILE *f)
|
||||
{
|
||||
const char *ext_list[] = {"frm", "isl", "MYD", "MYI", "MAD", "MAI",
|
||||
"MRG", "TRG", "TRN", "ARM", "ARZ", "CSM", "CSV", "opt", "par",
|
||||
NULL};
|
||||
|
||||
/* Get the name and the path for the tablespace. node->name always
|
||||
contains the path (which may be absolute for remote tablespaces in
|
||||
5.6+). space->name contains the tablespace name in the form
|
||||
"./database/table.ibd" (in 5.5-) or "database/table" (in 5.6+). For a
|
||||
multi-node shared tablespace, space->name contains the name of the first
|
||||
node, but that's irrelevant, since we only need node_name to match them
|
||||
against filters, and the shared tablespace is always copied regardless
|
||||
of the filters value. */
|
||||
|
||||
if (check_if_skip_table(filepath)) {
|
||||
return(true);
|
||||
}
|
||||
|
||||
if (filename_matches(filepath, ext_list)) {
|
||||
fprintf(f, "%s\n", filepath);
|
||||
if (save_to_list) {
|
||||
rsync_list.insert(filepath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return(true);
|
||||
}
|
||||
@ -1004,16 +1080,15 @@ Copy file for backup/restore.
|
||||
bool
|
||||
ds_ctxt_t::copy_file(const char *src_file_path,
|
||||
const char *dst_file_path,
|
||||
uint thread_n)
|
||||
uint thread_n,
|
||||
bool rewrite)
|
||||
{
|
||||
char dst_name[FN_REFLEN];
|
||||
ds_file_t *dstfile = NULL;
|
||||
datafile_cur_t cursor;
|
||||
xb_fil_cur_result_t res;
|
||||
DBUG_ASSERT(datasink->remove);
|
||||
const char *dst_path =
|
||||
(xtrabackup_copy_back || xtrabackup_move_back)?
|
||||
dst_file_path : trim_dotslash(dst_file_path);
|
||||
const char *dst_path = convert_dst(dst_file_path);
|
||||
|
||||
if (!datafile_open(src_file_path, &cursor, thread_n)) {
|
||||
goto error_close;
|
||||
@ -1021,7 +1096,7 @@ ds_ctxt_t::copy_file(const char *src_file_path,
|
||||
|
||||
strncpy(dst_name, cursor.rel_path, sizeof(dst_name));
|
||||
|
||||
dstfile = ds_open(this, dst_path, &cursor.statinfo);
|
||||
dstfile = ds_open(this, dst_path, &cursor.statinfo, rewrite);
|
||||
if (dstfile == NULL) {
|
||||
msg(thread_n,"error: "
|
||||
"cannot open the destination stream for %s", dst_name);
|
||||
@ -1245,278 +1320,45 @@ cleanup:
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static
|
||||
bool
|
||||
backup_files(ds_ctxt *ds_data, const char *from, bool prep_mode)
|
||||
backup_files(ds_ctxt *ds_data, const char *from)
|
||||
{
|
||||
char rsync_tmpfile_name[FN_REFLEN];
|
||||
FILE *rsync_tmpfile = NULL;
|
||||
datadir_iter_t *it;
|
||||
datadir_node_t node;
|
||||
bool ret = true;
|
||||
|
||||
if (prep_mode && !opt_rsync) {
|
||||
return(true);
|
||||
}
|
||||
|
||||
if (opt_rsync) {
|
||||
snprintf(rsync_tmpfile_name, sizeof(rsync_tmpfile_name),
|
||||
"%s/%s%d", opt_mysql_tmpdir,
|
||||
"xtrabackup_rsyncfiles_pass",
|
||||
prep_mode ? 1 : 2);
|
||||
rsync_tmpfile = fopen(rsync_tmpfile_name, "w");
|
||||
if (rsync_tmpfile == NULL) {
|
||||
msg("Error: can't create file %s",
|
||||
rsync_tmpfile_name);
|
||||
return(false);
|
||||
}
|
||||
}
|
||||
|
||||
msg("Starting %s non-InnoDB tables and files",
|
||||
prep_mode ? "prep copy of" : "to backup");
|
||||
|
||||
msg("Starting to backup non-InnoDB tables and files");
|
||||
datadir_node_init(&node);
|
||||
it = datadir_iter_new(from);
|
||||
|
||||
while (datadir_iter_next(it, &node)) {
|
||||
|
||||
if (!node.is_empty_dir) {
|
||||
if (opt_rsync) {
|
||||
ret = datafile_rsync_backup(node.filepath,
|
||||
!prep_mode, rsync_tmpfile);
|
||||
} else {
|
||||
ret = datafile_copy_backup(ds_data, node.filepath, 1);
|
||||
}
|
||||
ret = datafile_copy_backup(ds_data, node.filepath, 1);
|
||||
if (!ret) {
|
||||
msg("Failed to copy file %s", node.filepath);
|
||||
goto out;
|
||||
}
|
||||
} else if (!prep_mode) {
|
||||
} else {
|
||||
/* backup fake file into empty directory */
|
||||
char path[FN_REFLEN];
|
||||
snprintf(path, sizeof(path),
|
||||
"%s/db.opt", node.filepath);
|
||||
if (!(ret = ds_data->backup_file_printf(
|
||||
trim_dotslash(path), "%s", ""))) {
|
||||
snprintf(path, sizeof(path), "%s/db.opt", node.filepath);
|
||||
if (!(ret = ds_data->backup_file_printf(trim_dotslash(path), "%s", ""))) {
|
||||
msg("Failed to create file %s", path);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (opt_rsync) {
|
||||
std::stringstream cmd;
|
||||
int err;
|
||||
|
||||
if (buffer_pool_filename && file_exists(buffer_pool_filename)) {
|
||||
fprintf(rsync_tmpfile, "%s\n", buffer_pool_filename);
|
||||
rsync_list.insert(buffer_pool_filename);
|
||||
}
|
||||
if (file_exists("ib_lru_dump")) {
|
||||
fprintf(rsync_tmpfile, "%s\n", "ib_lru_dump");
|
||||
rsync_list.insert("ib_lru_dump");
|
||||
}
|
||||
|
||||
fclose(rsync_tmpfile);
|
||||
rsync_tmpfile = NULL;
|
||||
|
||||
cmd << "rsync -t . --files-from=" << rsync_tmpfile_name
|
||||
<< " " << xtrabackup_target_dir;
|
||||
|
||||
msg("Starting rsync as: %s", cmd.str().c_str());
|
||||
if ((err = system(cmd.str().c_str()) && !prep_mode) != 0) {
|
||||
msg("Error: rsync failed with error code %d", err);
|
||||
ret = false;
|
||||
goto out;
|
||||
}
|
||||
msg("rsync finished successfully.");
|
||||
|
||||
if (!prep_mode && !opt_no_lock) {
|
||||
char path[FN_REFLEN];
|
||||
char dst_path[FN_REFLEN];
|
||||
char *newline;
|
||||
|
||||
/* Remove files that have been removed between first and
|
||||
second passes. Cannot use "rsync --delete" because it
|
||||
does not work with --files-from. */
|
||||
snprintf(rsync_tmpfile_name, sizeof(rsync_tmpfile_name),
|
||||
"%s/%s", opt_mysql_tmpdir,
|
||||
"xtrabackup_rsyncfiles_pass1");
|
||||
|
||||
rsync_tmpfile = fopen(rsync_tmpfile_name, "r");
|
||||
if (rsync_tmpfile == NULL) {
|
||||
msg("Error: can't open file %s",
|
||||
rsync_tmpfile_name);
|
||||
ret = false;
|
||||
goto out;
|
||||
}
|
||||
|
||||
while (fgets(path, sizeof(path), rsync_tmpfile)) {
|
||||
|
||||
newline = strchr(path, '\n');
|
||||
if (newline) {
|
||||
*newline = 0;
|
||||
}
|
||||
if (rsync_list.count(path) < 1) {
|
||||
snprintf(dst_path, sizeof(dst_path),
|
||||
"%s/%s", xtrabackup_target_dir,
|
||||
path);
|
||||
msg("Removing %s", dst_path);
|
||||
unlink(dst_path);
|
||||
}
|
||||
}
|
||||
|
||||
fclose(rsync_tmpfile);
|
||||
rsync_tmpfile = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
msg("Finished %s non-InnoDB tables and files",
|
||||
prep_mode ? "a prep copy of" : "backing up");
|
||||
|
||||
msg("Finished backing up non-InnoDB tables and files");
|
||||
out:
|
||||
datadir_iter_free(it);
|
||||
datadir_node_free(&node);
|
||||
|
||||
if (rsync_tmpfile != NULL) {
|
||||
fclose(rsync_tmpfile);
|
||||
}
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
lsn_t get_current_lsn(MYSQL *connection)
|
||||
{
|
||||
static const char lsn_prefix[] = "\nLog sequence number ";
|
||||
lsn_t lsn = 0;
|
||||
if (MYSQL_RES *res = xb_mysql_query(connection,
|
||||
"SHOW ENGINE INNODB STATUS",
|
||||
true, false)) {
|
||||
if (MYSQL_ROW row = mysql_fetch_row(res)) {
|
||||
const char *p= strstr(row[2], lsn_prefix);
|
||||
DBUG_ASSERT(p);
|
||||
if (p) {
|
||||
p += sizeof lsn_prefix - 1;
|
||||
lsn = lsn_t(strtoll(p, NULL, 10));
|
||||
}
|
||||
}
|
||||
mysql_free_result(res);
|
||||
}
|
||||
return lsn;
|
||||
}
|
||||
|
||||
lsn_t server_lsn_after_lock;
|
||||
extern void backup_wait_for_lsn(lsn_t lsn);
|
||||
/** Start --backup */
|
||||
bool backup_start(ds_ctxt *ds_data, ds_ctxt *ds_meta,
|
||||
CorruptedPages &corrupted_pages)
|
||||
{
|
||||
if (!opt_no_lock) {
|
||||
if (opt_safe_slave_backup) {
|
||||
if (!wait_for_safe_slave(mysql_connection)) {
|
||||
return(false);
|
||||
}
|
||||
}
|
||||
|
||||
if (!backup_files(ds_data, fil_path_to_mysql_datadir, true)) {
|
||||
return(false);
|
||||
}
|
||||
|
||||
history_lock_time = time(NULL);
|
||||
|
||||
if (!lock_tables(mysql_connection)) {
|
||||
return(false);
|
||||
}
|
||||
server_lsn_after_lock = get_current_lsn(mysql_connection);
|
||||
}
|
||||
|
||||
if (!backup_files(ds_data, fil_path_to_mysql_datadir, false)) {
|
||||
return(false);
|
||||
}
|
||||
|
||||
if (!backup_files_from_datadir(ds_data, fil_path_to_mysql_datadir,
|
||||
"aws-kms-key") ||
|
||||
!backup_files_from_datadir(ds_data,
|
||||
aria_log_dir_path,
|
||||
"aria_log")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (has_rocksdb_plugin()) {
|
||||
rocksdb_create_checkpoint();
|
||||
}
|
||||
|
||||
msg("Waiting for log copy thread to read lsn %llu", (ulonglong)server_lsn_after_lock);
|
||||
backup_wait_for_lsn(server_lsn_after_lock);
|
||||
DBUG_EXECUTE_FOR_KEY("sleep_after_waiting_for_lsn", {},
|
||||
{
|
||||
ulong milliseconds = strtoul(dbug_val, NULL, 10);
|
||||
msg("sleep_after_waiting_for_lsn");
|
||||
my_sleep(milliseconds*1000UL);
|
||||
});
|
||||
|
||||
corrupted_pages.backup_fix_ddl(ds_data, ds_meta);
|
||||
|
||||
// There is no need to stop slave thread before coping non-Innodb data when
|
||||
// --no-lock option is used because --no-lock option requires that no DDL or
|
||||
// DML to non-transaction tables can occur.
|
||||
if (opt_no_lock) {
|
||||
if (opt_safe_slave_backup) {
|
||||
if (!wait_for_safe_slave(mysql_connection)) {
|
||||
return(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (opt_slave_info) {
|
||||
lock_binlog_maybe(mysql_connection);
|
||||
|
||||
if (!write_slave_info(ds_data, mysql_connection)) {
|
||||
return(false);
|
||||
}
|
||||
}
|
||||
|
||||
/* The only reason why Galera/binlog info is written before
|
||||
wait_for_ibbackup_log_copy_finish() is that after that call the xtrabackup
|
||||
binary will start streamig a temporary copy of REDO log to stdout and
|
||||
thus, any streaming from innobackupex would interfere. The only way to
|
||||
avoid that is to have a single process, i.e. merge innobackupex and
|
||||
xtrabackup. */
|
||||
if (opt_galera_info) {
|
||||
if (!write_galera_info(ds_data, mysql_connection)) {
|
||||
return(false);
|
||||
}
|
||||
}
|
||||
|
||||
if (opt_binlog_info == BINLOG_INFO_ON) {
|
||||
|
||||
lock_binlog_maybe(mysql_connection);
|
||||
write_binlog_info(ds_data, mysql_connection);
|
||||
}
|
||||
|
||||
if (!opt_no_lock) {
|
||||
msg("Executing FLUSH NO_WRITE_TO_BINLOG ENGINE LOGS...");
|
||||
xb_mysql_query(mysql_connection,
|
||||
"FLUSH NO_WRITE_TO_BINLOG ENGINE LOGS", false);
|
||||
}
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
/** Release resources after backup_start() */
|
||||
void backup_release()
|
||||
{
|
||||
/* release all locks */
|
||||
if (!opt_no_lock) {
|
||||
unlock_all(mysql_connection);
|
||||
history_lock_time = 0;
|
||||
} else {
|
||||
history_lock_time = time(NULL) - history_lock_time;
|
||||
}
|
||||
|
||||
if (opt_lock_ddl_per_table) {
|
||||
mdl_unlock_all();
|
||||
}
|
||||
@ -1534,7 +1376,7 @@ static const char *default_buffer_pool_file = "ib_buffer_pool";
|
||||
bool backup_finish(ds_ctxt *ds_data)
|
||||
{
|
||||
/* Copy buffer pool dump or LRU dump */
|
||||
if (!opt_rsync && opt_galera_info) {
|
||||
if (opt_galera_info) {
|
||||
if (buffer_pool_filename && file_exists(buffer_pool_filename)) {
|
||||
ds_data->copy_file(buffer_pool_filename, default_buffer_pool_file, 0);
|
||||
}
|
||||
@ -1922,7 +1764,8 @@ copy_back()
|
||||
|
||||
dst_dir = dst_dir_buf.make(srv_log_group_home_dir);
|
||||
|
||||
/* --backup generates a single ib_logfile0, which we must copy. */
|
||||
/* --backup generates a single LOG_FILE_NAME, which we must copy
|
||||
if it exists. */
|
||||
|
||||
ds_tmp = ds_create(dst_dir, DS_TYPE_LOCAL);
|
||||
if (!(ret = copy_or_move_file(ds_tmp, LOG_FILE_NAME, LOG_FILE_NAME,
|
||||
@ -2169,8 +2012,6 @@ decrypt_decompress()
|
||||
|
||||
it = datadir_iter_new(".", false);
|
||||
|
||||
ut_a(xtrabackup_parallel >= 0);
|
||||
|
||||
ret = run_data_threads(it, decrypt_decompress_thread_func,
|
||||
xtrabackup_parallel ? xtrabackup_parallel : 1);
|
||||
|
||||
@ -2192,9 +2033,9 @@ decrypt_decompress()
|
||||
Do not copy the Innodb files (ibdata1, redo log files),
|
||||
as this is done in a separate step.
|
||||
*/
|
||||
static bool backup_files_from_datadir(ds_ctxt_t *ds_data,
|
||||
const char *dir_path,
|
||||
const char *prefix)
|
||||
bool backup_files_from_datadir(ds_ctxt_t *ds_data,
|
||||
const char *dir_path,
|
||||
const char *prefix)
|
||||
{
|
||||
os_file_dir_t dir = os_file_opendir(dir_path);
|
||||
if (dir == IF_WIN(INVALID_HANDLE_VALUE, nullptr)) return false;
|
||||
@ -2218,10 +2059,6 @@ static bool backup_files_from_datadir(ds_ctxt_t *ds_data,
|
||||
pname = info.name;
|
||||
|
||||
if (!starts_with(pname, prefix))
|
||||
/* For ES exchange the above line with the following code:
|
||||
(!xtrabackup_prepare || !xtrabackup_incremental_dir ||
|
||||
!starts_with(pname, "aria_log")))
|
||||
*/
|
||||
continue;
|
||||
|
||||
if (xtrabackup_prepare && xtrabackup_incremental_dir &&
|
||||
@ -2244,7 +2081,7 @@ static int rocksdb_remove_checkpoint_directory()
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool has_rocksdb_plugin()
|
||||
bool has_rocksdb_plugin()
|
||||
{
|
||||
static bool first_time = true;
|
||||
static bool has_plugin= false;
|
||||
@ -2390,7 +2227,7 @@ static void rocksdb_unlock_checkpoint()
|
||||
#define MARIADB_CHECKPOINT_DIR "mariabackup-checkpoint"
|
||||
static char rocksdb_checkpoint_dir[FN_REFLEN];
|
||||
|
||||
static void rocksdb_create_checkpoint()
|
||||
void rocksdb_create_checkpoint()
|
||||
{
|
||||
MYSQL_RES *result = xb_mysql_query(mysql_connection, "SELECT @@rocksdb_datadir,@@datadir", true, true);
|
||||
MYSQL_ROW row = mysql_fetch_row(result);
|
||||
@ -2470,3 +2307,39 @@ static void rocksdb_copy_back(ds_ctxt *ds_data) {
|
||||
mkdirp(rocksdb_home_dir, 0777, MYF(0));
|
||||
ds_data->copy_or_move_dir(ROCKSDB_BACKUP_DIR, rocksdb_home_dir, xtrabackup_copy_back, xtrabackup_copy_back);
|
||||
}
|
||||
|
||||
void foreach_file_in_db_dirs(
|
||||
const char *dir_path, std::function<bool(const char *)> func) {
|
||||
DBUG_ASSERT(dir_path);
|
||||
|
||||
datadir_iter_t *it;
|
||||
datadir_node_t node;
|
||||
|
||||
datadir_node_init(&node);
|
||||
it = datadir_iter_new(dir_path);
|
||||
|
||||
while (datadir_iter_next(it, &node))
|
||||
if (!node.is_empty_dir && !func(node.filepath))
|
||||
break;
|
||||
|
||||
datadir_iter_free(it);
|
||||
datadir_node_free(&node);
|
||||
}
|
||||
|
||||
void foreach_file_in_datadir(
|
||||
const char *dir_path, std::function<bool(const char *)> func)
|
||||
{
|
||||
DBUG_ASSERT(dir_path);
|
||||
os_file_dir_t dir = os_file_opendir(dir_path);
|
||||
os_file_stat_t info;
|
||||
while (os_file_readdir_next_file(dir_path, dir, &info) == 0) {
|
||||
if (info.type != OS_FILE_TYPE_FILE)
|
||||
continue;
|
||||
const char *pname = strrchr(info.name, IF_WIN('\\', '/'));
|
||||
if (!pname)
|
||||
pname = info.name;
|
||||
if (!func(pname))
|
||||
break;
|
||||
}
|
||||
os_file_closedir(dir);
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
#ifndef XTRABACKUP_BACKUP_COPY_H
|
||||
#define XTRABACKUP_BACKUP_COPY_H
|
||||
|
||||
#include <functional>
|
||||
#include <my_global.h>
|
||||
#include <mysql.h>
|
||||
#include "datasink.h"
|
||||
@ -21,8 +22,7 @@ bool
|
||||
equal_paths(const char *first, const char *second);
|
||||
|
||||
/** Start --backup */
|
||||
bool backup_start(ds_ctxt *ds_data, ds_ctxt *ds_meta,
|
||||
CorruptedPages &corrupted_pages);
|
||||
bool backup_files(ds_ctxt *ds_data, const char *from);
|
||||
/** Release resources after backup_start() */
|
||||
void backup_release();
|
||||
/** Finish after backup_start() and backup_release() */
|
||||
@ -38,7 +38,25 @@ is_path_separator(char);
|
||||
bool
|
||||
directory_exists(const char *dir, bool create);
|
||||
|
||||
lsn_t
|
||||
get_current_lsn(MYSQL *connection);
|
||||
bool has_rocksdb_plugin();
|
||||
void rocksdb_create_checkpoint();
|
||||
void foreach_file_in_db_dirs(
|
||||
const char *dir_path, std::function<bool(const char *)> func);
|
||||
void foreach_file_in_datadir(
|
||||
const char *dir_path, std::function<bool(const char *)> func);
|
||||
bool ends_with(const char *str, const char *suffix);
|
||||
bool starts_with(const char *str, const char *prefix);
|
||||
void parse_db_table_from_file_path(
|
||||
const char *filepath, char *dbname, char *tablename);
|
||||
const char *trim_dotslash(const char *path);
|
||||
bool backup_files_from_datadir(ds_ctxt_t *ds_data,
|
||||
const char *dir_path,
|
||||
const char *prefix);
|
||||
|
||||
bool is_system_table(const char *dbname, const char *tablename);
|
||||
std::unique_ptr<std::vector<std::string>>
|
||||
find_files(const char *dir_path, const char *prefix, const char *suffix);
|
||||
bool file_exists(const char *filename);
|
||||
bool
|
||||
filename_matches(const char *filename, const char **ext_list);
|
||||
#endif
|
||||
|
@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
#include "my_dbug.h"
|
||||
|
||||
#ifndef DBUG_OFF
|
||||
char *dbug_mariabackup_get_val(const char *event, fil_space_t::name_type key);
|
||||
/*
|
||||
@ -14,11 +15,21 @@ To use this facility, you need to
|
||||
for the variable)
|
||||
3. start mariabackup with --dbug=+d,debug_mariabackup_events
|
||||
*/
|
||||
#define DBUG_EXECUTE_FOR_KEY(EVENT, KEY, CODE) \
|
||||
DBUG_EXECUTE_IF("mariabackup_inject_code", \
|
||||
{ char *dbug_val= dbug_mariabackup_get_val(EVENT, KEY); \
|
||||
if (dbug_val) CODE })
|
||||
extern void dbug_mariabackup_event(
|
||||
const char *event, const fil_space_t::name_type key, bool need_lock);
|
||||
#define DBUG_MARIABACKUP_EVENT(A, B) \
|
||||
DBUG_EXECUTE_IF("mariabackup_events", \
|
||||
dbug_mariabackup_event(A,B,false););
|
||||
#define DBUG_MARIABACKUP_EVENT_LOCK(A, B) \
|
||||
DBUG_EXECUTE_IF("mariabackup_events", \
|
||||
dbug_mariabackup_event(A,B, true););
|
||||
#define DBUG_EXECUTE_FOR_KEY(EVENT, KEY, CODE) \
|
||||
DBUG_EXECUTE_IF("mariabackup_inject_code", {\
|
||||
char *dbug_val = dbug_mariabackup_get_val(EVENT, KEY); \
|
||||
if (dbug_val && *dbug_val) CODE \
|
||||
})
|
||||
#else
|
||||
#define DBUG_MARIABACKUP_EVENT(A,B)
|
||||
#define DBUG_MARIABACKUP_EVENT_LOCK(A,B)
|
||||
#define DBUG_EXECUTE_FOR_KEY(EVENT, KEY, CODE)
|
||||
#endif
|
||||
|
||||
|
@ -60,10 +60,11 @@ Street, Fifth Floor, Boston, MA 02110-1335 USA
|
||||
#include "backup_copy.h"
|
||||
#include "backup_mysql.h"
|
||||
#include "mysqld.h"
|
||||
#include "xb_plugin.h"
|
||||
#include "encryption_plugin.h"
|
||||
#include <sstream>
|
||||
#include <sql_error.h>
|
||||
#include "page0zip.h"
|
||||
#include "backup_debug.h"
|
||||
|
||||
char *tool_name;
|
||||
char tool_args[2048];
|
||||
@ -71,7 +72,7 @@ char tool_args[2048];
|
||||
ulong mysql_server_version;
|
||||
|
||||
/* server capabilities */
|
||||
bool have_backup_locks = false;
|
||||
bool have_changed_page_bitmaps = false;
|
||||
bool have_lock_wait_timeout = false;
|
||||
bool have_galera_enabled = false;
|
||||
bool have_multi_threaded_slave = false;
|
||||
@ -251,13 +252,14 @@ struct mysql_variable {
|
||||
|
||||
|
||||
static
|
||||
void
|
||||
uint
|
||||
read_mysql_variables(MYSQL *connection, const char *query, mysql_variable *vars,
|
||||
bool vertical_result)
|
||||
{
|
||||
MYSQL_RES *mysql_result;
|
||||
MYSQL_ROW row;
|
||||
mysql_variable *var;
|
||||
uint n_values=0;
|
||||
|
||||
mysql_result = xb_mysql_query(connection, query, true);
|
||||
|
||||
@ -271,6 +273,7 @@ read_mysql_variables(MYSQL *connection, const char *query, mysql_variable *vars,
|
||||
if (strcmp(var->name, name) == 0
|
||||
&& value != NULL) {
|
||||
*(var->value) = strdup(value);
|
||||
n_values++;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -287,6 +290,7 @@ read_mysql_variables(MYSQL *connection, const char *query, mysql_variable *vars,
|
||||
if (strcmp(var->name, name) == 0
|
||||
&& value != NULL) {
|
||||
*(var->value) = strdup(value);
|
||||
n_values++;
|
||||
}
|
||||
}
|
||||
++i;
|
||||
@ -295,6 +299,7 @@ read_mysql_variables(MYSQL *connection, const char *query, mysql_variable *vars,
|
||||
}
|
||||
|
||||
mysql_free_result(mysql_result);
|
||||
return n_values;
|
||||
}
|
||||
|
||||
|
||||
@ -359,7 +364,6 @@ bool get_mysql_vars(MYSQL *connection)
|
||||
{
|
||||
char *gtid_mode_var= NULL;
|
||||
char *version_var= NULL;
|
||||
char *have_backup_locks_var= NULL;
|
||||
char *log_bin_var= NULL;
|
||||
char *lock_wait_timeout_var= NULL;
|
||||
char *wsrep_on_var= NULL;
|
||||
@ -384,7 +388,6 @@ bool get_mysql_vars(MYSQL *connection)
|
||||
bool ret= true;
|
||||
|
||||
mysql_variable mysql_vars[]= {
|
||||
{"have_backup_locks", &have_backup_locks_var},
|
||||
{"log_bin", &log_bin_var},
|
||||
{"lock_wait_timeout", &lock_wait_timeout_var},
|
||||
{"gtid_mode", >id_mode_var},
|
||||
@ -409,11 +412,6 @@ bool get_mysql_vars(MYSQL *connection)
|
||||
|
||||
read_mysql_variables(connection, "SHOW VARIABLES", mysql_vars, true);
|
||||
|
||||
if (have_backup_locks_var != NULL && !opt_no_backup_locks)
|
||||
{
|
||||
have_backup_locks= true;
|
||||
}
|
||||
|
||||
if (opt_binlog_info == BINLOG_INFO_AUTO)
|
||||
{
|
||||
if (log_bin_var != NULL && !strcmp(log_bin_var, "ON"))
|
||||
@ -867,11 +865,11 @@ static void stop_query_killer()
|
||||
|
||||
|
||||
/*********************************************************************//**
|
||||
Function acquires either a backup tables lock, if supported
|
||||
by the server, or a global read lock (FLUSH TABLES WITH READ LOCK)
|
||||
otherwise.
|
||||
Function acquires backup locks
|
||||
@returns true if lock acquired */
|
||||
bool lock_tables(MYSQL *connection)
|
||||
|
||||
bool
|
||||
lock_for_backup_stage_start(MYSQL *connection)
|
||||
{
|
||||
if (have_lock_wait_timeout || opt_lock_wait_timeout)
|
||||
{
|
||||
@ -884,12 +882,6 @@ bool lock_tables(MYSQL *connection)
|
||||
xb_mysql_query(connection, buf, false);
|
||||
}
|
||||
|
||||
if (have_backup_locks)
|
||||
{
|
||||
msg("Executing LOCK TABLES FOR BACKUP...");
|
||||
xb_mysql_query(connection, "LOCK TABLES FOR BACKUP", false);
|
||||
return (true);
|
||||
}
|
||||
|
||||
if (opt_lock_wait_timeout)
|
||||
{
|
||||
@ -914,8 +906,6 @@ bool lock_tables(MYSQL *connection)
|
||||
|
||||
xb_mysql_query(connection, "BACKUP STAGE START", true);
|
||||
DBUG_MARIABACKUP_EVENT("after_backup_stage_start", {});
|
||||
xb_mysql_query(connection, "BACKUP STAGE BLOCK_COMMIT", true);
|
||||
DBUG_MARIABACKUP_EVENT("after_backup_stage_block_commit", {});
|
||||
/* Set the maximum supported session value for
|
||||
lock_wait_timeout to prevent unnecessary timeouts when the
|
||||
global value is changed from the default */
|
||||
@ -931,24 +921,68 @@ bool lock_tables(MYSQL *connection)
|
||||
return (true);
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
If backup locks are used, execute LOCK BINLOG FOR BACKUP provided that we are
|
||||
not in the --no-lock mode and the lock has not been acquired already.
|
||||
@returns true if lock acquired */
|
||||
bool
|
||||
lock_binlog_maybe(MYSQL *connection)
|
||||
{
|
||||
if (have_backup_locks && !opt_no_lock && !binlog_locked) {
|
||||
msg("Executing LOCK BINLOG FOR BACKUP...");
|
||||
xb_mysql_query(connection, "LOCK BINLOG FOR BACKUP", false);
|
||||
binlog_locked = true;
|
||||
|
||||
return(true);
|
||||
lock_for_backup_stage_flush(MYSQL *connection) {
|
||||
if (opt_kill_long_queries_timeout) {
|
||||
start_query_killer();
|
||||
}
|
||||
|
||||
return(false);
|
||||
xb_mysql_query(connection, "BACKUP STAGE FLUSH", true);
|
||||
if (opt_kill_long_queries_timeout) {
|
||||
stop_query_killer();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
lock_for_backup_stage_block_ddl(MYSQL *connection) {
|
||||
if (opt_kill_long_queries_timeout) {
|
||||
start_query_killer();
|
||||
}
|
||||
xb_mysql_query(connection, "BACKUP STAGE BLOCK_DDL", true);
|
||||
DBUG_MARIABACKUP_EVENT("after_backup_stage_block_ddl", {});
|
||||
if (opt_kill_long_queries_timeout) {
|
||||
stop_query_killer();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
lock_for_backup_stage_commit(MYSQL *connection) {
|
||||
if (opt_kill_long_queries_timeout) {
|
||||
start_query_killer();
|
||||
}
|
||||
xb_mysql_query(connection, "BACKUP STAGE BLOCK_COMMIT", true);
|
||||
DBUG_MARIABACKUP_EVENT("after_backup_stage_block_commit", {});
|
||||
if (opt_kill_long_queries_timeout) {
|
||||
stop_query_killer();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool backup_lock(MYSQL *con, const char *table_name) {
|
||||
static const std::string backup_lock_prefix("BACKUP LOCK ");
|
||||
std::string backup_lock_query = backup_lock_prefix + table_name;
|
||||
xb_mysql_query(con, backup_lock_query.c_str(), true);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool backup_unlock(MYSQL *con) {
|
||||
xb_mysql_query(con, "BACKUP UNLOCK", true);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::unordered_set<std::string>
|
||||
get_tables_in_use(MYSQL *con) {
|
||||
std::unordered_set<std::string> result;
|
||||
MYSQL_RES *q_res =
|
||||
xb_mysql_query(con, "SHOW OPEN TABLES WHERE In_use = 1", true);
|
||||
while (MYSQL_ROW row = mysql_fetch_row(q_res)) {
|
||||
auto tk = table_key(row[0], row[1]);
|
||||
msg("Table %s is in use", tk.c_str());
|
||||
result.insert(std::move(tk));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Releases either global read lock acquired with FTWRL and the binlog
|
||||
@ -1383,77 +1417,12 @@ write_slave_info(ds_ctxt *datasink, MYSQL *connection)
|
||||
|
||||
|
||||
/*********************************************************************//**
|
||||
Retrieves MySQL Galera and
|
||||
saves it in a file. It also prints it to stdout. */
|
||||
Old function, not needed anymore with BACKUP LOCKS
|
||||
*/
|
||||
bool
|
||||
write_galera_info(ds_ctxt *datasink, MYSQL *connection)
|
||||
{
|
||||
char *state_uuid = NULL, *state_uuid55 = NULL;
|
||||
char *last_committed = NULL, *last_committed55 = NULL;
|
||||
char *domain_id = NULL, *domain_id55 = NULL;
|
||||
bool result;
|
||||
|
||||
mysql_variable status[] = {
|
||||
{"Wsrep_local_state_uuid", &state_uuid},
|
||||
{"wsrep_local_state_uuid", &state_uuid55},
|
||||
{"Wsrep_last_committed", &last_committed},
|
||||
{"wsrep_last_committed", &last_committed55},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
mysql_variable value[] = {
|
||||
{"Wsrep_gtid_domain_id", &domain_id},
|
||||
{"wsrep_gtid_domain_id", &domain_id55},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
/* When backup locks are supported by the server, we should skip
|
||||
creating xtrabackup_galera_info file on the backup stage, because
|
||||
wsrep_local_state_uuid and wsrep_last_committed will be inconsistent
|
||||
without blocking commits. The state file will be created on the prepare
|
||||
stage using the WSREP recovery procedure. */
|
||||
if (have_backup_locks) {
|
||||
return(true);
|
||||
}
|
||||
|
||||
read_mysql_variables(connection, "SHOW STATUS", status, true);
|
||||
|
||||
if ((state_uuid == NULL && state_uuid55 == NULL)
|
||||
|| (last_committed == NULL && last_committed55 == NULL)) {
|
||||
msg("Warning: failed to get master wsrep state from SHOW STATUS.");
|
||||
result = true;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
read_mysql_variables(connection, "SHOW VARIABLES LIKE 'wsrep%'", value, true);
|
||||
|
||||
if (domain_id == NULL && domain_id55 == NULL) {
|
||||
msg("Warning: failed to get master wsrep state from SHOW VARIABLES.");
|
||||
result = true;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
result = datasink->backup_file_printf(XTRABACKUP_GALERA_INFO,
|
||||
"%s:%s %s\n", state_uuid ? state_uuid : state_uuid55,
|
||||
last_committed ? last_committed : last_committed55,
|
||||
domain_id ? domain_id : domain_id55);
|
||||
|
||||
if (result)
|
||||
{
|
||||
result= datasink->backup_file_printf(XTRABACKUP_DONOR_GALERA_INFO,
|
||||
"%s:%s %s\n", state_uuid ? state_uuid : state_uuid55,
|
||||
last_committed ? last_committed : last_committed55,
|
||||
domain_id ? domain_id : domain_id55);
|
||||
}
|
||||
if (result)
|
||||
{
|
||||
write_current_binlog_file(datasink, connection);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
free_mysql_variables(status);
|
||||
|
||||
return(result);
|
||||
return true; // Success
|
||||
}
|
||||
|
||||
|
||||
@ -1496,8 +1465,6 @@ write_current_binlog_file(ds_ctxt *datasink, MYSQL *connection)
|
||||
if (gtid_exists) {
|
||||
size_t log_bin_dir_length;
|
||||
|
||||
lock_binlog_maybe(connection);
|
||||
|
||||
xb_mysql_query(connection, "FLUSH BINARY LOGS", false);
|
||||
|
||||
read_mysql_variables(connection, "SHOW MASTER STATUS",
|
||||
@ -1856,13 +1823,13 @@ bool write_backup_config_file(ds_ctxt *datasink)
|
||||
srv_log_file_size,
|
||||
srv_page_size,
|
||||
srv_undo_dir,
|
||||
srv_undo_tablespaces,
|
||||
(uint) srv_undo_tablespaces,
|
||||
page_zip_level,
|
||||
innobase_buffer_pool_filename ?
|
||||
"innodb_buffer_pool_filename=" : "",
|
||||
innobase_buffer_pool_filename ?
|
||||
innobase_buffer_pool_filename : "",
|
||||
xb_plugin_get_config());
|
||||
encryption_plugin_get_config());
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -1987,3 +1954,23 @@ mdl_unlock_all()
|
||||
mysql_close(mdl_con);
|
||||
spaceid_to_tablename.clear();
|
||||
}
|
||||
|
||||
ulonglong get_current_lsn(MYSQL *connection)
|
||||
{
|
||||
static const char lsn_prefix[] = "\nLog sequence number ";
|
||||
ulonglong lsn = 0;
|
||||
if (MYSQL_RES *res = xb_mysql_query(connection,
|
||||
"SHOW ENGINE INNODB STATUS",
|
||||
true, false)) {
|
||||
if (MYSQL_ROW row = mysql_fetch_row(res)) {
|
||||
const char *p= strstr(row[2], lsn_prefix);
|
||||
DBUG_ASSERT(p);
|
||||
if (p) {
|
||||
p += sizeof lsn_prefix - 1;
|
||||
lsn = lsn_t(strtoll(p, NULL, 10));
|
||||
}
|
||||
}
|
||||
mysql_free_result(res);
|
||||
}
|
||||
return lsn;
|
||||
}
|
||||
|
@ -2,12 +2,15 @@
|
||||
#define XTRABACKUP_BACKUP_MYSQL_H
|
||||
|
||||
#include <mysql.h>
|
||||
#include <string>
|
||||
#include <unordered_set>
|
||||
#include "datasink.h"
|
||||
|
||||
/* MariaDB version */
|
||||
extern ulong mysql_server_version;
|
||||
|
||||
/* server capabilities */
|
||||
extern bool have_backup_locks;
|
||||
extern bool have_changed_page_bitmaps;
|
||||
extern bool have_lock_wait_timeout;
|
||||
extern bool have_galera_enabled;
|
||||
extern bool have_multi_threaded_slave;
|
||||
@ -71,7 +74,21 @@ bool
|
||||
lock_binlog_maybe(MYSQL *connection);
|
||||
|
||||
bool
|
||||
lock_tables(MYSQL *connection);
|
||||
lock_for_backup_stage_start(MYSQL *connection);
|
||||
|
||||
bool
|
||||
lock_for_backup_stage_flush(MYSQL *connection);
|
||||
|
||||
bool
|
||||
lock_for_backup_stage_block_ddl(MYSQL *connection);
|
||||
|
||||
bool
|
||||
lock_for_backup_stage_commit(MYSQL *connection);
|
||||
|
||||
bool backup_lock(MYSQL *con, const char *table_name);
|
||||
bool backup_unlock(MYSQL *con);
|
||||
|
||||
std::unordered_set<std::string> get_tables_in_use(MYSQL *con);
|
||||
|
||||
bool
|
||||
wait_for_safe_slave(MYSQL *connection);
|
||||
@ -82,5 +99,6 @@ write_galera_info(ds_ctxt *datasink, MYSQL *connection);
|
||||
bool
|
||||
write_slave_info(ds_ctxt *datasink, MYSQL *connection);
|
||||
|
||||
ulonglong get_current_lsn(MYSQL *connection);
|
||||
|
||||
#endif
|
||||
|
512
extra/mariabackup/common_engine.cc
Normal file
512
extra/mariabackup/common_engine.cc
Normal file
@ -0,0 +1,512 @@
|
||||
#include "common_engine.h"
|
||||
#include "backup_copy.h"
|
||||
#include "xtrabackup.h"
|
||||
#include "common.h"
|
||||
#include "backup_debug.h"
|
||||
|
||||
#include <unordered_map>
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <chrono>
|
||||
|
||||
namespace common_engine {
|
||||
|
||||
class Table {
|
||||
public:
|
||||
Table(std::string &db, std::string &table, std::string &fs_name) :
|
||||
m_db(std::move(db)), m_table(std::move(table)),
|
||||
m_fs_name(std::move(fs_name)) {}
|
||||
virtual ~Table() {}
|
||||
void add_file_name(const char *file_name) { m_fnames.push_back(file_name); }
|
||||
virtual bool copy(ds_ctxt_t *ds, MYSQL *con, bool no_lock,
|
||||
bool finalize, unsigned thread_num);
|
||||
std::string &get_db() { return m_db; }
|
||||
std::string &get_table() { return m_table; }
|
||||
std::string &get_version() { return m_version; }
|
||||
|
||||
protected:
|
||||
std::string m_db;
|
||||
std::string m_table;
|
||||
std::string m_fs_name;
|
||||
std::string m_version;
|
||||
std::vector<std::string> m_fnames;
|
||||
};
|
||||
|
||||
bool
|
||||
Table::copy(ds_ctxt_t *ds, MYSQL *con, bool no_lock, bool, unsigned thread_num) {
|
||||
static const size_t buf_size = 10 * 1024 * 1024;
|
||||
std::unique_ptr<uchar[]> buf;
|
||||
bool result = false;
|
||||
File frm_file = -1;
|
||||
std::vector<File> files;
|
||||
bool locked = false;
|
||||
std::string full_tname("`");
|
||||
full_tname.append(m_db).append("`.`").append(m_table).append("`");
|
||||
|
||||
if (!no_lock && !backup_lock(con, full_tname.c_str())) {
|
||||
msg(thread_num, "Error on executing BACKUP LOCK for table %s",
|
||||
full_tname.c_str());
|
||||
goto exit;
|
||||
}
|
||||
else
|
||||
locked = !no_lock;
|
||||
|
||||
if ((frm_file = mysql_file_open(key_file_frm, (m_fs_name + ".frm").c_str(),
|
||||
O_RDONLY | O_SHARE, MYF(0))) < 0 && !m_fnames.empty() &&
|
||||
!ends_with(m_fnames[0].c_str(), ".ARZ") &&
|
||||
!ends_with(m_fnames[0].c_str(), ".ARM")) {
|
||||
// Don't treat it as error, as the table can be dropped after it
|
||||
// was added to queue for copying
|
||||
result = true;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
for (const auto &fname : m_fnames) {
|
||||
File file = mysql_file_open(0, fname.c_str(),O_RDONLY | O_SHARE, MYF(0));
|
||||
if (file < 0) {
|
||||
msg(thread_num, "Error on file %s open during %s table copy",
|
||||
fname.c_str(), full_tname.c_str());
|
||||
goto exit;
|
||||
}
|
||||
files.push_back(file);
|
||||
}
|
||||
|
||||
if (locked && !backup_unlock(con)) {
|
||||
msg(thread_num, "Error on BACKUP UNLOCK for table %s", full_tname.c_str());
|
||||
locked = false;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
locked = false;
|
||||
|
||||
buf.reset(new uchar[buf_size]);
|
||||
|
||||
for (size_t i = 0; i < m_fnames.size(); ++i) {
|
||||
ds_file_t *dst_file = nullptr;
|
||||
size_t bytes_read;
|
||||
size_t copied_size = 0;
|
||||
MY_STAT stat_info;
|
||||
|
||||
if (my_fstat(files[i], &stat_info, MYF(0))) {
|
||||
msg(thread_num, "error: failed to get stat info for file %s of "
|
||||
"table %s", m_fnames[i].c_str(), full_tname.c_str());
|
||||
goto exit;
|
||||
}
|
||||
|
||||
const char *dst_path =
|
||||
(xtrabackup_copy_back || xtrabackup_move_back) ?
|
||||
m_fnames[i].c_str() : trim_dotslash(m_fnames[i].c_str());
|
||||
|
||||
dst_file = ds_open(ds, dst_path, &stat_info, false);
|
||||
if (!dst_file) {
|
||||
msg(thread_num, "error: cannot open destination stream for %s, table %s",
|
||||
dst_path, full_tname.c_str());
|
||||
goto exit;
|
||||
}
|
||||
|
||||
while ((bytes_read = my_read(files[i], buf.get(), buf_size, MY_WME))) {
|
||||
if (bytes_read == size_t(-1)) {
|
||||
msg(thread_num, "error: file %s read for table %s",
|
||||
m_fnames[i].c_str(), full_tname.c_str());
|
||||
ds_close(dst_file);
|
||||
goto exit;
|
||||
}
|
||||
xtrabackup_io_throttling();
|
||||
if (ds_write(dst_file, buf.get(), bytes_read)) {
|
||||
msg(thread_num, "error: file %s write for table %s",
|
||||
dst_path, full_tname.c_str());
|
||||
ds_close(dst_file);
|
||||
goto exit;
|
||||
}
|
||||
copied_size += bytes_read;
|
||||
}
|
||||
mysql_file_close(files[i], MYF(MY_WME));
|
||||
files[i] = -1;
|
||||
ds_close(dst_file);
|
||||
msg(thread_num, "Copied file %s for table %s, %zu bytes",
|
||||
m_fnames[i].c_str(), full_tname.c_str(), copied_size);
|
||||
}
|
||||
|
||||
result = true;
|
||||
|
||||
#ifndef DBUG_OFF
|
||||
{
|
||||
std::string sql_name(m_db);
|
||||
sql_name.append("/").append(m_table);
|
||||
DBUG_MARIABACKUP_EVENT_LOCK("after_ce_table_copy", fil_space_t::name_type(sql_name.data(), sql_name.size()));
|
||||
}
|
||||
#endif // DBUG_OFF
|
||||
exit:
|
||||
if (frm_file >= 0) {
|
||||
m_version = ::read_table_version_id(frm_file);
|
||||
mysql_file_close(frm_file, MYF(MY_WME));
|
||||
}
|
||||
if (locked && !backup_unlock(con)) {
|
||||
msg(thread_num, "Error on BACKUP UNLOCK for table %s", full_tname.c_str());
|
||||
result = false;
|
||||
}
|
||||
for (auto file : files)
|
||||
if (file >= 0)
|
||||
mysql_file_close(file, MYF(MY_WME));
|
||||
return result;
|
||||
}
|
||||
|
||||
// Append-only tables
|
||||
class LogTable : public Table {
|
||||
public:
|
||||
LogTable(std::string &db, std::string &table, std::string &fs_name) :
|
||||
Table(db, table, fs_name) {}
|
||||
|
||||
virtual ~LogTable() { (void)close(); }
|
||||
bool
|
||||
copy(ds_ctxt_t *ds, MYSQL *con, bool no_lock, bool finalize,
|
||||
unsigned thread_num) override;
|
||||
bool close();
|
||||
private:
|
||||
bool open(ds_ctxt_t *ds, unsigned thread_num);
|
||||
std::vector<File> m_src;
|
||||
std::vector<ds_file_t *> m_dst;
|
||||
};
|
||||
|
||||
bool
|
||||
LogTable::open(ds_ctxt_t *ds, unsigned thread_num) {
|
||||
DBUG_ASSERT(m_src.empty());
|
||||
DBUG_ASSERT(m_dst.empty());
|
||||
|
||||
std::string full_tname("`");
|
||||
full_tname.append(m_db).append("`.`").append(m_table).append("`");
|
||||
|
||||
for (const auto &fname : m_fnames) {
|
||||
File file = mysql_file_open(0, fname.c_str(),O_RDONLY | O_SHARE, MYF(0));
|
||||
if (file < 0) {
|
||||
msg(thread_num, "Error on file %s open during %s log table copy",
|
||||
fname.c_str(), full_tname.c_str());
|
||||
return false;
|
||||
}
|
||||
m_src.push_back(file);
|
||||
|
||||
MY_STAT stat_info;
|
||||
if (my_fstat(file, &stat_info, MYF(0))) {
|
||||
msg(thread_num, "error: failed to get stat info for file %s of "
|
||||
"log table %s", fname.c_str(), full_tname.c_str());
|
||||
return false;
|
||||
}
|
||||
const char *dst_path =
|
||||
(xtrabackup_copy_back || xtrabackup_move_back) ?
|
||||
fname.c_str() : trim_dotslash(fname.c_str());
|
||||
ds_file_t *dst_file = ds_open(ds, dst_path, &stat_info, false);
|
||||
if (!dst_file) {
|
||||
msg(thread_num, "error: cannot open destination stream for %s, "
|
||||
"log table %s", dst_path, full_tname.c_str());
|
||||
return false;
|
||||
}
|
||||
m_dst.push_back(dst_file);
|
||||
}
|
||||
|
||||
File frm_file;
|
||||
if ((frm_file = mysql_file_open(key_file_frm, (m_fs_name + ".frm").c_str(),
|
||||
O_RDONLY | O_SHARE, MYF(0))) < 0 && !m_fnames.empty() &&
|
||||
!ends_with(m_fnames[0].c_str(), ".ARZ") &&
|
||||
!ends_with(m_fnames[0].c_str(), ".ARM")) {
|
||||
msg(thread_num, "Error on .frm file open for log table %s",
|
||||
full_tname.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
m_version = ::read_table_version_id(frm_file);
|
||||
mysql_file_close(frm_file, MYF(MY_WME));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LogTable::close() {
|
||||
while (!m_src.empty()) {
|
||||
auto f = m_src.back();
|
||||
m_src.pop_back();
|
||||
mysql_file_close(f, MYF(MY_WME));
|
||||
}
|
||||
while (!m_dst.empty()) {
|
||||
auto f = m_dst.back();
|
||||
m_dst.pop_back();
|
||||
ds_close(f);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
LogTable::copy(ds_ctxt_t *ds, MYSQL *con, bool no_lock, bool finalize,
|
||||
unsigned thread_num) {
|
||||
static const size_t buf_size = 10 * 1024 * 1024;
|
||||
DBUG_ASSERT(ds);
|
||||
DBUG_ASSERT(con);
|
||||
if (m_src.empty() && !open(ds, thread_num)) {
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
DBUG_ASSERT(m_src.size() == m_dst.size());
|
||||
|
||||
std::unique_ptr<uchar[]> buf(new uchar[buf_size]);
|
||||
for (size_t i = 0; i < m_src.size(); ++i) {
|
||||
// .CSM can be rewritten (see write_meta_file() usage in ha_tina.cc)
|
||||
if (!finalize && ends_with(m_fnames[i].c_str(), ".CSM"))
|
||||
continue;
|
||||
size_t bytes_read;
|
||||
size_t copied_size = 0;
|
||||
while ((bytes_read = my_read(m_src[i], buf.get(), buf_size, MY_WME))) {
|
||||
if (bytes_read == size_t(-1)) {
|
||||
msg(thread_num, "error: file %s read for log table %s",
|
||||
m_fnames[i].c_str(),
|
||||
std::string("`").append(m_db).append("`.`").
|
||||
append(m_table).append("`").c_str());
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
xtrabackup_io_throttling();
|
||||
if (ds_write(m_dst[i], buf.get(), bytes_read)) {
|
||||
msg(thread_num, "error: file %s write for log table %s",
|
||||
m_fnames[i].c_str(), std::string("`").append(m_db).append("`.`").
|
||||
append(m_table).append("`").c_str());
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
copied_size += bytes_read;
|
||||
}
|
||||
msg(thread_num, "Copied file %s for log table %s, %zu bytes",
|
||||
m_fnames[i].c_str(), std::string("`").append(m_db).append("`.`").
|
||||
append(m_table).append("`").c_str(), copied_size);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
class BackupImpl {
|
||||
public:
|
||||
BackupImpl(
|
||||
const char *datadir_path, ds_ctxt_t *datasink,
|
||||
std::vector<MYSQL *> &con_pool, ThreadPool &thread_pool) :
|
||||
m_datadir_path(datadir_path), m_ds(datasink), m_con_pool(con_pool),
|
||||
m_process_table_jobs(thread_pool) {}
|
||||
~BackupImpl() { }
|
||||
bool scan(
|
||||
const std::unordered_set<std::string> &exclude_tables,
|
||||
std::unordered_set<std::string> *out_processed_tables,
|
||||
bool no_lock, bool collect_log_and_stats);
|
||||
void set_post_copy_table_hook(const post_copy_table_hook_t &hook) {
|
||||
m_table_post_copy_hook = hook;
|
||||
}
|
||||
bool copy_log_tables(bool finalize);
|
||||
bool copy_stats_tables();
|
||||
bool wait_for_finish();
|
||||
bool close_log_tables();
|
||||
private:
|
||||
|
||||
void process_table_job(Table *table, bool no_lock, bool delete_table,
|
||||
bool finalize, unsigned thread_num);
|
||||
|
||||
const char *m_datadir_path;
|
||||
ds_ctxt_t *m_ds;
|
||||
std::vector<MYSQL *> &m_con_pool;
|
||||
TasksGroup m_process_table_jobs;
|
||||
|
||||
post_copy_table_hook_t m_table_post_copy_hook;
|
||||
std::unordered_map<table_key_t, std::unique_ptr<LogTable>> m_log_tables;
|
||||
std::unordered_map<table_key_t, std::unique_ptr<Table>> m_stats_tables;
|
||||
};
|
||||
|
||||
void BackupImpl::process_table_job(Table *table, bool no_lock,
|
||||
bool delete_table, bool finalize, unsigned thread_num) {
|
||||
int result = 0;
|
||||
|
||||
if (!m_process_table_jobs.get_result())
|
||||
goto exit;
|
||||
|
||||
if (!table->copy(m_ds, m_con_pool[thread_num], no_lock, finalize, thread_num))
|
||||
goto exit;
|
||||
|
||||
if (m_table_post_copy_hook)
|
||||
m_table_post_copy_hook(table->get_db(), table->get_table(),
|
||||
table->get_version());
|
||||
|
||||
result = 1;
|
||||
|
||||
exit:
|
||||
if (delete_table)
|
||||
delete table;
|
||||
m_process_table_jobs.finish_task(result);
|
||||
}
|
||||
|
||||
bool BackupImpl::scan(const std::unordered_set<table_key_t> &exclude_tables,
|
||||
std::unordered_set<table_key_t> *out_processed_tables, bool no_lock,
|
||||
bool collect_log_and_stats) {
|
||||
|
||||
msg("Start scanning common engine tables, need backup locks: %d, "
|
||||
"collect log and stat tables: %d", no_lock, collect_log_and_stats);
|
||||
|
||||
std::unordered_map<table_key_t, std::unique_ptr<Table>> found_tables;
|
||||
|
||||
foreach_file_in_db_dirs(m_datadir_path,
|
||||
[&](const char *file_path)->bool {
|
||||
|
||||
static const char *ext_list[] =
|
||||
{".MYD", ".MYI", ".MRG", ".ARM", ".ARZ", ".CSM", ".CSV", NULL};
|
||||
|
||||
bool is_aria = ends_with(file_path, ".MAD") || ends_with(file_path, ".MAI");
|
||||
|
||||
if (!collect_log_and_stats && is_aria)
|
||||
return true;
|
||||
|
||||
if (!is_aria && !filename_matches(file_path, ext_list))
|
||||
return true;
|
||||
|
||||
if (check_if_skip_table(file_path)) {
|
||||
msg("Skipping %s.", file_path);
|
||||
return true;
|
||||
}
|
||||
|
||||
auto db_table_fs = convert_filepath_to_tablename(file_path);
|
||||
auto tk =
|
||||
table_key(std::get<0>(db_table_fs), std::get<1>(db_table_fs));
|
||||
|
||||
// log and stats tables are only collected in this function,
|
||||
// so there is no need to filter out them with exclude_tables.
|
||||
if (collect_log_and_stats) {
|
||||
if (is_log_table(std::get<0>(db_table_fs).c_str(),
|
||||
std::get<1>(db_table_fs).c_str())) {
|
||||
auto table_it = m_log_tables.find(tk);
|
||||
if (table_it == m_log_tables.end()) {
|
||||
msg("Log table found: %s", tk.c_str());
|
||||
table_it = m_log_tables.emplace(tk,
|
||||
std::unique_ptr<LogTable>(new LogTable(std::get<0>(db_table_fs),
|
||||
std::get<1>(db_table_fs), std::get<2>(db_table_fs)))).first;
|
||||
}
|
||||
msg("Collect log table file: %s", file_path);
|
||||
table_it->second->add_file_name(file_path);
|
||||
return true;
|
||||
}
|
||||
// Aria can handle statistics tables
|
||||
else if (is_stats_table(std::get<0>(db_table_fs).c_str(),
|
||||
std::get<1>(db_table_fs).c_str()) && !is_aria) {
|
||||
auto table_it = m_stats_tables.find(tk);
|
||||
if (table_it == m_stats_tables.end()) {
|
||||
msg("Stats table found: %s", tk.c_str());
|
||||
table_it = m_stats_tables.emplace(tk,
|
||||
std::unique_ptr<Table>(new Table(std::get<0>(db_table_fs),
|
||||
std::get<1>(db_table_fs), std::get<2>(db_table_fs)))).first;
|
||||
}
|
||||
msg("Collect stats table file: %s", file_path);
|
||||
table_it->second->add_file_name(file_path);
|
||||
return true;
|
||||
}
|
||||
} else if (is_log_table(std::get<0>(db_table_fs).c_str(),
|
||||
std::get<1>(db_table_fs).c_str()) ||
|
||||
is_stats_table(std::get<0>(db_table_fs).c_str(),
|
||||
std::get<1>(db_table_fs).c_str()))
|
||||
return true;
|
||||
|
||||
if (is_aria)
|
||||
return true;
|
||||
|
||||
if (exclude_tables.count(tk)) {
|
||||
msg("Skip table %s at it is in exclude list", tk.c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
auto table_it = found_tables.find(tk);
|
||||
if (table_it == found_tables.end()) {
|
||||
table_it = found_tables.emplace(tk,
|
||||
std::unique_ptr<Table>(new Table(std::get<0>(db_table_fs),
|
||||
std::get<1>(db_table_fs), std::get<2>(db_table_fs)))).first;
|
||||
}
|
||||
|
||||
table_it->second->add_file_name(file_path);
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
for (auto &table_it : found_tables) {
|
||||
m_process_table_jobs.push_task(
|
||||
std::bind(&BackupImpl::process_table_job, this, table_it.second.release(),
|
||||
no_lock, true, false, std::placeholders::_1));
|
||||
if (out_processed_tables)
|
||||
out_processed_tables->insert(table_it.first);
|
||||
}
|
||||
|
||||
msg("Stop scanning common engine tables");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BackupImpl::copy_log_tables(bool finalize) {
|
||||
for (auto &table_it : m_log_tables) {
|
||||
// Do not execute BACKUP LOCK for log tables as it's supposed
|
||||
// that they must be copied on BLOCK_DDL and BLOCK_COMMIT locks.
|
||||
m_process_table_jobs.push_task(
|
||||
std::bind(&BackupImpl::process_table_job, this, table_it.second.get(),
|
||||
true, false, finalize, std::placeholders::_1));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BackupImpl::copy_stats_tables() {
|
||||
for (auto &table_it : m_stats_tables) {
|
||||
// Do not execute BACKUP LOCK for stats tables as it's supposed
|
||||
// that they must be copied on BLOCK_DDL and BLOCK_COMMIT locks.
|
||||
// Delete stats table object after copy (see process_table_job())
|
||||
m_process_table_jobs.push_task(
|
||||
std::bind(&BackupImpl::process_table_job, this, table_it.second.release(),
|
||||
true, true, false, std::placeholders::_1));
|
||||
}
|
||||
m_stats_tables.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BackupImpl::wait_for_finish() {
|
||||
/* Wait for threads to exit */
|
||||
return m_process_table_jobs.wait_for_finish();
|
||||
}
|
||||
|
||||
bool BackupImpl::close_log_tables() {
|
||||
bool result = wait_for_finish();
|
||||
for (auto &table_it : m_log_tables)
|
||||
table_it.second->close();
|
||||
return result;
|
||||
}
|
||||
|
||||
Backup::Backup(const char *datadir_path, ds_ctxt_t *datasink,
|
||||
std::vector<MYSQL *> &con_pool, ThreadPool &thread_pool) :
|
||||
m_backup_impl(
|
||||
new BackupImpl(datadir_path, datasink, con_pool,
|
||||
thread_pool)) { }
|
||||
|
||||
Backup::~Backup() {
|
||||
delete m_backup_impl;
|
||||
}
|
||||
|
||||
bool Backup::scan(
|
||||
const std::unordered_set<table_key_t> &exclude_tables,
|
||||
std::unordered_set<table_key_t> *out_processed_tables,
|
||||
bool no_lock, bool collect_log_and_stats) {
|
||||
return m_backup_impl->scan(exclude_tables, out_processed_tables, no_lock,
|
||||
collect_log_and_stats);
|
||||
}
|
||||
|
||||
bool Backup::copy_log_tables(bool finalize) {
|
||||
return m_backup_impl->copy_log_tables(finalize);
|
||||
}
|
||||
|
||||
bool Backup::copy_stats_tables() {
|
||||
return m_backup_impl->copy_stats_tables();
|
||||
}
|
||||
|
||||
bool Backup::wait_for_finish() {
|
||||
return m_backup_impl->wait_for_finish();
|
||||
}
|
||||
|
||||
bool Backup::close_log_tables() {
|
||||
return m_backup_impl->close_log_tables();
|
||||
}
|
||||
|
||||
void Backup::set_post_copy_table_hook(const post_copy_table_hook_t &hook) {
|
||||
m_backup_impl->set_post_copy_table_hook(hook);
|
||||
}
|
||||
|
||||
} // namespace common_engine
|
39
extra/mariabackup/common_engine.h
Normal file
39
extra/mariabackup/common_engine.h
Normal file
@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
#include "my_global.h"
|
||||
#include "backup_mysql.h"
|
||||
#include "datasink.h"
|
||||
#include "thread_pool.h"
|
||||
#include "xtrabackup.h"
|
||||
|
||||
#include <unordered_set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace common_engine {
|
||||
|
||||
class BackupImpl;
|
||||
|
||||
class Backup {
|
||||
public:
|
||||
Backup(const char *datadir_path, ds_ctxt_t *datasink,
|
||||
std::vector<MYSQL *> &con_pool, ThreadPool &thread_pool);
|
||||
~Backup();
|
||||
Backup (Backup &&other) = delete;
|
||||
Backup & operator= (Backup &&other) = delete;
|
||||
Backup(const Backup &) = delete;
|
||||
Backup & operator= (const Backup &) = delete;
|
||||
bool scan(
|
||||
const std::unordered_set<table_key_t> &exclude_tables,
|
||||
std::unordered_set<table_key_t> *out_processed_tables,
|
||||
bool no_lock, bool collect_log_and_stats);
|
||||
bool copy_log_tables(bool finalize);
|
||||
bool copy_stats_tables();
|
||||
bool wait_for_finish();
|
||||
bool close_log_tables();
|
||||
void set_post_copy_table_hook(const post_copy_table_hook_t &hook);
|
||||
private:
|
||||
BackupImpl *m_backup_impl;
|
||||
};
|
||||
|
||||
} // namespace common_engine
|
||||
|
@ -80,11 +80,11 @@ ds_create(const char *root, ds_type_t type)
|
||||
/************************************************************************
|
||||
Open a datasink file */
|
||||
ds_file_t *
|
||||
ds_open(ds_ctxt_t *ctxt, const char *path, MY_STAT *stat)
|
||||
ds_open(ds_ctxt_t *ctxt, const char *path, const MY_STAT *stat, bool rewrite)
|
||||
{
|
||||
ds_file_t *file;
|
||||
|
||||
file = ctxt->datasink->open(ctxt, path, stat);
|
||||
file = ctxt->datasink->open(ctxt, path, stat, rewrite);
|
||||
if (file != NULL) {
|
||||
file->datasink = ctxt->datasink;
|
||||
}
|
||||
@ -104,6 +104,30 @@ ds_write(ds_file_t *file, const void *buf, size_t len)
|
||||
return file->datasink->write(file, (const uchar *)buf, len);
|
||||
}
|
||||
|
||||
int ds_seek_set(ds_file_t *file, my_off_t offset) {
|
||||
DBUG_ASSERT(file);
|
||||
DBUG_ASSERT(file->datasink);
|
||||
if (file->datasink->seek_set)
|
||||
return file->datasink->seek_set(file, offset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ds_rename(ds_ctxt_t *ctxt, const char *old_path, const char *new_path) {
|
||||
DBUG_ASSERT(ctxt);
|
||||
DBUG_ASSERT(ctxt->datasink);
|
||||
if (ctxt->datasink->rename)
|
||||
return ctxt->datasink->rename(ctxt, old_path, new_path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ds_remove(ds_ctxt_t *ctxt, const char *path) {
|
||||
DBUG_ASSERT(ctxt);
|
||||
DBUG_ASSERT(ctxt->datasink);
|
||||
if (ctxt->datasink->remove)
|
||||
return ctxt->datasink->mremove(ctxt, path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Close a datasink file.
|
||||
@return 0 on success, 1, on error. */
|
||||
|
@ -43,7 +43,8 @@ typedef struct ds_ctxt {
|
||||
*/
|
||||
bool copy_file(const char *src_file_path,
|
||||
const char *dst_file_path,
|
||||
uint thread_n);
|
||||
uint thread_n,
|
||||
bool rewrite = false);
|
||||
|
||||
bool move_file(const char *src_file_path,
|
||||
const char *dst_file_path,
|
||||
@ -76,10 +77,15 @@ typedef struct {
|
||||
|
||||
struct datasink_struct {
|
||||
ds_ctxt_t *(*init)(const char *root);
|
||||
ds_file_t *(*open)(ds_ctxt_t *ctxt, const char *path, MY_STAT *stat);
|
||||
ds_file_t *(*open)(ds_ctxt_t *ctxt, const char *path,
|
||||
const MY_STAT *stat, bool rewrite);
|
||||
int (*write)(ds_file_t *file, const unsigned char *buf, size_t len);
|
||||
int (*seek_set)(ds_file_t *file, my_off_t offset);
|
||||
int (*close)(ds_file_t *file);
|
||||
int (*remove)(const char *path);
|
||||
// TODO: consider to return bool from "rename" and "remove"
|
||||
int (*rename)(ds_ctxt_t *ctxt, const char *old_path, const char *new_path);
|
||||
int (*mremove)(ds_ctxt_t *ctxt, const char *path);
|
||||
void (*deinit)(ds_ctxt_t *ctxt);
|
||||
};
|
||||
|
||||
@ -106,12 +112,17 @@ ds_ctxt_t *ds_create(const char *root, ds_type_t type);
|
||||
|
||||
/************************************************************************
|
||||
Open a datasink file */
|
||||
ds_file_t *ds_open(ds_ctxt_t *ctxt, const char *path, MY_STAT *stat);
|
||||
ds_file_t *ds_open(
|
||||
ds_ctxt_t *ctxt, const char *path, const MY_STAT *stat, bool rewrite = false);
|
||||
|
||||
/************************************************************************
|
||||
Write to a datasink file.
|
||||
@return 0 on success, 1 on error. */
|
||||
int ds_write(ds_file_t *file, const void *buf, size_t len);
|
||||
int ds_seek_set(ds_file_t *file, my_off_t offset);
|
||||
|
||||
int ds_rename(ds_ctxt_t *ctxt, const char *old_path, const char *new_path);
|
||||
int ds_remove(ds_ctxt_t *ctxt, const char *path);
|
||||
|
||||
/************************************************************************
|
||||
Close a datasink file.
|
||||
|
553
extra/mariabackup/ddl_log.cc
Normal file
553
extra/mariabackup/ddl_log.cc
Normal file
@ -0,0 +1,553 @@
|
||||
#include "ddl_log.h"
|
||||
#include "common.h"
|
||||
#include "my_sys.h"
|
||||
#include "sql_table.h"
|
||||
#include "backup_copy.h"
|
||||
#include "xtrabackup.h"
|
||||
#include <unordered_set>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <cstddef>
|
||||
|
||||
namespace ddl_log {
|
||||
|
||||
struct Entry {
|
||||
enum Type {
|
||||
CREATE,
|
||||
ALTER,
|
||||
RENAME,
|
||||
REPAIR,
|
||||
OPTIMIZE,
|
||||
DROP,
|
||||
TRUNCATE,
|
||||
CHANGE_INDEX,
|
||||
BULK_INSERT
|
||||
};
|
||||
Type type;
|
||||
std::string date;
|
||||
std::string engine;
|
||||
bool partitioned;
|
||||
std::string db;
|
||||
std::string table;
|
||||
std::string id;
|
||||
std::string new_engine;
|
||||
bool new_partitioned;
|
||||
std::string new_db;
|
||||
std::string new_table;
|
||||
std::string new_id;
|
||||
};
|
||||
|
||||
typedef std::vector<std::unique_ptr<Entry>> entries_t;
|
||||
typedef std::function<bool(std::unique_ptr<Entry>)> store_entry_func_t;
|
||||
|
||||
const char *aria_engine_name = "Aria";
|
||||
static const char *frm_ext = ".frm";
|
||||
static const char *database_keyword = "DATABASE";
|
||||
|
||||
const std::unordered_map<std::string, std::vector<const char *>> engine_exts =
|
||||
{
|
||||
{"Aria", {".MAD", ".MAI"}},
|
||||
{"MyISAM", {".MYD", ".MYI"}},
|
||||
{"MRG_MyISAM", {".MRG"}},
|
||||
{"ARCHIVE", {".ARM", ".ARZ"}},
|
||||
{"CSV", {".CSM", ".CSV"}}
|
||||
};
|
||||
|
||||
static inline bool known_engine(const std::string &engine) {
|
||||
return engine_exts.count(engine);
|
||||
}
|
||||
|
||||
// TODO: add error messages
|
||||
size_t parse(const uchar *buf, size_t buf_size, bool &error_flag,
|
||||
store_entry_func_t &store_entry_func) {
|
||||
DBUG_ASSERT(buf);
|
||||
static constexpr char token_delimiter = '\t';
|
||||
static constexpr char line_delimiter = '\n';
|
||||
enum {
|
||||
TOKEN_FIRST = 0,
|
||||
TOKEN_DATE = TOKEN_FIRST,
|
||||
TOKEN_TYPE,
|
||||
TOKEN_ENGINE,
|
||||
TOKEN_PARTITIONED,
|
||||
TOKEN_DB,
|
||||
TOKEN_TABLE,
|
||||
TOKEN_ID,
|
||||
TOKEN_MANDATORY = TOKEN_ID,
|
||||
TOKEN_NEW_ENGINE,
|
||||
TOKEN_NEW_PARTITIONED,
|
||||
TOKEN_NEW_DB,
|
||||
TOKEN_NEW_TABLE,
|
||||
TOKEN_NEW_ID,
|
||||
TOKEN_LAST = TOKEN_NEW_ID
|
||||
};
|
||||
const size_t string_offsets[TOKEN_LAST + 1] = {
|
||||
offsetof(Entry, date),
|
||||
offsetof(Entry, type), // not a string, be careful
|
||||
offsetof(Entry, engine),
|
||||
offsetof(Entry, partitioned), // not a string, be careful
|
||||
offsetof(Entry, db),
|
||||
offsetof(Entry, table),
|
||||
offsetof(Entry, id),
|
||||
offsetof(Entry, new_engine),
|
||||
offsetof(Entry, new_partitioned), // not a string, be careful
|
||||
offsetof(Entry, new_db),
|
||||
offsetof(Entry, new_table),
|
||||
offsetof(Entry, new_id)
|
||||
};
|
||||
const std::unordered_map<std::string, Entry::Type> str_to_type = {
|
||||
{"CREATE", Entry::CREATE},
|
||||
{"ALTER", Entry::ALTER},
|
||||
{"RENAME", Entry::RENAME},
|
||||
// TODO: fix to use uppercase-only
|
||||
{"repair", Entry::REPAIR},
|
||||
{"optimize", Entry::OPTIMIZE},
|
||||
{"DROP", Entry::DROP},
|
||||
{"TRUNCATE", Entry::TRUNCATE},
|
||||
{"CHANGE_INDEX", Entry::CHANGE_INDEX},
|
||||
{"BULK_INSERT", Entry::BULK_INSERT}
|
||||
};
|
||||
|
||||
const uchar *new_line = buf;
|
||||
const uchar *token_start = buf;
|
||||
unsigned token_num = TOKEN_FIRST;
|
||||
|
||||
error_flag = false;
|
||||
|
||||
std::unique_ptr<Entry> entry(new Entry());
|
||||
|
||||
for (const uchar *ptr = buf; ptr < buf + buf_size; ++ptr) {
|
||||
|
||||
if (*ptr != token_delimiter && *ptr != line_delimiter)
|
||||
continue;
|
||||
|
||||
if (token_start != ptr) {
|
||||
std::string token(token_start, ptr);
|
||||
|
||||
if (token_num == TOKEN_TYPE) {
|
||||
const auto type_it = str_to_type.find(token);
|
||||
if (type_it == str_to_type.end()) {
|
||||
error_flag = true;
|
||||
goto exit;
|
||||
}
|
||||
entry->type = type_it->second;
|
||||
}
|
||||
else if (token_num == TOKEN_PARTITIONED) {
|
||||
entry->partitioned = token[0] - '0';
|
||||
}
|
||||
else if (token_num == TOKEN_NEW_PARTITIONED) {
|
||||
entry->new_partitioned = token[0] - '0';
|
||||
}
|
||||
else if (token_num <= TOKEN_LAST) {
|
||||
DBUG_ASSERT(token_num != TOKEN_TYPE);
|
||||
DBUG_ASSERT(token_num != TOKEN_PARTITIONED);
|
||||
DBUG_ASSERT(token_num != TOKEN_NEW_PARTITIONED);
|
||||
reinterpret_cast<std::string *>
|
||||
(reinterpret_cast<uchar *>(entry.get()) + string_offsets[token_num])->
|
||||
assign(std::move(token));
|
||||
}
|
||||
else {
|
||||
error_flag = true;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
token_start = ptr + 1;
|
||||
|
||||
if (*ptr == line_delimiter) {
|
||||
if (token_num < TOKEN_MANDATORY) {
|
||||
error_flag = true;
|
||||
goto exit;
|
||||
}
|
||||
if (!store_entry_func(std::move(entry))) {
|
||||
error_flag = true;
|
||||
goto exit;
|
||||
}
|
||||
entry.reset(new Entry());
|
||||
token_num = TOKEN_FIRST;
|
||||
new_line = ptr + 1;
|
||||
} else
|
||||
++token_num;
|
||||
}
|
||||
|
||||
exit:
|
||||
return new_line - buf;
|
||||
}
|
||||
|
||||
bool parse(const char *file_path, store_entry_func_t store_entry_func) {
|
||||
DBUG_ASSERT(file_path);
|
||||
DBUG_ASSERT(store_entry_func);
|
||||
File file= -1;
|
||||
bool result = true;
|
||||
uchar buf[1024];
|
||||
size_t bytes_read = 0;
|
||||
size_t buf_read_offset = 0;
|
||||
|
||||
if ((file= my_open(file_path, O_RDONLY | O_SHARE | O_NOFOLLOW | O_CLOEXEC,
|
||||
MYF(MY_WME))) < 0) {
|
||||
msg("DDL log file %s open failed: %d", file_path, my_errno);
|
||||
result = false;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
while((bytes_read = my_read(
|
||||
file, &buf[buf_read_offset], sizeof(buf) - buf_read_offset, MY_WME)) > 0) {
|
||||
if (bytes_read == size_t(-1)) {
|
||||
msg("DDL log file %s read error: %d", file_path, my_errno);
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
bytes_read += buf_read_offset;
|
||||
bool parse_error_flag = false;
|
||||
size_t bytes_parsed = parse(
|
||||
buf, bytes_read, parse_error_flag, store_entry_func);
|
||||
if (parse_error_flag) {
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
size_t rest_size = bytes_read - bytes_parsed;
|
||||
if (rest_size)
|
||||
memcpy(buf, buf + bytes_parsed, rest_size);
|
||||
buf_read_offset = rest_size;
|
||||
}
|
||||
|
||||
exit:
|
||||
if (file >= 0)
|
||||
my_close(file, MYF(MY_WME));
|
||||
return result;
|
||||
};
|
||||
|
||||
|
||||
static
|
||||
bool process_database(
|
||||
const char *datadir_path,
|
||||
ds_ctxt_t *ds,
|
||||
const Entry &entry,
|
||||
std::unordered_set<std::string> &dropped_databases) {
|
||||
|
||||
if (entry.type == Entry::Type::CREATE ||
|
||||
entry.type == Entry::Type::ALTER) {
|
||||
std::string opt_file(datadir_path);
|
||||
opt_file.append("/").append(entry.db).append("/db.opt");
|
||||
if (!ds->copy_file(opt_file.c_str(), opt_file.c_str(), 0, true)) {
|
||||
msg("Failed to re-copy %s.", opt_file.c_str());
|
||||
return false;
|
||||
}
|
||||
if (entry.type == Entry::Type::CREATE)
|
||||
dropped_databases.erase(entry.db);
|
||||
return true;
|
||||
}
|
||||
|
||||
DBUG_ASSERT(entry.type == Entry::Type::DROP);
|
||||
|
||||
std::string db_path(datadir_path);
|
||||
db_path.append("/").append(entry.db);
|
||||
const char *dst_path = convert_dst(db_path.c_str());
|
||||
if (!ds_remove(ds, dst_path)) {
|
||||
dropped_databases.insert(entry.db);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static
|
||||
std::unique_ptr<std::vector<std::string>>
|
||||
find_table_files(
|
||||
const char *dir_path,
|
||||
const std::string &db,
|
||||
const std::string &table) {
|
||||
|
||||
std::unique_ptr<std::vector<std::string>>
|
||||
result(new std::vector<std::string>());
|
||||
|
||||
std::string prefix = convert_tablename_to_filepath(dir_path, db, table);
|
||||
foreach_file_in_db_dirs(dir_path, [&](const char *file_name)->bool {
|
||||
if (!strncmp(file_name, prefix.c_str(), prefix.size())) {
|
||||
DBUG_ASSERT(strlen(file_name) >= prefix.size());
|
||||
if (file_name[prefix.size()] == '.' ||
|
||||
!strncmp(file_name + prefix.size(), "#P#", strlen("#P#")))
|
||||
result->push_back(std::string(file_name));
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static
|
||||
bool process_remove(
|
||||
const char *datadir_path,
|
||||
ds_ctxt_t *ds,
|
||||
const Entry &entry,
|
||||
bool remove_frm) {
|
||||
|
||||
if (check_if_skip_table(
|
||||
std::string(entry.db).append("/").append(entry.table).c_str()))
|
||||
return true;
|
||||
|
||||
auto ext_it = engine_exts.find(entry.engine);
|
||||
if (ext_it == engine_exts.end())
|
||||
return true;
|
||||
|
||||
std::string file_preffix = convert_tablename_to_filepath(datadir_path,
|
||||
entry.db, entry.table);
|
||||
const char *dst_preffix = convert_dst(file_preffix.c_str());
|
||||
|
||||
for (const char *ext : ext_it->second) {
|
||||
std::string old_name(dst_preffix);
|
||||
if (!entry.partitioned)
|
||||
old_name.append(ext);
|
||||
else
|
||||
old_name.append("#P#*");
|
||||
if (ds_remove(ds, old_name.c_str())) {
|
||||
msg("Failed to remove %s.", old_name.c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (remove_frm) {
|
||||
std::string old_frm_name(dst_preffix);
|
||||
old_frm_name.append(frm_ext);
|
||||
if (ds_remove(ds, old_frm_name.c_str())) {
|
||||
msg("Failed to remove %s.", old_frm_name.c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
static
|
||||
bool process_recopy(
|
||||
const char *datadir_path,
|
||||
ds_ctxt_t *ds,
|
||||
const Entry &entry,
|
||||
const tables_t &tables) {
|
||||
|
||||
if (check_if_skip_table(
|
||||
std::string(entry.db).append("/").append(entry.table).c_str()))
|
||||
return true;
|
||||
|
||||
const std::string &new_table_id =
|
||||
entry.new_id.empty() ? entry.id : entry.new_id;
|
||||
DBUG_ASSERT(!new_table_id.empty());
|
||||
const std::string &new_table =
|
||||
entry.new_table.empty() ? entry.table : entry.new_table;
|
||||
DBUG_ASSERT(!new_table.empty());
|
||||
const std::string &new_db =
|
||||
entry.new_db.empty() ? entry.db : entry.new_db;
|
||||
DBUG_ASSERT(!new_db.empty());
|
||||
const std::string &new_engine =
|
||||
entry.new_engine.empty() ? entry.engine : entry.new_engine;
|
||||
DBUG_ASSERT(!new_engine.empty());
|
||||
|
||||
if (entry.type != Entry::Type::BULK_INSERT) {
|
||||
auto table_it = tables.find(table_key(new_db, new_table));
|
||||
if (table_it != tables.end() &&
|
||||
table_it->second == new_table_id)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!entry.new_engine.empty() &&
|
||||
entry.engine != entry.new_engine &&
|
||||
!known_engine(entry.new_engine)) {
|
||||
return process_remove(datadir_path, ds, entry, false);
|
||||
}
|
||||
|
||||
if ((entry.partitioned || entry.new_partitioned) &&
|
||||
!process_remove(datadir_path, ds, entry, false))
|
||||
return false;
|
||||
|
||||
if (entry.partitioned || entry.new_partitioned) {
|
||||
auto files = find_table_files(datadir_path, new_db, new_table);
|
||||
if (!files.get())
|
||||
return true;
|
||||
for (const auto &file : *files) {
|
||||
const char *dst_path = convert_dst(file.c_str());
|
||||
if (!ds->copy_file(file.c_str(), dst_path, 0, true)) {
|
||||
msg("Failed to re-copy %s.", file.c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
auto ext_it = engine_exts.find(new_engine);
|
||||
if (ext_it == engine_exts.end())
|
||||
return false;
|
||||
|
||||
for (const char *ext : ext_it->second) {
|
||||
std::string file_name =
|
||||
convert_tablename_to_filepath(datadir_path, new_db, new_table).
|
||||
append(ext);
|
||||
const char *dst_path = convert_dst(file_name.c_str());
|
||||
if (file_exists(file_name.c_str()) &&
|
||||
!ds->copy_file(file_name.c_str(), dst_path, 0, true)) {
|
||||
msg("Failed to re-copy %s.", file_name.c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
std::string frm_file =
|
||||
convert_tablename_to_filepath(datadir_path, new_db, new_table).
|
||||
append(frm_ext);
|
||||
const char *frm_dst_path = convert_dst(frm_file.c_str());
|
||||
if (file_exists(frm_file.c_str()) &&
|
||||
!ds->copy_file(frm_file.c_str(), frm_dst_path, 0, true)) {
|
||||
msg("Failed to re-copy %s.", frm_file.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static
|
||||
bool process_rename(
|
||||
const char *datadir_path,
|
||||
ds_ctxt_t *ds,
|
||||
const Entry &entry) {
|
||||
|
||||
if (check_if_skip_table(
|
||||
std::string(entry.db).append("/").append(entry.table).c_str()))
|
||||
return true;
|
||||
|
||||
DBUG_ASSERT(entry.db != "partition");
|
||||
|
||||
auto ext_it = engine_exts.find(entry.engine);
|
||||
if (ext_it == engine_exts.end())
|
||||
return false;
|
||||
|
||||
std::string new_preffix = convert_tablename_to_filepath(datadir_path,
|
||||
entry.new_db, entry.new_table);
|
||||
const char *dst_path = convert_dst(new_preffix.c_str());
|
||||
|
||||
std::string old_preffix = convert_tablename_to_filepath(datadir_path,
|
||||
entry.db, entry.table);
|
||||
const char *src_path = convert_dst(old_preffix.c_str());
|
||||
|
||||
for (const char *ext : ext_it->second) {
|
||||
std::string old_name(src_path);
|
||||
old_name.append(ext);
|
||||
std::string new_name(dst_path);
|
||||
new_name.append(ext);
|
||||
if (ds_rename(ds, old_name.c_str(), new_name.c_str())) {
|
||||
msg("Failed to rename %s to %s.",
|
||||
old_name.c_str(), new_name.c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
std::string new_frm_file = new_preffix + frm_ext;
|
||||
const char *new_frm_dst = convert_dst(new_frm_file.c_str());
|
||||
if (file_exists(new_frm_file.c_str()) &&
|
||||
!ds->copy_file(new_frm_file.c_str(), new_frm_dst, 0, true)) {
|
||||
msg("Failed to re-copy %s.", new_frm_file.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: return this code if .frm is copied not under BLOCK_DDL
|
||||
/*
|
||||
std::string old_frm_name(src_path);
|
||||
old_frm_name.append(frm_ext);
|
||||
std::string new_frm_name(dst_path);
|
||||
new_frm_name.append(frm_ext);
|
||||
if (ds_rename(ds, old_frm_name.c_str(), new_frm_name.c_str())) {
|
||||
msg("Failed to rename %s to %s.",
|
||||
old_frm_name.c_str(), new_frm_name.c_str());
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
bool backup(
|
||||
const char *datadir_path,
|
||||
ds_ctxt_t *ds,
|
||||
const tables_t &tables) {
|
||||
DBUG_ASSERT(datadir_path);
|
||||
DBUG_ASSERT(ds);
|
||||
char ddl_log_path[FN_REFLEN];
|
||||
fn_format(ddl_log_path, "ddl", datadir_path, ".log", 0);
|
||||
std::vector<std::unique_ptr<Entry>> entries;
|
||||
|
||||
std::unordered_set<std::string> processed_tables;
|
||||
std::unordered_set<std::string> dropped_databases;
|
||||
|
||||
bool parsing_result =
|
||||
parse(ddl_log_path, [&](std::unique_ptr<Entry> entry)->bool {
|
||||
|
||||
if (entry->engine == database_keyword)
|
||||
return process_database(datadir_path, ds, *entry, dropped_databases);
|
||||
|
||||
if (!known_engine(entry->engine) && !known_engine(entry->new_engine))
|
||||
return true;
|
||||
|
||||
if (entry->type == Entry::Type::CREATE ||
|
||||
(entry->type == Entry::Type::ALTER &&
|
||||
!entry->new_engine.empty() &&
|
||||
entry->engine != entry->new_engine)) {
|
||||
if (!process_recopy(datadir_path, ds, *entry, tables))
|
||||
return false;
|
||||
processed_tables.insert(table_key(entry->db, entry->table));
|
||||
if (entry->type == Entry::Type::ALTER)
|
||||
processed_tables.insert(table_key(entry->new_db, entry->new_table));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (entry->type == Entry::Type::DROP) {
|
||||
if (!process_remove(datadir_path, ds, *entry, true))
|
||||
return false;
|
||||
processed_tables.insert(table_key(entry->db, entry->table));
|
||||
return true;
|
||||
}
|
||||
if (entry->type == Entry::Type::RENAME) {
|
||||
if (entry->partitioned) {
|
||||
if (!process_remove(datadir_path, ds, *entry, true))
|
||||
return false;
|
||||
Entry recopy_entry {
|
||||
entry->type,
|
||||
{},
|
||||
entry->new_engine.empty() ? entry->engine : entry->new_engine,
|
||||
true,
|
||||
entry->new_db,
|
||||
entry->new_table,
|
||||
entry->new_id,
|
||||
{}, true, {}, {}, {}
|
||||
};
|
||||
if (!process_recopy(datadir_path, ds, recopy_entry, tables))
|
||||
return false;
|
||||
}
|
||||
else if (!process_rename(datadir_path, ds, *entry))
|
||||
return false;
|
||||
processed_tables.insert(table_key(entry->db, entry->table));
|
||||
processed_tables.insert(table_key(entry->new_db, entry->new_table));
|
||||
return true;
|
||||
}
|
||||
|
||||
entries.push_back(std::move(entry));
|
||||
return true;
|
||||
|
||||
});
|
||||
|
||||
if (!parsing_result)
|
||||
return false;
|
||||
|
||||
|
||||
while (!entries.empty()) {
|
||||
auto entry = std::move(entries.back());
|
||||
entries.pop_back();
|
||||
auto tk = table_key(
|
||||
entry->new_db.empty() ? entry->db : entry->new_db,
|
||||
entry->new_table.empty() ? entry->table : entry->new_table);
|
||||
if (dropped_databases.count(entry->db) ||
|
||||
dropped_databases.count(entry->new_db))
|
||||
continue;
|
||||
if (processed_tables.count(tk))
|
||||
continue;
|
||||
processed_tables.insert(std::move(tk));
|
||||
if (!process_recopy(datadir_path, ds, *entry, tables))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace ddl_log
|
15
extra/mariabackup/ddl_log.h
Normal file
15
extra/mariabackup/ddl_log.h
Normal file
@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
#include "my_global.h"
|
||||
#include "datasink.h"
|
||||
#include "aria_backup_client.h"
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace ddl_log {
|
||||
|
||||
typedef std::unordered_map<std::string, std::string> tables_t;
|
||||
bool backup(const char *datadir_path, ds_ctxt_t *ds, const tables_t &tables);
|
||||
|
||||
} // namespace ddl_log
|
@ -44,7 +44,7 @@ typedef struct {
|
||||
|
||||
static ds_ctxt_t *buffer_init(const char *root);
|
||||
static ds_file_t *buffer_open(ds_ctxt_t *ctxt, const char *path,
|
||||
MY_STAT *mystat);
|
||||
const MY_STAT *mystat, bool rewrite);
|
||||
static int buffer_write(ds_file_t *file, const uchar *buf, size_t len);
|
||||
static int buffer_close(ds_file_t *file);
|
||||
static void buffer_deinit(ds_ctxt_t *ctxt);
|
||||
@ -53,8 +53,11 @@ datasink_t datasink_buffer = {
|
||||
&buffer_init,
|
||||
&buffer_open,
|
||||
&buffer_write,
|
||||
nullptr,
|
||||
&buffer_close,
|
||||
&dummy_remove,
|
||||
nullptr,
|
||||
nullptr,
|
||||
&buffer_deinit
|
||||
};
|
||||
|
||||
@ -84,8 +87,10 @@ buffer_init(const char *root)
|
||||
}
|
||||
|
||||
static ds_file_t *
|
||||
buffer_open(ds_ctxt_t *ctxt, const char *path, MY_STAT *mystat)
|
||||
buffer_open(ds_ctxt_t *ctxt, const char *path,
|
||||
const MY_STAT *mystat, bool rewrite)
|
||||
{
|
||||
DBUG_ASSERT(rewrite == false);
|
||||
ds_buffer_ctxt_t *buffer_ctxt;
|
||||
ds_ctxt_t *pipe_ctxt;
|
||||
ds_file_t *dst_file;
|
||||
|
@ -65,7 +65,7 @@ extern ulonglong xtrabackup_compress_chunk_size;
|
||||
|
||||
static ds_ctxt_t *compress_init(const char *root);
|
||||
static ds_file_t *compress_open(ds_ctxt_t *ctxt, const char *path,
|
||||
MY_STAT *mystat);
|
||||
const MY_STAT *mystat, bool rewrite);
|
||||
static int compress_write(ds_file_t *file, const uchar *buf, size_t len);
|
||||
static int compress_close(ds_file_t *file);
|
||||
static void compress_deinit(ds_ctxt_t *ctxt);
|
||||
@ -74,8 +74,11 @@ datasink_t datasink_compress = {
|
||||
&compress_init,
|
||||
&compress_open,
|
||||
&compress_write,
|
||||
nullptr,
|
||||
&compress_close,
|
||||
&dummy_remove,
|
||||
nullptr,
|
||||
nullptr,
|
||||
&compress_deinit
|
||||
};
|
||||
|
||||
@ -116,8 +119,10 @@ compress_init(const char *root)
|
||||
|
||||
static
|
||||
ds_file_t *
|
||||
compress_open(ds_ctxt_t *ctxt, const char *path, MY_STAT *mystat)
|
||||
compress_open(ds_ctxt_t *ctxt, const char *path,
|
||||
const MY_STAT *mystat, bool rewrite)
|
||||
{
|
||||
DBUG_ASSERT(rewrite == false);
|
||||
ds_compress_ctxt_t *comp_ctxt;
|
||||
ds_ctxt_t *dest_ctxt;
|
||||
ds_file_t *dest_file;
|
||||
|
@ -42,8 +42,9 @@ typedef struct {
|
||||
|
||||
static ds_ctxt_t *local_init(const char *root);
|
||||
static ds_file_t *local_open(ds_ctxt_t *ctxt, const char *path,
|
||||
MY_STAT *mystat);
|
||||
const MY_STAT *mystat, bool rewrite);
|
||||
static int local_write(ds_file_t *file, const uchar *buf, size_t len);
|
||||
static int local_seek_set(ds_file_t *file, my_off_t offset);
|
||||
static int local_close(ds_file_t *file);
|
||||
static void local_deinit(ds_ctxt_t *ctxt);
|
||||
|
||||
@ -52,13 +53,20 @@ static int local_remove(const char *path)
|
||||
return unlink(path);
|
||||
}
|
||||
|
||||
static int local_rename(
|
||||
ds_ctxt_t *ctxt, const char *old_path, const char *new_path);
|
||||
static int local_mremove(ds_ctxt_t *ctxt, const char *path);
|
||||
|
||||
extern "C" {
|
||||
datasink_t datasink_local = {
|
||||
&local_init,
|
||||
&local_open,
|
||||
&local_write,
|
||||
&local_seek_set,
|
||||
&local_close,
|
||||
&local_remove,
|
||||
&local_rename,
|
||||
&local_mremove,
|
||||
&local_deinit
|
||||
};
|
||||
}
|
||||
@ -89,7 +97,7 @@ local_init(const char *root)
|
||||
static
|
||||
ds_file_t *
|
||||
local_open(ds_ctxt_t *ctxt, const char *path,
|
||||
MY_STAT *mystat __attribute__((unused)))
|
||||
const MY_STAT *mystat __attribute__((unused)), bool rewrite)
|
||||
{
|
||||
char fullpath[FN_REFLEN];
|
||||
char dirpath[FN_REFLEN];
|
||||
@ -111,8 +119,10 @@ local_open(ds_ctxt_t *ctxt, const char *path,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fd = my_create(fullpath, 0, O_WRONLY | O_BINARY | O_EXCL | O_NOFOLLOW,
|
||||
MYF(MY_WME));
|
||||
// TODO: check in Windows and set the corresponding flags on fail
|
||||
fd = my_create(fullpath, 0,
|
||||
O_WRONLY | O_BINARY | (rewrite ? O_TRUNC : O_EXCL) | O_NOFOLLOW,
|
||||
MYF(MY_WME));
|
||||
if (fd < 0) {
|
||||
return NULL;
|
||||
}
|
||||
@ -194,8 +204,8 @@ static void init_ibd_data(ds_local_file_t *local_file, const uchar *buf, size_t
|
||||
return;
|
||||
}
|
||||
|
||||
auto flags = mach_read_from_4(&buf[FIL_PAGE_DATA + FSP_SPACE_FLAGS]);
|
||||
auto ssize = FSP_FLAGS_GET_PAGE_SSIZE(flags);
|
||||
uint32_t flags = mach_read_from_4(&buf[FIL_PAGE_DATA + FSP_SPACE_FLAGS]);
|
||||
uint32_t ssize = FSP_FLAGS_GET_PAGE_SSIZE(flags);
|
||||
local_file->pagesize= ssize == 0 ? UNIV_PAGE_SIZE_ORIG : ((UNIV_ZIP_SIZE_MIN >> 1) << ssize);
|
||||
local_file->compressed = fil_space_t::full_crc32(flags)
|
||||
? fil_space_t::is_compressed(flags)
|
||||
@ -239,6 +249,15 @@ local_write(ds_file_t *file, const uchar *buf, size_t len)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
local_seek_set(ds_file_t *file, my_off_t offset) {
|
||||
ds_local_file_t *local_file= (ds_local_file_t *)file->ptr;
|
||||
if (my_seek(local_file->fd, offset, SEEK_SET, MYF(0)) == MY_FILEPOS_ERROR)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set EOF at file's current position.*/
|
||||
static int set_eof(File fd)
|
||||
{
|
||||
@ -276,3 +295,77 @@ local_deinit(ds_ctxt_t *ctxt)
|
||||
my_free(ctxt->root);
|
||||
my_free(ctxt);
|
||||
}
|
||||
|
||||
|
||||
static int local_rename(
|
||||
ds_ctxt_t *ctxt, const char *old_path, const char *new_path) {
|
||||
char full_old_path[FN_REFLEN];
|
||||
char full_new_path[FN_REFLEN];
|
||||
fn_format(full_old_path, old_path, ctxt->root, "", MYF(MY_RELATIVE_PATH));
|
||||
fn_format(full_new_path, new_path, ctxt->root, "", MYF(MY_RELATIVE_PATH));
|
||||
// Ignore errors as .frm files can me copied separately.
|
||||
// TODO: return error processing here after the corresponding changes in
|
||||
// xtrabackup.cc
|
||||
(void)my_rename(full_old_path, full_new_path, MYF(0));
|
||||
// if (my_rename(full_old_path, full_new_path, MYF(0))) {
|
||||
// msg("Failed to rename file %s to %s", old_path, new_path);
|
||||
// return 1;
|
||||
// }
|
||||
return 0;
|
||||
}
|
||||
|
||||
// It's ok if destination does not contain the file or folder
|
||||
static int local_mremove(ds_ctxt_t *ctxt, const char *path) {
|
||||
char full_path[FN_REFLEN];
|
||||
fn_format(full_path, path, ctxt->root, "", MYF(MY_RELATIVE_PATH));
|
||||
size_t full_path_len = strlen(full_path);
|
||||
if (full_path[full_path_len - 1] == '*') {
|
||||
full_path[full_path_len - 1] = '\0';
|
||||
char *preffix = strrchr(full_path, '/');
|
||||
const char *full_path_dir = full_path;
|
||||
size_t preffix_len;
|
||||
if (preffix) {
|
||||
preffix_len = (full_path_len - 1) - (preffix - full_path);
|
||||
*(preffix++) = '\0';
|
||||
}
|
||||
else {
|
||||
preffix = full_path;
|
||||
preffix_len = full_path_len - 1;
|
||||
full_path_dir= IF_WIN(".\\", "./");
|
||||
}
|
||||
if (!preffix_len)
|
||||
return 0;
|
||||
MY_DIR *dir= my_dir(full_path_dir, 0);
|
||||
if (!dir)
|
||||
return 0;
|
||||
for (size_t i = 0; i < dir->number_of_files; ++i) {
|
||||
char full_fpath[FN_REFLEN];
|
||||
if (strncmp(dir->dir_entry[i].name, preffix, preffix_len))
|
||||
continue;
|
||||
fn_format(full_fpath, dir->dir_entry[i].name,
|
||||
full_path_dir, "", MYF(MY_RELATIVE_PATH));
|
||||
(void)my_delete(full_fpath, MYF(0));
|
||||
}
|
||||
my_dirend(dir);
|
||||
}
|
||||
else {
|
||||
MY_STAT stat;
|
||||
if (!my_stat(full_path, &stat, MYF(0)))
|
||||
return 0;
|
||||
MY_DIR *dir= my_dir(full_path, 0);
|
||||
if (!dir) {
|
||||
// TODO: check for error here if necessary
|
||||
(void)my_delete(full_path, MYF(0));
|
||||
return 0;
|
||||
}
|
||||
for (size_t i = 0; i < dir->number_of_files; ++i) {
|
||||
char full_fpath[FN_REFLEN];
|
||||
fn_format(full_fpath, dir->dir_entry[i].name,
|
||||
full_path, "", MYF(MY_RELATIVE_PATH));
|
||||
(void)my_delete(full_fpath, MYF(0));
|
||||
}
|
||||
my_dirend(dir);
|
||||
(void)my_rmtree(full_path, MYF(0));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ typedef struct {
|
||||
|
||||
static ds_ctxt_t *stdout_init(const char *root);
|
||||
static ds_file_t *stdout_open(ds_ctxt_t *ctxt, const char *path,
|
||||
MY_STAT *mystat);
|
||||
const MY_STAT *mystat, bool rewrite);
|
||||
static int stdout_write(ds_file_t *file, const uchar *buf, size_t len);
|
||||
static int stdout_close(ds_file_t *file);
|
||||
static void stdout_deinit(ds_ctxt_t *ctxt);
|
||||
@ -39,8 +39,11 @@ datasink_t datasink_stdout = {
|
||||
&stdout_init,
|
||||
&stdout_open,
|
||||
&stdout_write,
|
||||
nullptr,
|
||||
&stdout_close,
|
||||
&dummy_remove,
|
||||
nullptr,
|
||||
nullptr,
|
||||
&stdout_deinit
|
||||
};
|
||||
|
||||
@ -61,8 +64,9 @@ static
|
||||
ds_file_t *
|
||||
stdout_open(ds_ctxt_t *ctxt __attribute__((unused)),
|
||||
const char *path __attribute__((unused)),
|
||||
MY_STAT *mystat __attribute__((unused)))
|
||||
const MY_STAT *mystat __attribute__((unused)), bool rewrite)
|
||||
{
|
||||
DBUG_ASSERT(rewrite == false);
|
||||
ds_stdout_file_t *stdout_file;
|
||||
ds_file_t *file;
|
||||
size_t pathlen;
|
||||
|
@ -41,7 +41,7 @@ typedef struct {
|
||||
|
||||
static ds_ctxt_t *tmpfile_init(const char *root);
|
||||
static ds_file_t *tmpfile_open(ds_ctxt_t *ctxt, const char *path,
|
||||
MY_STAT *mystat);
|
||||
const MY_STAT *mystat, bool rewrite);
|
||||
static int tmpfile_write(ds_file_t *file, const uchar *buf, size_t len);
|
||||
static int tmpfile_close(ds_file_t *file);
|
||||
static void tmpfile_deinit(ds_ctxt_t *ctxt);
|
||||
@ -50,8 +50,11 @@ datasink_t datasink_tmpfile = {
|
||||
&tmpfile_init,
|
||||
&tmpfile_open,
|
||||
&tmpfile_write,
|
||||
nullptr,
|
||||
&tmpfile_close,
|
||||
&dummy_remove,
|
||||
nullptr,
|
||||
nullptr,
|
||||
&tmpfile_deinit
|
||||
};
|
||||
|
||||
@ -80,8 +83,9 @@ tmpfile_init(const char *root)
|
||||
|
||||
static ds_file_t *
|
||||
tmpfile_open(ds_ctxt_t *ctxt, const char *path,
|
||||
MY_STAT *mystat)
|
||||
const MY_STAT *mystat, bool rewrite)
|
||||
{
|
||||
DBUG_ASSERT(rewrite == false);
|
||||
ds_tmpfile_ctxt_t *tmpfile_ctxt;
|
||||
char tmp_path[FN_REFLEN];
|
||||
ds_tmp_file_t *tmp_file;
|
||||
|
@ -40,24 +40,31 @@ General streaming interface */
|
||||
|
||||
static ds_ctxt_t *xbstream_init(const char *root);
|
||||
static ds_file_t *xbstream_open(ds_ctxt_t *ctxt, const char *path,
|
||||
MY_STAT *mystat);
|
||||
const MY_STAT *mystat, bool rewrite);
|
||||
static int xbstream_write(ds_file_t *file, const uchar *buf, size_t len);
|
||||
static int xbstream_seek_set(ds_file_t *file, my_off_t offset);
|
||||
static int xbstream_close(ds_file_t *file);
|
||||
static void xbstream_deinit(ds_ctxt_t *ctxt);
|
||||
|
||||
static int xbstream_rename(
|
||||
ds_ctxt_t *ctxt, const char *old_path, const char *new_path);
|
||||
static int xbstream_mremove(ds_ctxt_t *ctxt, const char *path);
|
||||
|
||||
datasink_t datasink_xbstream = {
|
||||
&xbstream_init,
|
||||
&xbstream_open,
|
||||
&xbstream_write,
|
||||
&xbstream_seek_set,
|
||||
&xbstream_close,
|
||||
&dummy_remove,
|
||||
&xbstream_rename,
|
||||
&xbstream_mremove,
|
||||
&xbstream_deinit
|
||||
};
|
||||
|
||||
static
|
||||
ssize_t
|
||||
my_xbstream_write_callback(xb_wstream_file_t *f __attribute__((unused)),
|
||||
void *userdata, const void *buf, size_t len)
|
||||
my_xbstream_write_callback(void *userdata, const void *buf, size_t len)
|
||||
{
|
||||
ds_stream_ctxt_t *stream_ctxt;
|
||||
|
||||
@ -89,7 +96,7 @@ xbstream_init(const char *root __attribute__((unused)))
|
||||
goto err;
|
||||
}
|
||||
|
||||
xbstream = xb_stream_write_new();
|
||||
xbstream = xb_stream_write_new(my_xbstream_write_callback, stream_ctxt);
|
||||
if (xbstream == NULL) {
|
||||
msg("xb_stream_write_new() failed.");
|
||||
goto err;
|
||||
@ -108,7 +115,8 @@ err:
|
||||
|
||||
static
|
||||
ds_file_t *
|
||||
xbstream_open(ds_ctxt_t *ctxt, const char *path, MY_STAT *mystat)
|
||||
xbstream_open(ds_ctxt_t *ctxt, const char *path,
|
||||
const MY_STAT *mystat, bool rewrite)
|
||||
{
|
||||
ds_file_t *file;
|
||||
ds_stream_file_t *stream_file;
|
||||
@ -144,9 +152,7 @@ xbstream_open(ds_ctxt_t *ctxt, const char *path, MY_STAT *mystat)
|
||||
|
||||
xbstream = stream_ctxt->xbstream;
|
||||
|
||||
xbstream_file = xb_stream_write_open(xbstream, path, mystat,
|
||||
stream_ctxt,
|
||||
my_xbstream_write_callback);
|
||||
xbstream_file = xb_stream_write_open(xbstream, path, mystat, rewrite);
|
||||
|
||||
if (xbstream_file == NULL) {
|
||||
msg("xb_stream_write_open() failed.");
|
||||
@ -190,6 +196,45 @@ xbstream_write(ds_file_t *file, const uchar *buf, size_t len)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
xbstream_seek_set(ds_file_t *file, my_off_t offset)
|
||||
{
|
||||
ds_stream_file_t *stream_file;
|
||||
xb_wstream_file_t *xbstream_file;
|
||||
|
||||
|
||||
stream_file = (ds_stream_file_t *) file->ptr;
|
||||
|
||||
xbstream_file = stream_file->xbstream_file;
|
||||
|
||||
if (xb_stream_write_seek_set(xbstream_file, offset)) {
|
||||
msg("xb_stream_write_seek_set() failed.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
xbstream_mremove(ds_ctxt_t *ctxt, const char *path) {
|
||||
ds_stream_ctxt_t *stream_ctxt =
|
||||
reinterpret_cast<ds_stream_ctxt_t *>(ctxt->ptr);
|
||||
xb_wstream_t *xbstream = stream_ctxt->xbstream;
|
||||
return xb_stream_write_remove(xbstream, path);
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
xbstream_rename(
|
||||
ds_ctxt_t *ctxt, const char *old_path, const char *new_path) {
|
||||
ds_stream_ctxt_t *stream_ctxt =
|
||||
reinterpret_cast<ds_stream_ctxt_t *>(ctxt->ptr);
|
||||
xb_wstream_t *xbstream = stream_ctxt->xbstream;
|
||||
return xb_stream_write_rename(xbstream, old_path, new_path);
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
xbstream_close(ds_file_t *file)
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2017, 2022, MariaDB Corporation.
|
||||
/* Copyright (c) 2017, 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
|
||||
@ -17,18 +17,18 @@
|
||||
#include <mysqld.h>
|
||||
#include <mysql.h>
|
||||
#include <xtrabackup.h>
|
||||
#include <xb_plugin.h>
|
||||
#include <encryption_plugin.h>
|
||||
#include <sql_plugin.h>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <common.h>
|
||||
#include <backup_mysql.h>
|
||||
#include <srv0srv.h>
|
||||
#include <log0crypt.h>
|
||||
|
||||
|
||||
extern struct st_maria_plugin *mysql_optional_plugins[];
|
||||
extern struct st_maria_plugin *mysql_mandatory_plugins[];
|
||||
static void xb_plugin_init(int argc, char **argv);
|
||||
static void encryption_plugin_init(int argc, char **argv);
|
||||
|
||||
extern char *xb_plugin_load;
|
||||
extern char *xb_plugin_dir;
|
||||
@ -42,7 +42,7 @@ const char *QUERY_PLUGIN =
|
||||
" OR (plugin_type = 'DAEMON' AND plugin_name LIKE 'provider\\_%')"
|
||||
" AND plugin_status='ACTIVE'";
|
||||
|
||||
std::string xb_plugin_config;
|
||||
std::string encryption_plugin_config;
|
||||
|
||||
static void add_to_plugin_load_list(const char *plugin_def)
|
||||
{
|
||||
@ -52,16 +52,16 @@ static void add_to_plugin_load_list(const char *plugin_def)
|
||||
static char XTRABACKUP_EXE[] = "xtrabackup";
|
||||
|
||||
/*
|
||||
Read "plugin-load" value from backup-my.cnf during prepare phase.
|
||||
Read "plugin-load" value (encryption plugin) from backup-my.cnf during
|
||||
prepare phase.
|
||||
The value is stored during backup phase.
|
||||
*/
|
||||
static std::string get_plugin_from_cnf(const char *dir)
|
||||
static std::string get_encryption_plugin_from_cnf()
|
||||
{
|
||||
std::string path = dir + std::string("/backup-my.cnf");
|
||||
FILE *f = fopen(path.c_str(), "r");
|
||||
FILE *f = fopen("backup-my.cnf", "r");
|
||||
if (!f)
|
||||
{
|
||||
die("Can't open %s for reading", path.c_str());
|
||||
die("Can't open backup-my.cnf for reading");
|
||||
}
|
||||
char line[512];
|
||||
std::string plugin_load;
|
||||
@ -80,7 +80,7 @@ static std::string get_plugin_from_cnf(const char *dir)
|
||||
}
|
||||
|
||||
|
||||
void xb_plugin_backup_init(MYSQL *mysql)
|
||||
void encryption_plugin_backup_init(MYSQL *mysql)
|
||||
{
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row;
|
||||
@ -163,7 +163,7 @@ void xb_plugin_backup_init(MYSQL *mysql)
|
||||
mysql_free_result(result);
|
||||
}
|
||||
|
||||
xb_plugin_config = oss.str();
|
||||
encryption_plugin_config = oss.str();
|
||||
|
||||
argc = 0;
|
||||
argv[argc++] = XTRABACKUP_EXE;
|
||||
@ -175,23 +175,23 @@ void xb_plugin_backup_init(MYSQL *mysql)
|
||||
}
|
||||
argv[argc] = 0;
|
||||
|
||||
xb_plugin_init(argc, argv);
|
||||
encryption_plugin_init(argc, argv);
|
||||
}
|
||||
|
||||
const char *xb_plugin_get_config()
|
||||
const char *encryption_plugin_get_config()
|
||||
{
|
||||
return xb_plugin_config.c_str();
|
||||
return encryption_plugin_config.c_str();
|
||||
}
|
||||
|
||||
extern int finalize_encryption_plugin(st_plugin_int *plugin);
|
||||
|
||||
|
||||
void xb_plugin_prepare_init(int argc, char **argv, const char *dir)
|
||||
void encryption_plugin_prepare_init(int argc, char **argv)
|
||||
{
|
||||
std::string plugin_load= get_plugin_from_cnf(dir ? dir : ".");
|
||||
std::string plugin_load= get_encryption_plugin_from_cnf();
|
||||
if (plugin_load.size())
|
||||
{
|
||||
msg("Loading plugins from %s", plugin_load.c_str());
|
||||
msg("Loading encryption plugin from %s", plugin_load.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -211,19 +211,19 @@ void xb_plugin_prepare_init(int argc, char **argv, const char *dir)
|
||||
new_argv[0] = XTRABACKUP_EXE;
|
||||
memcpy(&new_argv[1], argv, argc*sizeof(char *));
|
||||
|
||||
xb_plugin_init(argc+1, new_argv);
|
||||
encryption_plugin_init(argc+1, new_argv);
|
||||
|
||||
delete[] new_argv;
|
||||
}
|
||||
|
||||
static void xb_plugin_init(int argc, char **argv)
|
||||
static void encryption_plugin_init(int argc, char **argv)
|
||||
{
|
||||
/* Patch optional and mandatory plugins, we only need to load the one in xb_plugin_load. */
|
||||
mysql_optional_plugins[0] = mysql_mandatory_plugins[0] = 0;
|
||||
plugin_maturity = MariaDB_PLUGIN_MATURITY_UNKNOWN; /* mariabackup accepts all plugins */
|
||||
msg("Loading plugins");
|
||||
msg("Loading encryption plugin");
|
||||
for (int i= 1; i < argc; i++)
|
||||
msg("\t Plugin parameter : '%s'", argv[i]);
|
||||
msg("\t Encryption plugin parameter : '%s'", argv[i]);
|
||||
plugin_init(&argc, argv, PLUGIN_INIT_SKIP_PLUGIN_TABLE);
|
||||
}
|
||||
|
7
extra/mariabackup/encryption_plugin.h
Normal file
7
extra/mariabackup/encryption_plugin.h
Normal file
@ -0,0 +1,7 @@
|
||||
#include <mysql.h>
|
||||
#include <string>
|
||||
extern void encryption_plugin_backup_init(MYSQL *mysql);
|
||||
extern const char* encryption_plugin_get_config();
|
||||
extern void encryption_plugin_prepare_init(int argc, char **argv);
|
||||
|
||||
//extern void encryption_plugin_init(int argc, char **argv);
|
@ -78,7 +78,6 @@ my_bool opt_ibx_galera_info = FALSE;
|
||||
my_bool opt_ibx_slave_info = FALSE;
|
||||
my_bool opt_ibx_no_lock = FALSE;
|
||||
my_bool opt_ibx_safe_slave_backup = FALSE;
|
||||
my_bool opt_ibx_rsync = FALSE;
|
||||
my_bool opt_ibx_force_non_empty_dirs = FALSE;
|
||||
my_bool opt_ibx_noversioncheck = FALSE;
|
||||
my_bool opt_ibx_no_backup_locks = FALSE;
|
||||
@ -297,15 +296,6 @@ static struct my_option ibx_long_options[] =
|
||||
(uchar *) &opt_ibx_safe_slave_backup,
|
||||
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
{"rsync", OPT_RSYNC, "Uses the rsync utility to optimize local file "
|
||||
"transfers. When this option is specified, innobackupex uses rsync "
|
||||
"to copy all non-InnoDB files instead of spawning a separate cp for "
|
||||
"each file, which can be much faster for servers with a large number "
|
||||
"of databases or tables. This option cannot be used together with "
|
||||
"--stream.",
|
||||
(uchar *) &opt_ibx_rsync, (uchar *) &opt_ibx_rsync,
|
||||
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
{"force-non-empty-directories", OPT_FORCE_NON_EMPTY_DIRS, "This "
|
||||
"option, when specified, makes --copy-back or --move-back transfer "
|
||||
"files to non-empty directories. Note that no existing files will be "
|
||||
@ -864,10 +854,8 @@ ibx_init()
|
||||
opt_slave_info = opt_ibx_slave_info;
|
||||
opt_no_lock = opt_ibx_no_lock;
|
||||
opt_safe_slave_backup = opt_ibx_safe_slave_backup;
|
||||
opt_rsync = opt_ibx_rsync;
|
||||
opt_force_non_empty_dirs = opt_ibx_force_non_empty_dirs;
|
||||
opt_noversioncheck = opt_ibx_noversioncheck;
|
||||
opt_no_backup_locks = opt_ibx_no_backup_locks;
|
||||
opt_decompress = opt_ibx_decompress;
|
||||
|
||||
opt_incremental_history_name = opt_ibx_incremental_history_name;
|
||||
|
50
extra/mariabackup/thread_pool.cc
Normal file
50
extra/mariabackup/thread_pool.cc
Normal file
@ -0,0 +1,50 @@
|
||||
#include "thread_pool.h"
|
||||
#include "common.h"
|
||||
|
||||
bool ThreadPool::start(size_t threads_count) {
|
||||
if (!m_stopped)
|
||||
return false;
|
||||
m_stopped = false;
|
||||
for (unsigned i = 0; i < threads_count; ++i)
|
||||
m_threads.emplace_back(&ThreadPool::thread_func, this, i);
|
||||
return true;
|
||||
}
|
||||
|
||||
void ThreadPool::stop() {
|
||||
if (m_stopped)
|
||||
return;
|
||||
m_stop = true;
|
||||
m_cv.notify_all();
|
||||
for (auto &t : m_threads)
|
||||
t.join();
|
||||
m_stopped = true;
|
||||
};
|
||||
|
||||
void ThreadPool::push(ThreadPool::job_t &&j) {
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
m_jobs.push(j);
|
||||
lock.unlock();
|
||||
m_cv.notify_one();
|
||||
}
|
||||
|
||||
void ThreadPool::thread_func(unsigned thread_num) {
|
||||
if (my_thread_init())
|
||||
die("Can't init mysql thread");
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
while(true) {
|
||||
if (m_stop)
|
||||
goto exit;
|
||||
while (!m_jobs.empty()) {
|
||||
if (m_stop)
|
||||
goto exit;
|
||||
job_t j = std::move(m_jobs.front());
|
||||
m_jobs.pop();
|
||||
lock.unlock();
|
||||
j(thread_num);
|
||||
lock.lock();
|
||||
}
|
||||
m_cv.wait(lock, [&] { return m_stop || !m_jobs.empty(); });
|
||||
}
|
||||
exit:
|
||||
my_thread_end();
|
||||
}
|
62
extra/mariabackup/thread_pool.h
Normal file
62
extra/mariabackup/thread_pool.h
Normal file
@ -0,0 +1,62 @@
|
||||
#pragma once
|
||||
#include <queue>
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
#include <atomic>
|
||||
#include "trx0sys.h"
|
||||
|
||||
class ThreadPool {
|
||||
public:
|
||||
typedef std::function<void(unsigned)> job_t;
|
||||
|
||||
ThreadPool() { m_stop = false; m_stopped = true; }
|
||||
ThreadPool (ThreadPool &&other) = delete;
|
||||
ThreadPool & operator= (ThreadPool &&other) = delete;
|
||||
ThreadPool(const ThreadPool &) = delete;
|
||||
ThreadPool & operator= (const ThreadPool &) = delete;
|
||||
|
||||
bool start(size_t threads_count);
|
||||
void stop();
|
||||
void push(job_t &&j);
|
||||
size_t threads_count() const { return m_threads.size(); }
|
||||
private:
|
||||
void thread_func(unsigned thread_num);
|
||||
std::mutex m_mutex;
|
||||
std::condition_variable m_cv;
|
||||
std::queue<job_t> m_jobs;
|
||||
std::atomic<bool> m_stop;
|
||||
std::atomic<bool> m_stopped;
|
||||
std::vector<std::thread> m_threads;
|
||||
};
|
||||
|
||||
class TasksGroup {
|
||||
public:
|
||||
TasksGroup(ThreadPool &thread_pool) : m_thread_pool(thread_pool) {
|
||||
m_tasks_count = 0;
|
||||
m_tasks_result = 1;
|
||||
}
|
||||
void push_task(ThreadPool::job_t &&j) {
|
||||
++m_tasks_count;
|
||||
m_thread_pool.push(std::forward<ThreadPool::job_t>(j));
|
||||
}
|
||||
void finish_task(int res) {
|
||||
--m_tasks_count;
|
||||
m_tasks_result.fetch_and(res);
|
||||
}
|
||||
int get_result() const { return m_tasks_result; }
|
||||
bool is_finished() const {
|
||||
return !m_tasks_count;
|
||||
}
|
||||
bool wait_for_finish() {
|
||||
while (!is_finished())
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
return get_result();
|
||||
}
|
||||
private:
|
||||
ThreadPool &m_thread_pool;
|
||||
std::atomic<size_t> m_tasks_count;
|
||||
std::atomic<int> m_tasks_result;
|
||||
};
|
@ -144,6 +144,18 @@ wf_incremental_process(xb_write_filt_ctxt_t *ctxt, ds_file_t *dstfile)
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Check whether TRX_SYS page has been changed */
|
||||
if (mach_read_from_4(page + FIL_PAGE_SPACE_ID)
|
||||
== TRX_SYS_SPACE
|
||||
&& mach_read_from_4(page + FIL_PAGE_OFFSET)
|
||||
== TRX_SYS_PAGE_NO) {
|
||||
msg(cursor->thread_n,
|
||||
"--incremental backup is impossible if "
|
||||
"the server had been restarted with "
|
||||
"different innodb_undo_tablespaces.");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* updated page */
|
||||
if (cp->npages == page_size / 4) {
|
||||
/* flush buffer */
|
||||
|
@ -55,6 +55,9 @@ permission notice:
|
||||
#define XB_GALERA_INFO_FILENAME "xtrabackup_galera_info"
|
||||
#define XB_GALERA_DONOR_INFO_FILENAME "donor_galera_info"
|
||||
|
||||
/* backup copy of galera info file as sent by donor */
|
||||
#define XB_GALERA_INFO_FILENAME_SST "xtrabackup_galera_info_SST"
|
||||
|
||||
/***********************************************************************
|
||||
Store Galera checkpoint info in the 'xtrabackup_galera_info' file, if that
|
||||
information is present in the trx system header. Otherwise, do nothing. */
|
||||
@ -68,19 +71,45 @@ xb_write_galera_info(bool incremental_prepare)
|
||||
long long seqno;
|
||||
MY_STAT statinfo;
|
||||
|
||||
/* Do not overwrite an existing file to be compatible with
|
||||
servers with older server versions */
|
||||
if (!incremental_prepare &&
|
||||
my_stat(XB_GALERA_INFO_FILENAME, &statinfo, MYF(0)) != NULL) {
|
||||
xid.null();
|
||||
|
||||
/* try to read last wsrep XID from innodb rsegs, we will use it
|
||||
instead of galera info file received from donor
|
||||
*/
|
||||
if (!trx_rseg_read_wsrep_checkpoint(xid)) {
|
||||
/* no worries yet, SST may have brought in galera info file
|
||||
from some old MariaDB version, which does not support
|
||||
wsrep XID storing in innodb rsegs
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
xid.null();
|
||||
/* if SST brought in galera info file, copy it as *_SST file
|
||||
this will not be used, saved just for future reference
|
||||
*/
|
||||
if (my_stat(XB_GALERA_INFO_FILENAME, &statinfo, MYF(0)) != NULL) {
|
||||
FILE* fp_in = fopen(XB_GALERA_INFO_FILENAME, "r");
|
||||
FILE* fp_out = fopen(XB_GALERA_INFO_FILENAME_SST, "w");
|
||||
|
||||
if (!trx_rseg_read_wsrep_checkpoint(xid)) {
|
||||
|
||||
return;
|
||||
char buf[BUFSIZ] = {'\0'};
|
||||
size_t size;
|
||||
while ((size = fread(buf, 1, BUFSIZ, fp_in))) {
|
||||
if (fwrite(buf, 1, size, fp_out) != strlen(buf)) {
|
||||
die(
|
||||
"could not write to "
|
||||
XB_GALERA_INFO_FILENAME_SST
|
||||
", errno = %d\n",
|
||||
errno);
|
||||
}
|
||||
}
|
||||
if (!feof(fp_in)) {
|
||||
die(
|
||||
XB_GALERA_INFO_FILENAME_SST
|
||||
" not fully copied\n"
|
||||
);
|
||||
}
|
||||
fclose(fp_out);
|
||||
fclose(fp_in);
|
||||
}
|
||||
|
||||
wsrep_uuid_t uuid;
|
||||
@ -97,7 +126,6 @@ xb_write_galera_info(bool incremental_prepare)
|
||||
"could not create " XB_GALERA_INFO_FILENAME
|
||||
", errno = %d\n",
|
||||
errno);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
seqno = wsrep_xid_seqno(&xid);
|
||||
|
@ -1,5 +0,0 @@
|
||||
#include <mysql.h>
|
||||
#include <string>
|
||||
extern void xb_plugin_backup_init(MYSQL *mysql);
|
||||
extern const char* xb_plugin_get_config();
|
||||
extern void xb_plugin_prepare_init(int argc, char **argv, const char *dir);
|
@ -262,7 +262,7 @@ mode_create(int argc, char **argv)
|
||||
return 1;
|
||||
}
|
||||
|
||||
stream = xb_stream_write_new();
|
||||
stream = xb_stream_write_new(nullptr, nullptr);
|
||||
if (stream == NULL) {
|
||||
msg("%s: xb_stream_write_new() failed.", my_progname);
|
||||
return 1;
|
||||
@ -287,7 +287,7 @@ mode_create(int argc, char **argv)
|
||||
goto err;
|
||||
}
|
||||
|
||||
file = xb_stream_write_open(stream, filepath, &mystat, NULL, NULL);
|
||||
file = xb_stream_write_open(stream, filepath, &mystat, false);
|
||||
if (file == NULL) {
|
||||
goto err;
|
||||
}
|
||||
@ -314,7 +314,8 @@ err:
|
||||
|
||||
static
|
||||
file_entry_t *
|
||||
file_entry_new(extract_ctxt_t *ctxt, const char *path, uint pathlen)
|
||||
file_entry_new(extract_ctxt_t *ctxt, const char *path, uint pathlen,
|
||||
uchar chunk_flags)
|
||||
{
|
||||
file_entry_t *entry;
|
||||
ds_file_t *file;
|
||||
@ -331,7 +332,8 @@ file_entry_new(extract_ctxt_t *ctxt, const char *path, uint pathlen)
|
||||
}
|
||||
entry->pathlen = pathlen;
|
||||
|
||||
file = ds_open(ctxt->ds_ctxt, path, NULL);
|
||||
file = ds_open(ctxt->ds_ctxt, path, NULL,
|
||||
chunk_flags == XB_STREAM_FLAG_REWRITE);
|
||||
|
||||
if (file == NULL) {
|
||||
msg("%s: failed to create file.", my_progname);
|
||||
@ -412,10 +414,50 @@ extract_worker_thread_func(void *arg)
|
||||
(uchar *) chunk.path,
|
||||
chunk.pathlen);
|
||||
|
||||
if (entry && (chunk.type == XB_CHUNK_TYPE_REMOVE ||
|
||||
chunk.type == XB_CHUNK_TYPE_RENAME)) {
|
||||
msg("%s: rename and remove chunks can not be applied to opened file: %s",
|
||||
my_progname, chunk.path);
|
||||
pthread_mutex_unlock(ctxt->mutex);
|
||||
break;
|
||||
}
|
||||
|
||||
if (chunk.type == XB_CHUNK_TYPE_REMOVE) {
|
||||
if (ds_remove(ctxt->ds_ctxt, chunk.path)) {
|
||||
msg("%s: error on file removing: %s", my_progname, chunk.path);
|
||||
pthread_mutex_unlock(ctxt->mutex);
|
||||
res = XB_STREAM_READ_ERROR;
|
||||
break;
|
||||
}
|
||||
pthread_mutex_unlock(ctxt->mutex);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (chunk.type == XB_CHUNK_TYPE_RENAME) {
|
||||
if (my_hash_search(ctxt->filehash,
|
||||
reinterpret_cast<const uchar *>(chunk.data), chunk.length)) {
|
||||
msg("%s: rename chunks can not be applied to opened file: %s",
|
||||
my_progname, reinterpret_cast<const uchar *>(chunk.data));
|
||||
pthread_mutex_unlock(ctxt->mutex);
|
||||
break;
|
||||
}
|
||||
if (ds_rename(ctxt->ds_ctxt, chunk.path,
|
||||
reinterpret_cast<const char *>(chunk.data))) {
|
||||
msg("%s: error on file renaming: %s to %s", my_progname,
|
||||
reinterpret_cast<const char *>(chunk.data), chunk.path);
|
||||
pthread_mutex_unlock(ctxt->mutex);
|
||||
res = XB_STREAM_READ_ERROR;
|
||||
break;
|
||||
}
|
||||
pthread_mutex_unlock(ctxt->mutex);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (entry == NULL) {
|
||||
entry = file_entry_new(ctxt,
|
||||
chunk.path,
|
||||
chunk.pathlen);
|
||||
chunk.pathlen,
|
||||
chunk.flags);
|
||||
if (entry == NULL) {
|
||||
pthread_mutex_unlock(ctxt->mutex);
|
||||
break;
|
||||
@ -432,6 +474,18 @@ extract_worker_thread_func(void *arg)
|
||||
|
||||
pthread_mutex_unlock(ctxt->mutex);
|
||||
|
||||
if (chunk.type == XB_CHUNK_TYPE_SEEK) {
|
||||
if (ds_seek_set(entry->file, chunk.offset)) {
|
||||
msg("%s: my_seek() failed.", my_progname);
|
||||
pthread_mutex_unlock(&entry->mutex);
|
||||
res = XB_STREAM_READ_ERROR;
|
||||
break;
|
||||
}
|
||||
entry->offset = chunk.offset;
|
||||
pthread_mutex_unlock(&entry->mutex);
|
||||
continue;
|
||||
}
|
||||
|
||||
res = xb_stream_validate_checksum(&chunk);
|
||||
|
||||
if (res != XB_STREAM_READ_CHUNK) {
|
||||
|
@ -29,6 +29,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA
|
||||
/* Chunk flags */
|
||||
/* Chunk can be ignored if unknown version/format */
|
||||
#define XB_STREAM_FLAG_IGNORABLE 0x01
|
||||
#define XB_STREAM_FLAG_REWRITE 0x02
|
||||
|
||||
/* Magic + flags + type + path len */
|
||||
#define CHUNK_HEADER_CONSTANT_LEN ((sizeof(XB_STREAM_CHUNK_MAGIC) - 1) + \
|
||||
@ -48,18 +49,21 @@ typedef enum {
|
||||
/************************************************************************
|
||||
Write interface. */
|
||||
|
||||
typedef ssize_t xb_stream_write_callback(xb_wstream_file_t *file,
|
||||
typedef ssize_t xb_stream_write_callback(
|
||||
void *userdata,
|
||||
const void *buf, size_t len);
|
||||
|
||||
xb_wstream_t *xb_stream_write_new(void);
|
||||
|
||||
xb_wstream_t *xb_stream_write_new(
|
||||
xb_stream_write_callback *write_callback, void *user_data);
|
||||
xb_wstream_file_t *xb_stream_write_open(xb_wstream_t *stream, const char *path,
|
||||
MY_STAT *mystat, void *userdata,
|
||||
xb_stream_write_callback *onwrite);
|
||||
const MY_STAT *mystat, bool rewrite);
|
||||
|
||||
int xb_stream_write_data(xb_wstream_file_t *file, const void *buf, size_t len);
|
||||
|
||||
int xb_stream_write_seek_set(xb_wstream_file_t *file, my_off_t offset);
|
||||
int xb_stream_write_remove(xb_wstream_t *stream, const char *path);
|
||||
int
|
||||
xb_stream_write_rename(
|
||||
xb_wstream_t *stream, const char *old_path, const char *new_path);
|
||||
int xb_stream_write_close(xb_wstream_file_t *file);
|
||||
|
||||
int xb_stream_write_done(xb_wstream_t *stream);
|
||||
@ -76,6 +80,9 @@ typedef enum {
|
||||
typedef enum {
|
||||
XB_CHUNK_TYPE_UNKNOWN = '\0',
|
||||
XB_CHUNK_TYPE_PAYLOAD = 'P',
|
||||
XB_CHUNK_TYPE_RENAME = 'R',
|
||||
XB_CHUNK_TYPE_REMOVE = 'D',
|
||||
XB_CHUNK_TYPE_SEEK = 'S',
|
||||
XB_CHUNK_TYPE_EOF = 'E'
|
||||
} xb_chunk_type_t;
|
||||
|
||||
|
@ -59,6 +59,9 @@ validate_chunk_type(uchar code)
|
||||
{
|
||||
switch ((xb_chunk_type_t) code) {
|
||||
case XB_CHUNK_TYPE_PAYLOAD:
|
||||
case XB_CHUNK_TYPE_RENAME:
|
||||
case XB_CHUNK_TYPE_REMOVE:
|
||||
case XB_CHUNK_TYPE_SEEK:
|
||||
case XB_CHUNK_TYPE_EOF:
|
||||
return (xb_chunk_type_t) code;
|
||||
default:
|
||||
@ -159,57 +162,91 @@ xb_stream_read_chunk(xb_rstream_t *stream, xb_rstream_chunk_t *chunk)
|
||||
}
|
||||
chunk->path[pathlen] = '\0';
|
||||
|
||||
if (chunk->type == XB_CHUNK_TYPE_EOF) {
|
||||
if (chunk->type == XB_CHUNK_TYPE_EOF ||
|
||||
chunk->type == XB_CHUNK_TYPE_REMOVE) {
|
||||
return XB_STREAM_READ_CHUNK;
|
||||
}
|
||||
|
||||
/* Payload length */
|
||||
F_READ(tmpbuf, 16);
|
||||
ullval = uint8korr(tmpbuf);
|
||||
if (ullval > (ulonglong) SIZE_T_MAX) {
|
||||
msg("xb_stream_read_chunk(): chunk length is too large at "
|
||||
"offset 0x%llx: 0x%llx.", (ulonglong) stream->offset,
|
||||
ullval);
|
||||
goto err;
|
||||
}
|
||||
chunk->length = (size_t) ullval;
|
||||
stream->offset += 8;
|
||||
|
||||
/* Payload offset */
|
||||
ullval = uint8korr(tmpbuf + 8);
|
||||
if (ullval > (ulonglong) MY_OFF_T_MAX) {
|
||||
msg("xb_stream_read_chunk(): chunk offset is too large at "
|
||||
"offset 0x%llx: 0x%llx.", (ulonglong) stream->offset,
|
||||
ullval);
|
||||
goto err;
|
||||
}
|
||||
chunk->offset = (my_off_t) ullval;
|
||||
stream->offset += 8;
|
||||
|
||||
/* Reallocate the buffer if needed */
|
||||
if (chunk->length > chunk->buflen) {
|
||||
chunk->data = my_realloc(PSI_NOT_INSTRUMENTED, chunk->data, chunk->length,
|
||||
MYF(MY_WME | MY_ALLOW_ZERO_PTR));
|
||||
if (chunk->data == NULL) {
|
||||
msg("xb_stream_read_chunk(): failed to increase buffer "
|
||||
"to %lu bytes.", (ulong) chunk->length);
|
||||
if (chunk->type == XB_CHUNK_TYPE_RENAME) {
|
||||
F_READ(tmpbuf, 4);
|
||||
size_t new_pathlen = uint4korr(tmpbuf);
|
||||
if (new_pathlen >= FN_REFLEN) {
|
||||
msg("xb_stream_read_chunk(): path length (%lu) for new name of 'rename'"
|
||||
" chunk is too large", (ulong) new_pathlen);
|
||||
goto err;
|
||||
}
|
||||
chunk->buflen = chunk->length;
|
||||
chunk->length = new_pathlen;
|
||||
stream->offset +=4;
|
||||
}
|
||||
else if (chunk->type == XB_CHUNK_TYPE_SEEK) {
|
||||
F_READ(tmpbuf, 8);
|
||||
chunk->offset = uint8korr(tmpbuf);
|
||||
stream->offset += 8;
|
||||
return XB_STREAM_READ_CHUNK;
|
||||
}
|
||||
else {
|
||||
/* Payload length */
|
||||
F_READ(tmpbuf, 16);
|
||||
ullval = uint8korr(tmpbuf);
|
||||
if (ullval > (ulonglong) SIZE_T_MAX) {
|
||||
msg("xb_stream_read_chunk(): chunk length is too large at "
|
||||
"offset 0x%llx: 0x%llx.", (ulonglong) stream->offset,
|
||||
ullval);
|
||||
goto err;
|
||||
}
|
||||
chunk->length = (size_t) ullval;
|
||||
stream->offset += 8;
|
||||
|
||||
/* Payload offset */
|
||||
ullval = uint8korr(tmpbuf + 8);
|
||||
if (ullval > (ulonglong) MY_OFF_T_MAX) {
|
||||
msg("xb_stream_read_chunk(): chunk offset is too large at "
|
||||
"offset 0x%llx: 0x%llx.", (ulonglong) stream->offset,
|
||||
ullval);
|
||||
goto err;
|
||||
}
|
||||
chunk->offset = (my_off_t) ullval;
|
||||
stream->offset += 8;
|
||||
}
|
||||
|
||||
/* Checksum */
|
||||
F_READ(tmpbuf, 4);
|
||||
chunk->checksum = uint4korr(tmpbuf);
|
||||
chunk->checksum_offset = stream->offset;
|
||||
/* Reallocate the buffer if needed, take into account trailing '\0' for
|
||||
new file name in the case of XB_CHUNK_TYPE_RENAME */
|
||||
if (chunk->length + 1 > chunk->buflen) {
|
||||
chunk->data = my_realloc(PSI_NOT_INSTRUMENTED, chunk->data,
|
||||
chunk->length + 1, MYF(MY_WME | MY_ALLOW_ZERO_PTR));
|
||||
if (chunk->data == NULL) {
|
||||
msg("xb_stream_read_chunk(): failed to increase buffer "
|
||||
"to %lu bytes.", (ulong) chunk->length + 1);
|
||||
goto err;
|
||||
}
|
||||
chunk->buflen = chunk->length + 1;
|
||||
}
|
||||
|
||||
/* Payload */
|
||||
if (chunk->length > 0) {
|
||||
if (chunk->type == XB_CHUNK_TYPE_RENAME) {
|
||||
if (chunk->length == 0) {
|
||||
msg("xb_stream_read_chunk(): failed to read new name for file to rename "
|
||||
": %s", chunk->path);
|
||||
goto err;
|
||||
}
|
||||
F_READ(chunk->data, chunk->length);
|
||||
stream->offset += chunk->length;
|
||||
reinterpret_cast<char *>(chunk->data)[chunk->length] = '\0';
|
||||
++chunk->length;
|
||||
}
|
||||
else {
|
||||
/* Checksum */
|
||||
F_READ(tmpbuf, 4);
|
||||
chunk->checksum = uint4korr(tmpbuf);
|
||||
chunk->checksum_offset = stream->offset;
|
||||
|
||||
stream->offset += 4;
|
||||
/* Payload */
|
||||
if (chunk->length > 0) {
|
||||
F_READ(chunk->data, chunk->length);
|
||||
stream->offset += chunk->length;
|
||||
}
|
||||
|
||||
stream->offset += 4;
|
||||
}
|
||||
|
||||
return XB_STREAM_READ_CHUNK;
|
||||
|
||||
|
@ -21,6 +21,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA
|
||||
#include <my_global.h>
|
||||
#include <my_base.h>
|
||||
#include <zlib.h>
|
||||
#include <stdint.h>
|
||||
#include "common.h"
|
||||
#include "xbstream.h"
|
||||
|
||||
@ -29,6 +30,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA
|
||||
|
||||
struct xb_wstream_struct {
|
||||
pthread_mutex_t mutex;
|
||||
xb_stream_write_callback *write;
|
||||
void *user_data;
|
||||
};
|
||||
|
||||
struct xb_wstream_file_struct {
|
||||
@ -39,8 +42,7 @@ struct xb_wstream_file_struct {
|
||||
char *chunk_ptr;
|
||||
size_t chunk_free;
|
||||
my_off_t offset;
|
||||
void *userdata;
|
||||
xb_stream_write_callback *write;
|
||||
bool rewrite;
|
||||
};
|
||||
|
||||
static int xb_stream_flush(xb_wstream_file_t *file);
|
||||
@ -50,7 +52,7 @@ static int xb_stream_write_eof(xb_wstream_file_t *file);
|
||||
|
||||
static
|
||||
ssize_t
|
||||
xb_stream_default_write_callback(xb_wstream_file_t *file __attribute__((unused)),
|
||||
xb_stream_default_write_callback(
|
||||
void *userdata __attribute__((unused)),
|
||||
const void *buf, size_t len)
|
||||
{
|
||||
@ -60,21 +62,31 @@ xb_stream_default_write_callback(xb_wstream_file_t *file __attribute__((unused))
|
||||
}
|
||||
|
||||
xb_wstream_t *
|
||||
xb_stream_write_new(void)
|
||||
xb_stream_write_new(
|
||||
xb_stream_write_callback *write_callback, void *user_data)
|
||||
{
|
||||
xb_wstream_t *stream;
|
||||
|
||||
stream = (xb_wstream_t *) my_malloc(PSI_NOT_INSTRUMENTED, sizeof(xb_wstream_t), MYF(MY_FAE));
|
||||
pthread_mutex_init(&stream->mutex, NULL);
|
||||
if (write_callback) {
|
||||
#ifdef _WIN32
|
||||
setmode(fileno(stdout), _O_BINARY);
|
||||
#endif
|
||||
stream->write = write_callback;
|
||||
stream->user_data = user_data;
|
||||
}
|
||||
else {
|
||||
stream->write = xb_stream_default_write_callback;
|
||||
stream->user_data = user_data;
|
||||
}
|
||||
|
||||
return stream;;
|
||||
}
|
||||
|
||||
xb_wstream_file_t *
|
||||
xb_stream_write_open(xb_wstream_t *stream, const char *path,
|
||||
MY_STAT *mystat __attribute__((unused)),
|
||||
void *userdata,
|
||||
xb_stream_write_callback *onwrite)
|
||||
const MY_STAT *mystat __attribute__((unused)), bool rewrite)
|
||||
{
|
||||
xb_wstream_file_t *file;
|
||||
size_t path_len;
|
||||
@ -109,16 +121,7 @@ xb_stream_write_open(xb_wstream_t *stream, const char *path,
|
||||
file->offset = 0;
|
||||
file->chunk_ptr = file->chunk;
|
||||
file->chunk_free = XB_STREAM_MIN_CHUNK_SIZE;
|
||||
if (onwrite) {
|
||||
#ifdef _WIN32
|
||||
setmode(fileno(stdout), _O_BINARY);
|
||||
#endif
|
||||
file->userdata = userdata;
|
||||
file->write = onwrite;
|
||||
} else {
|
||||
file->userdata = NULL;
|
||||
file->write = xb_stream_default_write_callback;
|
||||
}
|
||||
file->rewrite = rewrite;
|
||||
|
||||
return file;
|
||||
}
|
||||
@ -202,7 +205,8 @@ xb_stream_write_chunk(xb_wstream_file_t *file, const void *buf, size_t len)
|
||||
memcpy(ptr, XB_STREAM_CHUNK_MAGIC, sizeof(XB_STREAM_CHUNK_MAGIC) - 1);
|
||||
ptr += sizeof(XB_STREAM_CHUNK_MAGIC) - 1;
|
||||
|
||||
*ptr++ = 0; /* Chunk flags */
|
||||
*ptr++ =
|
||||
file->rewrite ? XB_STREAM_FLAG_REWRITE : 0; /* Chunk flags */
|
||||
|
||||
*ptr++ = (uchar) XB_CHUNK_TYPE_PAYLOAD; /* Chunk type */
|
||||
|
||||
@ -227,11 +231,11 @@ xb_stream_write_chunk(xb_wstream_file_t *file, const void *buf, size_t len)
|
||||
|
||||
xb_ad(ptr <= tmpbuf + sizeof(tmpbuf));
|
||||
|
||||
if (file->write(file, file->userdata, tmpbuf, ptr-tmpbuf) == -1)
|
||||
if (stream->write(stream->user_data, tmpbuf, ptr-tmpbuf) == -1)
|
||||
goto err;
|
||||
|
||||
|
||||
if (file->write(file, file->userdata, buf, len) == -1) /* Payload */
|
||||
if (stream->write(stream->user_data, buf, len) == -1) /* Payload */
|
||||
goto err;
|
||||
|
||||
file->offset+= len;
|
||||
@ -247,6 +251,38 @@ err:
|
||||
return 1;
|
||||
}
|
||||
|
||||
int xb_stream_write_seek_set(xb_wstream_file_t *file, my_off_t offset)
|
||||
{
|
||||
/* Chunk magic + flags + chunk type + path_len + path + offset */
|
||||
uchar tmpbuf[sizeof(XB_STREAM_CHUNK_MAGIC) - 1 + 1 + 1 + 4 +
|
||||
FN_REFLEN + 8];
|
||||
int error = 0;
|
||||
xb_wstream_t *stream = file->stream;
|
||||
uchar *ptr = tmpbuf;
|
||||
/* Chunk magic */
|
||||
memcpy(ptr, XB_STREAM_CHUNK_MAGIC, sizeof(XB_STREAM_CHUNK_MAGIC) - 1);
|
||||
ptr += sizeof(XB_STREAM_CHUNK_MAGIC) - 1;
|
||||
*ptr++ = 0; /* Chunk flags */
|
||||
*ptr++ = (uchar) XB_CHUNK_TYPE_SEEK; /* Chunk type */
|
||||
int4store(ptr, file->path_len); /* Path length */
|
||||
ptr += 4;
|
||||
memcpy(ptr, file->path, file->path_len); /* Path */
|
||||
ptr += file->path_len;
|
||||
int8store(ptr, static_cast<int64_t>(offset)); /* Offset */
|
||||
ptr += 8;
|
||||
if (xb_stream_flush(file))
|
||||
return 1;
|
||||
pthread_mutex_lock(&stream->mutex);
|
||||
if (stream->write(stream->user_data, tmpbuf, ptr-tmpbuf) == -1)
|
||||
error = 1;
|
||||
if (!error)
|
||||
file->offset = offset;
|
||||
pthread_mutex_unlock(&stream->mutex);
|
||||
if (xb_stream_flush(file))
|
||||
return 1;
|
||||
return error;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
xb_stream_write_eof(xb_wstream_file_t *file)
|
||||
@ -278,7 +314,7 @@ xb_stream_write_eof(xb_wstream_file_t *file)
|
||||
|
||||
xb_ad(ptr <= tmpbuf + sizeof(tmpbuf));
|
||||
|
||||
if (file->write(file, file->userdata, tmpbuf,
|
||||
if (stream->write(stream->user_data, tmpbuf,
|
||||
(ulonglong) (ptr - tmpbuf)) == -1)
|
||||
goto err;
|
||||
|
||||
@ -291,3 +327,77 @@ err:
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
xb_stream_write_remove(xb_wstream_t *stream, const char *path) {
|
||||
/* Chunk magic + flags + chunk type + path_len + path */
|
||||
uchar tmpbuf[sizeof(XB_STREAM_CHUNK_MAGIC) - 1 + 1 + 1 + 4 + FN_REFLEN];
|
||||
uchar *ptr = tmpbuf;
|
||||
/* Chunk magic */
|
||||
memcpy(ptr, XB_STREAM_CHUNK_MAGIC, sizeof(XB_STREAM_CHUNK_MAGIC) - 1);
|
||||
ptr += sizeof(XB_STREAM_CHUNK_MAGIC) - 1;
|
||||
|
||||
*ptr++ = 0; /* Chunk flags */
|
||||
|
||||
*ptr++ = (uchar) XB_CHUNK_TYPE_REMOVE; /* Chunk type */
|
||||
size_t path_len = strlen(path);
|
||||
int4store(ptr, path_len); /* Path length */
|
||||
ptr += 4;
|
||||
|
||||
memcpy(ptr, path, path_len); /* Path */
|
||||
ptr += path_len;
|
||||
|
||||
xb_ad(ptr <= tmpbuf + sizeof(tmpbuf));
|
||||
|
||||
pthread_mutex_lock(&stream->mutex);
|
||||
|
||||
ssize_t result = stream->write(stream->user_data, tmpbuf,
|
||||
(ulonglong) (ptr - tmpbuf));
|
||||
|
||||
pthread_mutex_unlock(&stream->mutex);
|
||||
|
||||
return result < 0;
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
xb_stream_write_rename(
|
||||
xb_wstream_t *stream, const char *old_path, const char *new_path) {
|
||||
/* Chunk magic + flags + chunk type + path_len + path + path_len + path*/
|
||||
uchar tmpbuf[sizeof(XB_STREAM_CHUNK_MAGIC) - 1 + 1 + 1 +
|
||||
4 + FN_REFLEN + 4 + FN_REFLEN];
|
||||
uchar *ptr = tmpbuf;
|
||||
/* Chunk magic */
|
||||
memcpy(ptr, XB_STREAM_CHUNK_MAGIC, sizeof(XB_STREAM_CHUNK_MAGIC) - 1);
|
||||
ptr += sizeof(XB_STREAM_CHUNK_MAGIC) - 1;
|
||||
|
||||
*ptr++ = 0; /* Chunk flags */
|
||||
|
||||
*ptr++ = (uchar) XB_CHUNK_TYPE_RENAME; /* Chunk type */
|
||||
size_t path_len = strlen(old_path);
|
||||
int4store(ptr, path_len); /* Path length */
|
||||
ptr += 4;
|
||||
|
||||
memcpy(ptr, old_path, path_len); /* Path */
|
||||
ptr += path_len;
|
||||
|
||||
path_len = strlen(new_path);
|
||||
int4store(ptr, path_len); /* Path length */
|
||||
ptr += 4;
|
||||
|
||||
memcpy(ptr, new_path, path_len); /* Path */
|
||||
ptr += path_len;
|
||||
|
||||
xb_ad(ptr <= tmpbuf + sizeof(tmpbuf));
|
||||
|
||||
pthread_mutex_lock(&stream->mutex);
|
||||
|
||||
ssize_t result = stream->write(stream->user_data, tmpbuf,
|
||||
(ulonglong) (ptr - tmpbuf));
|
||||
|
||||
pthread_mutex_unlock(&stream->mutex);
|
||||
|
||||
return result < 0;
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -26,6 +26,13 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA
|
||||
#include "xbstream.h"
|
||||
#include "fil0fil.h"
|
||||
#include <set>
|
||||
#include "handler.h"
|
||||
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <tuple>
|
||||
#include <functional>
|
||||
|
||||
|
||||
#define XB_TOOL_NAME "mariadb-backup"
|
||||
#define XB_HISTORY_TABLE "mysql.mariadb_backup_history"
|
||||
@ -110,7 +117,7 @@ extern my_bool xtrabackup_decrypt_decompress;
|
||||
extern char *innobase_data_file_path;
|
||||
extern longlong innobase_page_size;
|
||||
|
||||
extern int xtrabackup_parallel;
|
||||
extern uint xtrabackup_parallel;
|
||||
|
||||
extern my_bool xb_close_files;
|
||||
extern const char *xtrabackup_compress_alg;
|
||||
@ -129,7 +136,6 @@ extern my_bool opt_galera_info;
|
||||
extern my_bool opt_slave_info;
|
||||
extern my_bool opt_no_lock;
|
||||
extern my_bool opt_safe_slave_backup;
|
||||
extern my_bool opt_rsync;
|
||||
extern my_bool opt_force_non_empty_dirs;
|
||||
extern my_bool opt_noversioncheck;
|
||||
extern my_bool opt_no_backup_locks;
|
||||
@ -286,15 +292,40 @@ fil_file_readdir_next_file(
|
||||
os_file_stat_t* info); /*!< in/out: buffer where the
|
||||
info is returned */
|
||||
|
||||
#ifndef DBUG_OFF
|
||||
#include <fil0fil.h>
|
||||
extern void dbug_mariabackup_event(const char *event,
|
||||
const fil_space_t::name_type key);
|
||||
const char *convert_dst(const char *dst);
|
||||
|
||||
#define DBUG_MARIABACKUP_EVENT(A, B) \
|
||||
DBUG_EXECUTE_IF("mariabackup_events", dbug_mariabackup_event(A, B);)
|
||||
#else
|
||||
#define DBUG_MARIABACKUP_EVENT(A, B) /* empty */
|
||||
#endif // DBUG_OFF
|
||||
std::string get_table_version_from_image(const std::vector<uchar> &frm_image);
|
||||
std::pair<bool, legacy_db_type>
|
||||
get_table_engine_from_image(const std::vector<uchar> &frm_image);
|
||||
std::string read_table_version_id(File file);
|
||||
|
||||
std::string convert_tablename_to_filepath(
|
||||
const char *data_dir_path, const std::string &db, const std::string &table);
|
||||
|
||||
std::tuple<std::string, std::string, std::string>
|
||||
convert_filepath_to_tablename(const char *filepath);
|
||||
|
||||
typedef std::string table_key_t;
|
||||
|
||||
inline table_key_t table_key(const std::string &db, const std::string &table) {
|
||||
return std::string(db).append(".").append(table);
|
||||
};
|
||||
|
||||
inline table_key_t table_key(const char *db, const char *table) {
|
||||
return std::string(db).append(".").append(table);
|
||||
};
|
||||
|
||||
typedef std::function<void(std::string, std::string, std::string)>
|
||||
post_copy_table_hook_t;
|
||||
|
||||
my_bool
|
||||
check_if_skip_table(
|
||||
/******************/
|
||||
const char* name); /*!< in: path to the table */
|
||||
|
||||
bool is_log_table(const char *dbname, const char *tablename);
|
||||
bool is_stats_table(const char *dbname, const char *tablename);
|
||||
|
||||
extern my_bool xtrabackup_copy_back;
|
||||
extern my_bool xtrabackup_move_back;
|
||||
#endif /* XB_XTRABACKUP_H */
|
||||
|
11
mysql-test/include/aria_log_control_load.inc
Normal file
11
mysql-test/include/aria_log_control_load.inc
Normal file
@ -0,0 +1,11 @@
|
||||
#
|
||||
# This file loads aria_log_control file into a user variable @aria_log_control.
|
||||
# Set $ARIA_DATADIR before including this file
|
||||
#
|
||||
|
||||
--disable_query_log
|
||||
--copy_file $ARIA_DATADIR/aria_log_control $MYSQLTEST_VARDIR/aria_log_control_tmp
|
||||
--chmod 0777 $MYSQLTEST_VARDIR/aria_log_control_tmp
|
||||
--eval SET @aria_log_control=(SELECT LOAD_FILE('$MYSQLTEST_VARDIR/aria_log_control_tmp'))
|
||||
--remove_file $MYSQLTEST_VARDIR/aria_log_control_tmp
|
||||
--enable_query_log
|
@ -30,7 +30,7 @@ let $_innodb_data_file_path=`select @@innodb_data_file_path`;
|
||||
let $_innodb_data_home_dir=`select @@innodb_data_home_dir`;
|
||||
|
||||
--disable_result_log
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir;
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --parallel=10 --target-dir=$targetdir;
|
||||
--enable_result_log
|
||||
exec $XTRABACKUP --prepare --target-dir=$targetdir;
|
||||
|
||||
|
@ -4,7 +4,7 @@ INSERT into t1 values(1);
|
||||
connect con2, localhost, root,,;
|
||||
connection con2;
|
||||
set lock_wait_timeout=1;
|
||||
SET debug_sync='copy_data_between_tables_before_reset_backup_lock SIGNAL go WAIT_FOR after_backup_stage_block_commit';
|
||||
SET debug_sync='copy_data_between_tables_before_reset_backup_lock SIGNAL go WAIT_FOR after_backup_stage_block_ddl';
|
||||
SET debug_sync='alter_table_after_temp_table_drop SIGNAL temp_table_dropped';
|
||||
SET debug_sync='now WAIT_FOR after_backup_stage_start';ALTER TABLE test.t1 FORCE, algorithm=COPY;|
|
||||
connection default;
|
||||
|
@ -18,7 +18,7 @@ INSERT into t1 values(1);
|
||||
connect con2, localhost, root,,;
|
||||
connection con2;
|
||||
set lock_wait_timeout=1;
|
||||
SET debug_sync='copy_data_between_tables_before_reset_backup_lock SIGNAL go WAIT_FOR after_backup_stage_block_commit';
|
||||
SET debug_sync='copy_data_between_tables_before_reset_backup_lock SIGNAL go WAIT_FOR after_backup_stage_block_ddl';
|
||||
SET debug_sync='alter_table_after_temp_table_drop SIGNAL temp_table_dropped';
|
||||
DELIMITER |;
|
||||
send SET debug_sync='now WAIT_FOR after_backup_stage_start';ALTER TABLE test.t1 FORCE, algorithm=COPY;|
|
||||
@ -27,7 +27,7 @@ connection default;
|
||||
|
||||
# setup mariabackup events
|
||||
let after_backup_stage_start=SET debug_sync='now SIGNAL after_backup_stage_start WAIT_FOR go';
|
||||
let after_backup_stage_block_commit=SET debug_sync='now SIGNAL after_backup_stage_block_commit';
|
||||
let after_backup_stage_block_ddl=SET debug_sync='now SIGNAL after_backup_stage_block_ddl';
|
||||
let backup_fix_ddl=SET debug_sync='now WAIT_FOR temp_table_dropped';
|
||||
--disable_result_log
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir --dbug=+d,mariabackup_events;
|
||||
|
@ -19,7 +19,7 @@ dec $n;
|
||||
}
|
||||
|
||||
--disable_result_log
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$basedir;
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --parallel=10 --target-dir=$basedir;
|
||||
--enable_result_log
|
||||
let $n=100;
|
||||
while ($n) {
|
||||
@ -36,7 +36,7 @@ disconnect flush_log;
|
||||
connection default;
|
||||
|
||||
--disable_result_log
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --ftwrl-wait-timeout=5 --ftwrl-wait-threshold=300 --ftwrl-wait-query-type=all --target-dir=$incremental_dir --incremental-basedir=$basedir ;
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --parallel=10 --ftwrl-wait-timeout=5 --ftwrl-wait-threshold=300 --ftwrl-wait-query-type=all --target-dir=$incremental_dir --incremental-basedir=$basedir ;
|
||||
exec $XTRABACKUP --prepare --verbose --target-dir=$basedir ;
|
||||
--enable_result_log
|
||||
|
||||
|
@ -8,7 +8,7 @@ start transaction;
|
||||
INSERT INTO t VALUES(1);
|
||||
|
||||
--disable_result_log
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$basedir;
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --parallel=10 --target-dir=$basedir;
|
||||
--enable_result_log
|
||||
|
||||
exec $XTRABACKUP --prepare --target-dir=$basedir ;
|
||||
|
1
mysql-test/suite/mariabackup/aria_backup.opt
Normal file
1
mysql-test/suite/mariabackup/aria_backup.opt
Normal file
@ -0,0 +1 @@
|
||||
--loose-partition --loose-aria-log-file-size=8388608
|
780
mysql-test/suite/mariabackup/aria_backup.result
Normal file
780
mysql-test/suite/mariabackup/aria_backup.result
Normal file
@ -0,0 +1,780 @@
|
||||
###
|
||||
# Test for backup to stream
|
||||
#####
|
||||
###
|
||||
# Test for mix of online/offline backup tables
|
||||
#####
|
||||
CREATE TABLE t_default(i INT PRIMARY KEY)
|
||||
ENGINE ARIA;
|
||||
INSERT INTO t_default VALUES (1);
|
||||
CREATE TABLE t_tr_p_ch(i INT PRIMARY KEY)
|
||||
ENGINE ARIA TRANSACTIONAL=1 ROW_FORMAT=PAGE PAGE_CHECKSUM=1;
|
||||
INSERT INTO t_tr_p_ch VALUES (1);
|
||||
CREATE TABLE t_tr_p_nch(i INT PRIMARY KEY)
|
||||
ENGINE ARIA TRANSACTIONAL=1 ROW_FORMAT=PAGE PAGE_CHECKSUM=0;
|
||||
INSERT INTO t_tr_p_nch VALUES (1);
|
||||
CREATE TABLE t_p_ch(i INT PRIMARY KEY)
|
||||
ENGINE ARIA TRANSACTIONAL=0 ROW_FORMAT=PAGE PAGE_CHECKSUM=1;
|
||||
INSERT INTO t_p_ch VALUES (1);
|
||||
CREATE TABLE t_p_nch(i INT PRIMARY KEY)
|
||||
ENGINE ARIA TRANSACTIONAL=0 ROW_FORMAT=PAGE PAGE_CHECKSUM=0;
|
||||
INSERT INTO t_p_nch VALUES (1);
|
||||
CREATE TABLE t_fixed(i INT PRIMARY KEY)
|
||||
ENGINE ARIA TRANSACTIONAL=0 ROW_FORMAT=FIXED PAGE_CHECKSUM=1;
|
||||
INSERT INTO t_fixed VALUES (1);
|
||||
CREATE TABLE t_dyn(i INT PRIMARY KEY)
|
||||
ENGINE ARIA TRANSACTIONAL=0 ROW_FORMAT=DYNAMIC PAGE_CHECKSUM=1;
|
||||
INSERT INTO t_dyn VALUES (1);
|
||||
# Test for partitioned table
|
||||
CREATE TABLE t_part_online(i INT PRIMARY KEY)
|
||||
ENGINE ARIA TRANSACTIONAL = 1 PAGE_CHECKSUM = 1
|
||||
PARTITION BY RANGE( i ) (
|
||||
PARTITION p0 VALUES LESS THAN (10),
|
||||
PARTITION p1 VALUES LESS THAN (20),
|
||||
PARTITION p2 VALUES LESS THAN (30)
|
||||
);
|
||||
INSERT INTO t_part_online VALUES(5);
|
||||
INSERT INTO t_part_online VALUES(15);
|
||||
INSERT INTO t_part_online VALUES(25);
|
||||
SELECT * FROM t_part_online;
|
||||
i
|
||||
5
|
||||
15
|
||||
25
|
||||
CREATE TABLE t_part_offline(i INT)
|
||||
ENGINE ARIA TRANSACTIONAL = 0 PAGE_CHECKSUM = 0
|
||||
PARTITION BY RANGE( i ) (
|
||||
PARTITION p0 VALUES LESS THAN (10),
|
||||
PARTITION p1 VALUES LESS THAN (20),
|
||||
PARTITION p2 VALUES LESS THAN (30)
|
||||
);
|
||||
INSERT INTO t_part_offline VALUES(5);
|
||||
INSERT INTO t_part_offline VALUES(15);
|
||||
INSERT INTO t_part_offline VALUES(25);
|
||||
# Test for filename to tablename mapping
|
||||
CREATE TABLE `t 1 t-1`(i INT PRIMARY KEY)
|
||||
ENGINE ARIA TRANSACTIONAL=1 ROW_FORMAT=PAGE PAGE_CHECKSUM=1;
|
||||
INSERT INTO `t 1 t-1` VALUES (1);
|
||||
CREATE TABLE `t-part online`(i INT PRIMARY KEY)
|
||||
ENGINE ARIA TRANSACTIONAL = 1 PAGE_CHECKSUM = 1
|
||||
PARTITION BY RANGE( i ) (
|
||||
PARTITION p0 VALUES LESS THAN (10),
|
||||
PARTITION p1 VALUES LESS THAN (20),
|
||||
PARTITION p2 VALUES LESS THAN (30)
|
||||
);
|
||||
INSERT INTO `t-part online` VALUES(5);
|
||||
INSERT INTO `t-part online` VALUES(15);
|
||||
INSERT INTO `t-part online` VALUES(25);
|
||||
###
|
||||
# Test for redo log files backup;
|
||||
#####
|
||||
CREATE TABLE t_logs_1(i INT)
|
||||
ENGINE ARIA TRANSACTIONAL=1 ROW_FORMAT=PAGE PAGE_CHECKSUM=1;
|
||||
CREATE TABLE t_logs_2 LIKE t_logs_1;
|
||||
CREATE TABLE t_bulk_ins LIKE t_logs_1;
|
||||
INSERT INTO t_logs_1 VALUES
|
||||
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
|
||||
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
|
||||
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
|
||||
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
|
||||
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
|
||||
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
|
||||
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
|
||||
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
|
||||
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
|
||||
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9);
|
||||
# Generate several log files
|
||||
INSERT INTO t_logs_1 SELECT * FROM t_logs_1;
|
||||
INSERT INTO t_logs_1 SELECT * FROM t_logs_1;
|
||||
INSERT INTO t_logs_1 SELECT * FROM t_logs_1;
|
||||
INSERT INTO t_logs_1 SELECT * FROM t_logs_1;
|
||||
INSERT INTO t_logs_1 SELECT * FROM t_logs_1;
|
||||
INSERT INTO t_logs_1 SELECT * FROM t_logs_1;
|
||||
INSERT INTO t_logs_1 SELECT * FROM t_logs_1;
|
||||
INSERT INTO t_logs_1 SELECT * FROM t_logs_1;
|
||||
INSERT INTO t_logs_1 SELECT * FROM t_logs_1;
|
||||
INSERT INTO t_logs_1 SELECT * FROM t_logs_1;
|
||||
INSERT INTO t_logs_1 SELECT * FROM t_logs_1;
|
||||
INSERT INTO t_logs_1 SELECT * FROM t_logs_1;
|
||||
INSERT INTO t_logs_1 SELECT * FROM t_logs_1;
|
||||
INSERT INTO t_logs_1 SELECT * FROM t_logs_1;
|
||||
###
|
||||
# Test for DML during backup for online backup
|
||||
#####
|
||||
CREATE TABLE t_dml_ins(i INT PRIMARY KEY)
|
||||
ENGINE ARIA TRANSACTIONAL=1 ROW_FORMAT=PAGE PAGE_CHECKSUM=1;
|
||||
INSERT INTO t_dml_ins VALUES(1);
|
||||
CREATE TABLE t_dml_upd(i INT PRIMARY KEY)
|
||||
ENGINE ARIA TRANSACTIONAL=1 ROW_FORMAT=PAGE PAGE_CHECKSUM=1;
|
||||
INSERT INTO t_dml_upd VALUES(1);
|
||||
CREATE TABLE t_dml_del(i INT PRIMARY KEY)
|
||||
ENGINE ARIA TRANSACTIONAL=1 ROW_FORMAT=PAGE PAGE_CHECKSUM=1;
|
||||
INSERT INTO t_dml_del VALUES(1);
|
||||
###
|
||||
# Test for DDL during backup for online backup
|
||||
#####
|
||||
CREATE DATABASE test_for_db_drop;
|
||||
CREATE TABLE test_for_db_drop.t(i INT PRIMARY KEY) ENGINE ARIA;
|
||||
CREATE TABLE t_db_create(i INT PRIMARY KEY) ENGINE ARIA;
|
||||
SHOW DATABASES;
|
||||
Database
|
||||
information_schema
|
||||
mtr
|
||||
mysql
|
||||
performance_schema
|
||||
sys
|
||||
test
|
||||
test_for_db_drop
|
||||
CREATE TABLE t_alter(i INT PRIMARY KEY) ENGINE ARIA;
|
||||
INSERT INTO t_alter VALUES (1);
|
||||
CREATE TABLE t_trunc(i INT PRIMARY KEY) ENGINE ARIA;
|
||||
INSERT INTO t_trunc VALUES (1);
|
||||
CREATE TABLE t_ch_i (i int(10), index(i) ) ENGINE=Aria;
|
||||
INSERT INTO t_ch_i VALUES(1);
|
||||
CREATE TABLE t_change_engine(i INT PRIMARY KEY) ENGINE InnoDB;
|
||||
INSERT INTO t_change_engine VALUES (1);
|
||||
CREATE TABLE t_rename(i INT PRIMARY KEY) ENGINE ARIA;
|
||||
CREATE DATABASE test_for_rename;
|
||||
CREATE TABLE t_rename_2(i INT PRIMARY KEY) ENGINE ARIA;
|
||||
CREATE TABLE t_rename_3(i INT PRIMARY KEY) ENGINE ARIA;
|
||||
CREATE TABLE t_rename_4(i INT PRIMARY KEY) ENGINE ARIA;
|
||||
CREATE TABLE t_delete(i INT PRIMARY KEY) ENGINE ARIA;
|
||||
CREATE TABLE t_delete_2(i INT PRIMARY KEY) ENGINE ARIA;
|
||||
CREATE TABLE t_rename_alter(i INT PRIMARY KEY) ENGINE ARIA;
|
||||
CREATE TABLE t_rename_create(i INT PRIMARY KEY) ENGINE ARIA;
|
||||
CREATE TABLE t_part_create(i INT PRIMARY KEY) ENGINE ARIA;
|
||||
CREATE TABLE t_part_add_part(i INT PRIMARY KEY) ENGINE ARIA;
|
||||
CREATE TABLE t_part_change_eng(i INT PRIMARY KEY) ENGINE ARIA PARTITION BY HASH(i) PARTITIONS 2;
|
||||
CREATE TABLE t_part_change_eng_2(i INT PRIMARY KEY) ENGINE InnoDB PARTITION BY HASH(i) PARTITIONS 2;
|
||||
CREATE TABLE t_part_change_eng_3(i INT PRIMARY KEY) ENGINE Aria;
|
||||
CREATE TABLE t_part_alter(i INT PRIMARY KEY) ENGINE Aria PARTITION BY HASH(i) PARTITIONS 2;
|
||||
CREATE TABLE t_part_alter_2(i INT PRIMARY KEY) ENGINE Aria PARTITION BY HASH(i) PARTITIONS 3;
|
||||
CREATE TABLE t_part_drop(i INT PRIMARY KEY) ENGINE Aria PARTITION BY HASH(i) PARTITIONS 2;
|
||||
CREATE TABLE t_part_rename(i INT PRIMARY KEY) ENGINE Aria PARTITION BY HASH(i) PARTITIONS 2;
|
||||
CREATE TABLE t_part_rename_3(i INT PRIMARY KEY) ENGINE Aria PARTITION BY HASH(i) PARTITIONS 2;
|
||||
CREATE TABLE t_part_rm_part(i INT PRIMARY KEY) ENGINE Aria PARTITION BY HASH(i) PARTITIONS 2;
|
||||
SET SESSION debug_dbug="+d,maria_flush_whole_log";
|
||||
SET GLOBAL aria_checkpoint_interval=10000;
|
||||
### Backup to stream
|
||||
# xtrabackup prepare
|
||||
# shutdown server
|
||||
# remove datadir
|
||||
# xtrabackup move back
|
||||
# restart
|
||||
### Result for DDL test
|
||||
SHOW CREATE TABLE t_alter;
|
||||
Table Create Table
|
||||
t_alter CREATE TABLE `t_alter` (
|
||||
`i` int(11) NOT NULL,
|
||||
`c` int(11) DEFAULT NULL,
|
||||
PRIMARY KEY (`i`)
|
||||
) ENGINE=Aria DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci PAGE_CHECKSUM=1
|
||||
SELECT * FROM t_alter;
|
||||
i c
|
||||
1 NULL
|
||||
SHOW CREATE TABLE t_change_engine;
|
||||
Table Create Table
|
||||
t_change_engine CREATE TABLE `t_change_engine` (
|
||||
`i` int(11) NOT NULL,
|
||||
PRIMARY KEY (`i`)
|
||||
) ENGINE=Aria DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci PAGE_CHECKSUM=1
|
||||
SELECT * FROM t_change_engine;
|
||||
i
|
||||
1
|
||||
SELECT * FROM t_trunc;
|
||||
i
|
||||
1
|
||||
SELECT * FROM t_ch_i;
|
||||
i
|
||||
1
|
||||
SELECT * FROM t_rename_new;
|
||||
i
|
||||
SELECT * FROM test_for_rename.t_rename_new_2;
|
||||
i
|
||||
SELECT * FROM t_rename_new_new_3;
|
||||
i
|
||||
SELECT * FROM t_rename_new_4;
|
||||
i
|
||||
SELECT * FROM t_delete;
|
||||
ERROR 42S02: Table 'test.t_delete' doesn't exist
|
||||
SHOW CREATE TABLE t_delete_2;
|
||||
Table Create Table
|
||||
t_delete_2 CREATE TABLE `t_delete_2` (
|
||||
`i` int(11) NOT NULL,
|
||||
PRIMARY KEY (`i`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci PAGE_CHECKSUM=1
|
||||
SELECT * FROM t_rename_alter_2;
|
||||
i c
|
||||
SELECT * FROM t_rename_create;
|
||||
d
|
||||
SELECT * FROM t_rename_create_new;
|
||||
i
|
||||
SHOW CREATE TABLE t_part_create_2;
|
||||
Table Create Table
|
||||
t_part_create_2 CREATE TABLE `t_part_create_2` (
|
||||
`i` int(11) DEFAULT NULL
|
||||
) ENGINE=Aria DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
|
||||
PARTITION BY HASH (`i`)
|
||||
PARTITIONS 2
|
||||
SELECT * FROM t_part_create_2;
|
||||
i
|
||||
SHOW CREATE TABLE t_part_add_part;
|
||||
Table Create Table
|
||||
t_part_add_part CREATE TABLE `t_part_add_part` (
|
||||
`i` int(11) NOT NULL,
|
||||
PRIMARY KEY (`i`)
|
||||
) ENGINE=Aria DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci PAGE_CHECKSUM=1
|
||||
PARTITION BY HASH (`i`)
|
||||
PARTITIONS 2
|
||||
SELECT * FROM t_part_add_part;
|
||||
i
|
||||
SHOW CREATE TABLE t_part_change_eng;
|
||||
Table Create Table
|
||||
t_part_change_eng CREATE TABLE `t_part_change_eng` (
|
||||
`i` int(11) NOT NULL,
|
||||
PRIMARY KEY (`i`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
|
||||
PARTITION BY HASH (`i`)
|
||||
PARTITIONS 2
|
||||
SELECT * FROM t_part_change_eng;
|
||||
i
|
||||
SHOW CREATE TABLE t_part_change_eng_2;
|
||||
Table Create Table
|
||||
t_part_change_eng_2 CREATE TABLE `t_part_change_eng_2` (
|
||||
`i` int(11) NOT NULL,
|
||||
PRIMARY KEY (`i`)
|
||||
) ENGINE=Aria DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
|
||||
PARTITION BY HASH (`i`)
|
||||
PARTITIONS 2
|
||||
SELECT * FROM t_part_change_eng_2;
|
||||
i
|
||||
SELECT * FROM t_part_alter;
|
||||
i c
|
||||
SHOW CREATE TABLE t_part_alter_2;
|
||||
Table Create Table
|
||||
t_part_alter_2 CREATE TABLE `t_part_alter_2` (
|
||||
`i` int(11) NOT NULL,
|
||||
PRIMARY KEY (`i`)
|
||||
) ENGINE=Aria DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
|
||||
PARTITION BY HASH (`i`)
|
||||
PARTITIONS 2
|
||||
SELECT * FROM t_part_alter_2;
|
||||
i
|
||||
SELECT * FROM t_part_drop;
|
||||
ERROR 42S02: Table 'test.t_part_drop' doesn't exist
|
||||
SELECT * FROM t_part_rename;
|
||||
ERROR 42S02: Table 'test.t_part_rename' doesn't exist
|
||||
SELECT * FROM t_part_rename_2;
|
||||
i
|
||||
SELECT * FROM t_part_rename_3;
|
||||
ERROR 42S02: Table 'test.t_part_rename_3' doesn't exist
|
||||
SELECT * FROM test_for_rename.t_part_rename_4;
|
||||
i
|
||||
SHOW CREATE TABLE t_part_rm_part;
|
||||
Table Create Table
|
||||
t_part_rm_part CREATE TABLE `t_part_rm_part` (
|
||||
`i` int(11) NOT NULL,
|
||||
`c` int(11) DEFAULT NULL,
|
||||
PRIMARY KEY (`i`)
|
||||
) ENGINE=Aria DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci PAGE_CHECKSUM=1
|
||||
SELECT * FROM t_part_rm_part;
|
||||
i c
|
||||
SHOW DATABASES;
|
||||
Database
|
||||
information_schema
|
||||
mtr
|
||||
mysql
|
||||
performance_schema
|
||||
sys
|
||||
test
|
||||
test_for_db_create
|
||||
test_for_rename
|
||||
### Clean up for DDL test
|
||||
DROP DATABASE test_for_db_create;
|
||||
DROP TABLE t_db_create;
|
||||
DROP TABLE t_change_engine;
|
||||
DROP TABLE t_alter;
|
||||
DROP TABLE t_trunc;
|
||||
DROP TABLE t_ch_i;
|
||||
DROP TABLE t_rename_new;
|
||||
DROP TABLE t_rename_new_new_3;
|
||||
DROP TABLE t_rename_new_4;
|
||||
DROP TABLE t_delete_2;
|
||||
DROP TABLE t_rename_alter_2;
|
||||
DROP TABLE t_rename_create;
|
||||
DROP TABLE t_rename_create_new;
|
||||
DROP TABLE t_part_create;
|
||||
DROP TABLE t_part_create_2;
|
||||
DROP TABLE t_part_add_part;
|
||||
DROP TABLE t_part_change_eng;
|
||||
DROP TABLE t_part_change_eng_2;
|
||||
DROP TABLE t_part_change_eng_3;
|
||||
DROP TABLE t_part_alter;
|
||||
DROP TABLE t_part_alter_2;
|
||||
DROP TABLE t_part_rename_2;
|
||||
DROP TABLE t_part_rm_part;
|
||||
DROP DATABASE test_for_rename;
|
||||
### Result for DML test
|
||||
SELECT * FROM t_dml_ins;
|
||||
i
|
||||
1
|
||||
2
|
||||
SELECT * FROM t_dml_upd;
|
||||
i
|
||||
2
|
||||
SELECT * FROM t_dml_del;
|
||||
i
|
||||
### Clean up for DML test
|
||||
DROP TABLE t_dml_ins;
|
||||
DROP TABLE t_dml_upd;
|
||||
DROP TABLE t_dml_del;
|
||||
### Result for redo log files backup
|
||||
# ok
|
||||
# ok
|
||||
# ok
|
||||
### Cleanup for redo log files backup
|
||||
DROP TABLE t_logs_1;
|
||||
DROP TABLE t_logs_2;
|
||||
DROP TABLE t_bulk_ins;
|
||||
### Result for online/offline tables test
|
||||
SELECT * FROM t_default;
|
||||
i
|
||||
1
|
||||
SELECT * FROM t_tr_p_ch;
|
||||
i
|
||||
1
|
||||
SELECT * FROM t_tr_p_nch;
|
||||
i
|
||||
1
|
||||
SELECT * FROM t_p_ch;
|
||||
i
|
||||
1
|
||||
SELECT * FROM t_p_nch;
|
||||
i
|
||||
1
|
||||
SELECT * FROM t_fixed;
|
||||
i
|
||||
1
|
||||
SELECT * FROM t_dyn;
|
||||
i
|
||||
1
|
||||
SELECT * FROM t_part_online;
|
||||
i
|
||||
5
|
||||
15
|
||||
25
|
||||
SELECT * FROM t_part_offline;
|
||||
i
|
||||
5
|
||||
15
|
||||
25
|
||||
SELECT * FROM `t 1 t-1`;
|
||||
i
|
||||
1
|
||||
SELECT * FROM `t-part online`;
|
||||
i
|
||||
5
|
||||
15
|
||||
25
|
||||
### Cleanup for online/offline tables test
|
||||
DROP TABLE t_default;
|
||||
DROP TABLE t_tr_p_ch;
|
||||
DROP TABLE t_tr_p_nch;
|
||||
DROP TABLE t_p_ch;
|
||||
DROP TABLE t_p_nch;
|
||||
DROP TABLE t_fixed;
|
||||
DROP TABLE t_dyn;
|
||||
DROP TABLE t_part_online;
|
||||
DROP TABLE t_part_offline;
|
||||
DROP TABLE `t 1 t-1`;
|
||||
DROP TABLE `t-part online`;
|
||||
###
|
||||
# Test for backup to directory
|
||||
#####
|
||||
###
|
||||
# Test for mix of online/offline backup tables
|
||||
#####
|
||||
CREATE TABLE t_default(i INT PRIMARY KEY)
|
||||
ENGINE ARIA;
|
||||
INSERT INTO t_default VALUES (1);
|
||||
CREATE TABLE t_tr_p_ch(i INT PRIMARY KEY)
|
||||
ENGINE ARIA TRANSACTIONAL=1 ROW_FORMAT=PAGE PAGE_CHECKSUM=1;
|
||||
INSERT INTO t_tr_p_ch VALUES (1);
|
||||
CREATE TABLE t_tr_p_nch(i INT PRIMARY KEY)
|
||||
ENGINE ARIA TRANSACTIONAL=1 ROW_FORMAT=PAGE PAGE_CHECKSUM=0;
|
||||
INSERT INTO t_tr_p_nch VALUES (1);
|
||||
CREATE TABLE t_p_ch(i INT PRIMARY KEY)
|
||||
ENGINE ARIA TRANSACTIONAL=0 ROW_FORMAT=PAGE PAGE_CHECKSUM=1;
|
||||
INSERT INTO t_p_ch VALUES (1);
|
||||
CREATE TABLE t_p_nch(i INT PRIMARY KEY)
|
||||
ENGINE ARIA TRANSACTIONAL=0 ROW_FORMAT=PAGE PAGE_CHECKSUM=0;
|
||||
INSERT INTO t_p_nch VALUES (1);
|
||||
CREATE TABLE t_fixed(i INT PRIMARY KEY)
|
||||
ENGINE ARIA TRANSACTIONAL=0 ROW_FORMAT=FIXED PAGE_CHECKSUM=1;
|
||||
INSERT INTO t_fixed VALUES (1);
|
||||
CREATE TABLE t_dyn(i INT PRIMARY KEY)
|
||||
ENGINE ARIA TRANSACTIONAL=0 ROW_FORMAT=DYNAMIC PAGE_CHECKSUM=1;
|
||||
INSERT INTO t_dyn VALUES (1);
|
||||
# Test for partitioned table
|
||||
CREATE TABLE t_part_online(i INT PRIMARY KEY)
|
||||
ENGINE ARIA TRANSACTIONAL = 1 PAGE_CHECKSUM = 1
|
||||
PARTITION BY RANGE( i ) (
|
||||
PARTITION p0 VALUES LESS THAN (10),
|
||||
PARTITION p1 VALUES LESS THAN (20),
|
||||
PARTITION p2 VALUES LESS THAN (30)
|
||||
);
|
||||
INSERT INTO t_part_online VALUES(5);
|
||||
INSERT INTO t_part_online VALUES(15);
|
||||
INSERT INTO t_part_online VALUES(25);
|
||||
SELECT * FROM t_part_online;
|
||||
i
|
||||
5
|
||||
15
|
||||
25
|
||||
CREATE TABLE t_part_offline(i INT)
|
||||
ENGINE ARIA TRANSACTIONAL = 0 PAGE_CHECKSUM = 0
|
||||
PARTITION BY RANGE( i ) (
|
||||
PARTITION p0 VALUES LESS THAN (10),
|
||||
PARTITION p1 VALUES LESS THAN (20),
|
||||
PARTITION p2 VALUES LESS THAN (30)
|
||||
);
|
||||
INSERT INTO t_part_offline VALUES(5);
|
||||
INSERT INTO t_part_offline VALUES(15);
|
||||
INSERT INTO t_part_offline VALUES(25);
|
||||
# Test for filename to tablename mapping
|
||||
CREATE TABLE `t 1 t-1`(i INT PRIMARY KEY)
|
||||
ENGINE ARIA TRANSACTIONAL=1 ROW_FORMAT=PAGE PAGE_CHECKSUM=1;
|
||||
INSERT INTO `t 1 t-1` VALUES (1);
|
||||
CREATE TABLE `t-part online`(i INT PRIMARY KEY)
|
||||
ENGINE ARIA TRANSACTIONAL = 1 PAGE_CHECKSUM = 1
|
||||
PARTITION BY RANGE( i ) (
|
||||
PARTITION p0 VALUES LESS THAN (10),
|
||||
PARTITION p1 VALUES LESS THAN (20),
|
||||
PARTITION p2 VALUES LESS THAN (30)
|
||||
);
|
||||
INSERT INTO `t-part online` VALUES(5);
|
||||
INSERT INTO `t-part online` VALUES(15);
|
||||
INSERT INTO `t-part online` VALUES(25);
|
||||
###
|
||||
# Test for redo log files backup;
|
||||
#####
|
||||
CREATE TABLE t_logs_1(i INT)
|
||||
ENGINE ARIA TRANSACTIONAL=1 ROW_FORMAT=PAGE PAGE_CHECKSUM=1;
|
||||
CREATE TABLE t_logs_2 LIKE t_logs_1;
|
||||
CREATE TABLE t_bulk_ins LIKE t_logs_1;
|
||||
INSERT INTO t_logs_1 VALUES
|
||||
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
|
||||
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
|
||||
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
|
||||
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
|
||||
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
|
||||
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
|
||||
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
|
||||
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
|
||||
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
|
||||
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9);
|
||||
# Generate several log files
|
||||
INSERT INTO t_logs_1 SELECT * FROM t_logs_1;
|
||||
INSERT INTO t_logs_1 SELECT * FROM t_logs_1;
|
||||
INSERT INTO t_logs_1 SELECT * FROM t_logs_1;
|
||||
INSERT INTO t_logs_1 SELECT * FROM t_logs_1;
|
||||
INSERT INTO t_logs_1 SELECT * FROM t_logs_1;
|
||||
INSERT INTO t_logs_1 SELECT * FROM t_logs_1;
|
||||
INSERT INTO t_logs_1 SELECT * FROM t_logs_1;
|
||||
INSERT INTO t_logs_1 SELECT * FROM t_logs_1;
|
||||
INSERT INTO t_logs_1 SELECT * FROM t_logs_1;
|
||||
INSERT INTO t_logs_1 SELECT * FROM t_logs_1;
|
||||
INSERT INTO t_logs_1 SELECT * FROM t_logs_1;
|
||||
INSERT INTO t_logs_1 SELECT * FROM t_logs_1;
|
||||
INSERT INTO t_logs_1 SELECT * FROM t_logs_1;
|
||||
INSERT INTO t_logs_1 SELECT * FROM t_logs_1;
|
||||
###
|
||||
# Test for DML during backup for online backup
|
||||
#####
|
||||
CREATE TABLE t_dml_ins(i INT PRIMARY KEY)
|
||||
ENGINE ARIA TRANSACTIONAL=1 ROW_FORMAT=PAGE PAGE_CHECKSUM=1;
|
||||
INSERT INTO t_dml_ins VALUES(1);
|
||||
CREATE TABLE t_dml_upd(i INT PRIMARY KEY)
|
||||
ENGINE ARIA TRANSACTIONAL=1 ROW_FORMAT=PAGE PAGE_CHECKSUM=1;
|
||||
INSERT INTO t_dml_upd VALUES(1);
|
||||
CREATE TABLE t_dml_del(i INT PRIMARY KEY)
|
||||
ENGINE ARIA TRANSACTIONAL=1 ROW_FORMAT=PAGE PAGE_CHECKSUM=1;
|
||||
INSERT INTO t_dml_del VALUES(1);
|
||||
###
|
||||
# Test for DDL during backup for online backup
|
||||
#####
|
||||
CREATE DATABASE test_for_db_drop;
|
||||
CREATE TABLE test_for_db_drop.t(i INT PRIMARY KEY) ENGINE ARIA;
|
||||
CREATE TABLE t_db_create(i INT PRIMARY KEY) ENGINE ARIA;
|
||||
SHOW DATABASES;
|
||||
Database
|
||||
information_schema
|
||||
mtr
|
||||
mysql
|
||||
performance_schema
|
||||
sys
|
||||
test
|
||||
test_for_db_drop
|
||||
CREATE TABLE t_alter(i INT PRIMARY KEY) ENGINE ARIA;
|
||||
INSERT INTO t_alter VALUES (1);
|
||||
CREATE TABLE t_trunc(i INT PRIMARY KEY) ENGINE ARIA;
|
||||
INSERT INTO t_trunc VALUES (1);
|
||||
CREATE TABLE t_ch_i (i int(10), index(i) ) ENGINE=Aria;
|
||||
INSERT INTO t_ch_i VALUES(1);
|
||||
CREATE TABLE t_change_engine(i INT PRIMARY KEY) ENGINE InnoDB;
|
||||
INSERT INTO t_change_engine VALUES (1);
|
||||
CREATE TABLE t_rename(i INT PRIMARY KEY) ENGINE ARIA;
|
||||
CREATE DATABASE test_for_rename;
|
||||
CREATE TABLE t_rename_2(i INT PRIMARY KEY) ENGINE ARIA;
|
||||
CREATE TABLE t_rename_3(i INT PRIMARY KEY) ENGINE ARIA;
|
||||
CREATE TABLE t_rename_4(i INT PRIMARY KEY) ENGINE ARIA;
|
||||
CREATE TABLE t_delete(i INT PRIMARY KEY) ENGINE ARIA;
|
||||
CREATE TABLE t_delete_2(i INT PRIMARY KEY) ENGINE ARIA;
|
||||
CREATE TABLE t_rename_alter(i INT PRIMARY KEY) ENGINE ARIA;
|
||||
CREATE TABLE t_rename_create(i INT PRIMARY KEY) ENGINE ARIA;
|
||||
CREATE TABLE t_part_create(i INT PRIMARY KEY) ENGINE ARIA;
|
||||
CREATE TABLE t_part_add_part(i INT PRIMARY KEY) ENGINE ARIA;
|
||||
CREATE TABLE t_part_change_eng(i INT PRIMARY KEY) ENGINE ARIA PARTITION BY HASH(i) PARTITIONS 2;
|
||||
CREATE TABLE t_part_change_eng_2(i INT PRIMARY KEY) ENGINE InnoDB PARTITION BY HASH(i) PARTITIONS 2;
|
||||
CREATE TABLE t_part_change_eng_3(i INT PRIMARY KEY) ENGINE Aria;
|
||||
CREATE TABLE t_part_alter(i INT PRIMARY KEY) ENGINE Aria PARTITION BY HASH(i) PARTITIONS 2;
|
||||
CREATE TABLE t_part_alter_2(i INT PRIMARY KEY) ENGINE Aria PARTITION BY HASH(i) PARTITIONS 3;
|
||||
CREATE TABLE t_part_drop(i INT PRIMARY KEY) ENGINE Aria PARTITION BY HASH(i) PARTITIONS 2;
|
||||
CREATE TABLE t_part_rename(i INT PRIMARY KEY) ENGINE Aria PARTITION BY HASH(i) PARTITIONS 2;
|
||||
CREATE TABLE t_part_rename_3(i INT PRIMARY KEY) ENGINE Aria PARTITION BY HASH(i) PARTITIONS 2;
|
||||
CREATE TABLE t_part_rm_part(i INT PRIMARY KEY) ENGINE Aria PARTITION BY HASH(i) PARTITIONS 2;
|
||||
SET SESSION debug_dbug="+d,maria_flush_whole_log";
|
||||
SET GLOBAL aria_checkpoint_interval=10000;
|
||||
### Backup to dir
|
||||
# xtrabackup prepare
|
||||
# shutdown server
|
||||
# remove datadir
|
||||
# xtrabackup move back
|
||||
# restart
|
||||
### Result for DDL test
|
||||
SHOW CREATE TABLE t_alter;
|
||||
Table Create Table
|
||||
t_alter CREATE TABLE `t_alter` (
|
||||
`i` int(11) NOT NULL,
|
||||
`c` int(11) DEFAULT NULL,
|
||||
PRIMARY KEY (`i`)
|
||||
) ENGINE=Aria DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci PAGE_CHECKSUM=1
|
||||
SELECT * FROM t_alter;
|
||||
i c
|
||||
1 NULL
|
||||
SHOW CREATE TABLE t_change_engine;
|
||||
Table Create Table
|
||||
t_change_engine CREATE TABLE `t_change_engine` (
|
||||
`i` int(11) NOT NULL,
|
||||
PRIMARY KEY (`i`)
|
||||
) ENGINE=Aria DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci PAGE_CHECKSUM=1
|
||||
SELECT * FROM t_change_engine;
|
||||
i
|
||||
1
|
||||
SELECT * FROM t_trunc;
|
||||
i
|
||||
1
|
||||
SELECT * FROM t_ch_i;
|
||||
i
|
||||
1
|
||||
SELECT * FROM t_rename_new;
|
||||
i
|
||||
SELECT * FROM test_for_rename.t_rename_new_2;
|
||||
i
|
||||
SELECT * FROM t_rename_new_new_3;
|
||||
i
|
||||
SELECT * FROM t_rename_new_4;
|
||||
i
|
||||
SELECT * FROM t_delete;
|
||||
ERROR 42S02: Table 'test.t_delete' doesn't exist
|
||||
SHOW CREATE TABLE t_delete_2;
|
||||
Table Create Table
|
||||
t_delete_2 CREATE TABLE `t_delete_2` (
|
||||
`i` int(11) NOT NULL,
|
||||
PRIMARY KEY (`i`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci PAGE_CHECKSUM=1
|
||||
SELECT * FROM t_rename_alter_2;
|
||||
i c
|
||||
SELECT * FROM t_rename_create;
|
||||
d
|
||||
SELECT * FROM t_rename_create_new;
|
||||
i
|
||||
SHOW CREATE TABLE t_part_create_2;
|
||||
Table Create Table
|
||||
t_part_create_2 CREATE TABLE `t_part_create_2` (
|
||||
`i` int(11) DEFAULT NULL
|
||||
) ENGINE=Aria DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
|
||||
PARTITION BY HASH (`i`)
|
||||
PARTITIONS 2
|
||||
SELECT * FROM t_part_create_2;
|
||||
i
|
||||
SHOW CREATE TABLE t_part_add_part;
|
||||
Table Create Table
|
||||
t_part_add_part CREATE TABLE `t_part_add_part` (
|
||||
`i` int(11) NOT NULL,
|
||||
PRIMARY KEY (`i`)
|
||||
) ENGINE=Aria DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci PAGE_CHECKSUM=1
|
||||
PARTITION BY HASH (`i`)
|
||||
PARTITIONS 2
|
||||
SELECT * FROM t_part_add_part;
|
||||
i
|
||||
SHOW CREATE TABLE t_part_change_eng;
|
||||
Table Create Table
|
||||
t_part_change_eng CREATE TABLE `t_part_change_eng` (
|
||||
`i` int(11) NOT NULL,
|
||||
PRIMARY KEY (`i`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
|
||||
PARTITION BY HASH (`i`)
|
||||
PARTITIONS 2
|
||||
SELECT * FROM t_part_change_eng;
|
||||
i
|
||||
SHOW CREATE TABLE t_part_change_eng_2;
|
||||
Table Create Table
|
||||
t_part_change_eng_2 CREATE TABLE `t_part_change_eng_2` (
|
||||
`i` int(11) NOT NULL,
|
||||
PRIMARY KEY (`i`)
|
||||
) ENGINE=Aria DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
|
||||
PARTITION BY HASH (`i`)
|
||||
PARTITIONS 2
|
||||
SELECT * FROM t_part_change_eng_2;
|
||||
i
|
||||
SELECT * FROM t_part_alter;
|
||||
i c
|
||||
SHOW CREATE TABLE t_part_alter_2;
|
||||
Table Create Table
|
||||
t_part_alter_2 CREATE TABLE `t_part_alter_2` (
|
||||
`i` int(11) NOT NULL,
|
||||
PRIMARY KEY (`i`)
|
||||
) ENGINE=Aria DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
|
||||
PARTITION BY HASH (`i`)
|
||||
PARTITIONS 2
|
||||
SELECT * FROM t_part_alter_2;
|
||||
i
|
||||
SELECT * FROM t_part_drop;
|
||||
ERROR 42S02: Table 'test.t_part_drop' doesn't exist
|
||||
SELECT * FROM t_part_rename;
|
||||
ERROR 42S02: Table 'test.t_part_rename' doesn't exist
|
||||
SELECT * FROM t_part_rename_2;
|
||||
i
|
||||
SELECT * FROM t_part_rename_3;
|
||||
ERROR 42S02: Table 'test.t_part_rename_3' doesn't exist
|
||||
SELECT * FROM test_for_rename.t_part_rename_4;
|
||||
i
|
||||
SHOW CREATE TABLE t_part_rm_part;
|
||||
Table Create Table
|
||||
t_part_rm_part CREATE TABLE `t_part_rm_part` (
|
||||
`i` int(11) NOT NULL,
|
||||
`c` int(11) DEFAULT NULL,
|
||||
PRIMARY KEY (`i`)
|
||||
) ENGINE=Aria DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci PAGE_CHECKSUM=1
|
||||
SELECT * FROM t_part_rm_part;
|
||||
i c
|
||||
SHOW DATABASES;
|
||||
Database
|
||||
information_schema
|
||||
mtr
|
||||
mysql
|
||||
performance_schema
|
||||
sys
|
||||
test
|
||||
test_for_db_create
|
||||
test_for_rename
|
||||
### Clean up for DDL test
|
||||
DROP DATABASE test_for_db_create;
|
||||
DROP TABLE t_db_create;
|
||||
DROP TABLE t_change_engine;
|
||||
DROP TABLE t_alter;
|
||||
DROP TABLE t_trunc;
|
||||
DROP TABLE t_ch_i;
|
||||
DROP TABLE t_rename_new;
|
||||
DROP TABLE t_rename_new_new_3;
|
||||
DROP TABLE t_rename_new_4;
|
||||
DROP TABLE t_delete_2;
|
||||
DROP TABLE t_rename_alter_2;
|
||||
DROP TABLE t_rename_create;
|
||||
DROP TABLE t_rename_create_new;
|
||||
DROP TABLE t_part_create;
|
||||
DROP TABLE t_part_create_2;
|
||||
DROP TABLE t_part_add_part;
|
||||
DROP TABLE t_part_change_eng;
|
||||
DROP TABLE t_part_change_eng_2;
|
||||
DROP TABLE t_part_change_eng_3;
|
||||
DROP TABLE t_part_alter;
|
||||
DROP TABLE t_part_alter_2;
|
||||
DROP TABLE t_part_rename_2;
|
||||
DROP TABLE t_part_rm_part;
|
||||
DROP DATABASE test_for_rename;
|
||||
### Result for DML test
|
||||
SELECT * FROM t_dml_ins;
|
||||
i
|
||||
1
|
||||
2
|
||||
SELECT * FROM t_dml_upd;
|
||||
i
|
||||
2
|
||||
SELECT * FROM t_dml_del;
|
||||
i
|
||||
### Clean up for DML test
|
||||
DROP TABLE t_dml_ins;
|
||||
DROP TABLE t_dml_upd;
|
||||
DROP TABLE t_dml_del;
|
||||
### Result for redo log files backup
|
||||
# ok
|
||||
# ok
|
||||
# ok
|
||||
### Cleanup for redo log files backup
|
||||
DROP TABLE t_logs_1;
|
||||
DROP TABLE t_logs_2;
|
||||
DROP TABLE t_bulk_ins;
|
||||
### Result for online/offline tables test
|
||||
SELECT * FROM t_default;
|
||||
i
|
||||
1
|
||||
SELECT * FROM t_tr_p_ch;
|
||||
i
|
||||
1
|
||||
SELECT * FROM t_tr_p_nch;
|
||||
i
|
||||
1
|
||||
SELECT * FROM t_p_ch;
|
||||
i
|
||||
1
|
||||
SELECT * FROM t_p_nch;
|
||||
i
|
||||
1
|
||||
SELECT * FROM t_fixed;
|
||||
i
|
||||
1
|
||||
SELECT * FROM t_dyn;
|
||||
i
|
||||
1
|
||||
SELECT * FROM t_part_online;
|
||||
i
|
||||
5
|
||||
15
|
||||
25
|
||||
SELECT * FROM t_part_offline;
|
||||
i
|
||||
5
|
||||
15
|
||||
25
|
||||
SELECT * FROM `t 1 t-1`;
|
||||
i
|
||||
1
|
||||
SELECT * FROM `t-part online`;
|
||||
i
|
||||
5
|
||||
15
|
||||
25
|
||||
### Cleanup for online/offline tables test
|
||||
DROP TABLE t_default;
|
||||
DROP TABLE t_tr_p_ch;
|
||||
DROP TABLE t_tr_p_nch;
|
||||
DROP TABLE t_p_ch;
|
||||
DROP TABLE t_p_nch;
|
||||
DROP TABLE t_fixed;
|
||||
DROP TABLE t_dyn;
|
||||
DROP TABLE t_part_online;
|
||||
DROP TABLE t_part_offline;
|
||||
DROP TABLE `t 1 t-1`;
|
||||
DROP TABLE `t-part online`;
|
423
mysql-test/suite/mariabackup/aria_backup.test
Normal file
423
mysql-test/suite/mariabackup/aria_backup.test
Normal file
@ -0,0 +1,423 @@
|
||||
--source include/have_aria.inc
|
||||
--source include/have_partition.inc
|
||||
--source include/have_debug.inc
|
||||
--source include/big_test.inc
|
||||
|
||||
--let $targetdir=$MYSQLTEST_VARDIR/tmp/backup
|
||||
--let $backup_stream=2
|
||||
--let $backup_dir=1
|
||||
--let $backup_variant=$backup_stream
|
||||
|
||||
while ($backup_variant) {
|
||||
if ($backup_variant == $backup_stream) {
|
||||
--echo ###
|
||||
--echo # Test for backup to stream
|
||||
--echo #####
|
||||
}
|
||||
if ($backup_variant == $backup_dir) {
|
||||
--echo ###
|
||||
--echo # Test for backup to directory
|
||||
--echo #####
|
||||
}
|
||||
|
||||
--echo ###
|
||||
--echo # Test for mix of online/offline backup tables
|
||||
--echo #####
|
||||
|
||||
CREATE TABLE t_default(i INT PRIMARY KEY)
|
||||
ENGINE ARIA;
|
||||
INSERT INTO t_default VALUES (1);
|
||||
|
||||
CREATE TABLE t_tr_p_ch(i INT PRIMARY KEY)
|
||||
ENGINE ARIA TRANSACTIONAL=1 ROW_FORMAT=PAGE PAGE_CHECKSUM=1;
|
||||
INSERT INTO t_tr_p_ch VALUES (1);
|
||||
|
||||
CREATE TABLE t_tr_p_nch(i INT PRIMARY KEY)
|
||||
ENGINE ARIA TRANSACTIONAL=1 ROW_FORMAT=PAGE PAGE_CHECKSUM=0;
|
||||
INSERT INTO t_tr_p_nch VALUES (1);
|
||||
|
||||
CREATE TABLE t_p_ch(i INT PRIMARY KEY)
|
||||
ENGINE ARIA TRANSACTIONAL=0 ROW_FORMAT=PAGE PAGE_CHECKSUM=1;
|
||||
INSERT INTO t_p_ch VALUES (1);
|
||||
|
||||
CREATE TABLE t_p_nch(i INT PRIMARY KEY)
|
||||
ENGINE ARIA TRANSACTIONAL=0 ROW_FORMAT=PAGE PAGE_CHECKSUM=0;
|
||||
INSERT INTO t_p_nch VALUES (1);
|
||||
|
||||
CREATE TABLE t_fixed(i INT PRIMARY KEY)
|
||||
ENGINE ARIA TRANSACTIONAL=0 ROW_FORMAT=FIXED PAGE_CHECKSUM=1;
|
||||
INSERT INTO t_fixed VALUES (1);
|
||||
|
||||
CREATE TABLE t_dyn(i INT PRIMARY KEY)
|
||||
ENGINE ARIA TRANSACTIONAL=0 ROW_FORMAT=DYNAMIC PAGE_CHECKSUM=1;
|
||||
INSERT INTO t_dyn VALUES (1);
|
||||
|
||||
--echo # Test for partitioned table
|
||||
CREATE TABLE t_part_online(i INT PRIMARY KEY)
|
||||
ENGINE ARIA TRANSACTIONAL = 1 PAGE_CHECKSUM = 1
|
||||
PARTITION BY RANGE( i ) (
|
||||
PARTITION p0 VALUES LESS THAN (10),
|
||||
PARTITION p1 VALUES LESS THAN (20),
|
||||
PARTITION p2 VALUES LESS THAN (30)
|
||||
);
|
||||
|
||||
INSERT INTO t_part_online VALUES(5);
|
||||
INSERT INTO t_part_online VALUES(15);
|
||||
INSERT INTO t_part_online VALUES(25);
|
||||
SELECT * FROM t_part_online;
|
||||
|
||||
CREATE TABLE t_part_offline(i INT)
|
||||
ENGINE ARIA TRANSACTIONAL = 0 PAGE_CHECKSUM = 0
|
||||
PARTITION BY RANGE( i ) (
|
||||
PARTITION p0 VALUES LESS THAN (10),
|
||||
PARTITION p1 VALUES LESS THAN (20),
|
||||
PARTITION p2 VALUES LESS THAN (30)
|
||||
);
|
||||
|
||||
INSERT INTO t_part_offline VALUES(5);
|
||||
INSERT INTO t_part_offline VALUES(15);
|
||||
INSERT INTO t_part_offline VALUES(25);
|
||||
|
||||
--echo # Test for filename to tablename mapping
|
||||
CREATE TABLE `t 1 t-1`(i INT PRIMARY KEY)
|
||||
ENGINE ARIA TRANSACTIONAL=1 ROW_FORMAT=PAGE PAGE_CHECKSUM=1;
|
||||
INSERT INTO `t 1 t-1` VALUES (1);
|
||||
|
||||
CREATE TABLE `t-part online`(i INT PRIMARY KEY)
|
||||
ENGINE ARIA TRANSACTIONAL = 1 PAGE_CHECKSUM = 1
|
||||
PARTITION BY RANGE( i ) (
|
||||
PARTITION p0 VALUES LESS THAN (10),
|
||||
PARTITION p1 VALUES LESS THAN (20),
|
||||
PARTITION p2 VALUES LESS THAN (30)
|
||||
);
|
||||
|
||||
INSERT INTO `t-part online` VALUES(5);
|
||||
INSERT INTO `t-part online` VALUES(15);
|
||||
INSERT INTO `t-part online` VALUES(25);
|
||||
|
||||
|
||||
--echo ###
|
||||
--echo # Test for redo log files backup;
|
||||
--echo #####
|
||||
CREATE TABLE t_logs_1(i INT)
|
||||
ENGINE ARIA TRANSACTIONAL=1 ROW_FORMAT=PAGE PAGE_CHECKSUM=1;
|
||||
CREATE TABLE t_logs_2 LIKE t_logs_1;
|
||||
CREATE TABLE t_bulk_ins LIKE t_logs_1;
|
||||
INSERT INTO t_logs_1 VALUES
|
||||
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
|
||||
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
|
||||
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
|
||||
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
|
||||
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
|
||||
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
|
||||
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
|
||||
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
|
||||
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
|
||||
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9);
|
||||
--echo # Generate several log files
|
||||
--let $i = 0
|
||||
while ($i < 14) {
|
||||
INSERT INTO t_logs_1 SELECT * FROM t_logs_1;
|
||||
--inc $i
|
||||
}
|
||||
|
||||
--echo ###
|
||||
--echo # Test for DML during backup for online backup
|
||||
--echo #####
|
||||
CREATE TABLE t_dml_ins(i INT PRIMARY KEY)
|
||||
ENGINE ARIA TRANSACTIONAL=1 ROW_FORMAT=PAGE PAGE_CHECKSUM=1;
|
||||
INSERT INTO t_dml_ins VALUES(1);
|
||||
--let after_aria_table_copy_test_t_dml_ins=INSERT INTO test.t_dml_ins VALUES(2)
|
||||
CREATE TABLE t_dml_upd(i INT PRIMARY KEY)
|
||||
ENGINE ARIA TRANSACTIONAL=1 ROW_FORMAT=PAGE PAGE_CHECKSUM=1;
|
||||
INSERT INTO t_dml_upd VALUES(1);
|
||||
--let after_aria_table_copy_test_t_dml_upd=UPDATE test.t_dml_upd SET i = 2
|
||||
CREATE TABLE t_dml_del(i INT PRIMARY KEY)
|
||||
ENGINE ARIA TRANSACTIONAL=1 ROW_FORMAT=PAGE PAGE_CHECKSUM=1;
|
||||
INSERT INTO t_dml_del VALUES(1);
|
||||
--let after_aria_table_copy_test_t_dml_del=DELETE FROM test.t_dml_del
|
||||
|
||||
--echo ###
|
||||
--echo # Test for DDL during backup for online backup
|
||||
--echo #####
|
||||
CREATE DATABASE test_for_db_drop;
|
||||
CREATE TABLE test_for_db_drop.t(i INT PRIMARY KEY) ENGINE ARIA;
|
||||
--let after_aria_table_copy_test_for_db_drop_t=DROP DATABASE test_for_db_drop
|
||||
CREATE TABLE t_db_create(i INT PRIMARY KEY) ENGINE ARIA;
|
||||
--let after_aria_table_copy_test_t_db_create=CREATE DATABASE test_for_db_create
|
||||
--sorted_result
|
||||
SHOW DATABASES;
|
||||
|
||||
CREATE TABLE t_alter(i INT PRIMARY KEY) ENGINE ARIA;
|
||||
INSERT INTO t_alter VALUES (1);
|
||||
--let after_aria_table_copy_test_t_alter=ALTER TABLE test.t_alter ADD COLUMN c INT
|
||||
|
||||
CREATE TABLE t_trunc(i INT PRIMARY KEY) ENGINE ARIA;
|
||||
INSERT INTO t_trunc VALUES (1);
|
||||
--let after_aria_table_copy_test_t_trunc=TRUNCATE TABLE test.t_trunc
|
||||
|
||||
CREATE TABLE t_ch_i (i int(10), index(i) ) ENGINE=Aria;
|
||||
INSERT INTO t_ch_i VALUES(1);
|
||||
--let after_aria_table_copy_test_t_ch_i=ALTER TABLE test.t_ch_i DISABLE KEYS
|
||||
|
||||
CREATE TABLE t_change_engine(i INT PRIMARY KEY) ENGINE InnoDB;
|
||||
INSERT INTO t_change_engine VALUES (1);
|
||||
--let after_aria_background=begin not atomic ALTER TABLE test.t_change_engine ENGINE = ARIA; INSERT INTO test.t_logs_1 SELECT * FROM test.t_logs_1; INSERT INTO test.t_bulk_ins SELECT * FROM test.t_logs_1; INSERT INTO test.t_logs_2 SET i = 1; end
|
||||
|
||||
CREATE TABLE t_rename(i INT PRIMARY KEY) ENGINE ARIA;
|
||||
--let after_aria_table_copy_test_t_rename=RENAME TABLE test.t_rename TO test.t_rename_new
|
||||
CREATE DATABASE test_for_rename;
|
||||
CREATE TABLE t_rename_2(i INT PRIMARY KEY) ENGINE ARIA;
|
||||
--let after_aria_table_copy_test_t_rename_2=RENAME TABLE test.t_rename_2 TO test_for_rename.t_rename_new_2
|
||||
|
||||
CREATE TABLE t_rename_3(i INT PRIMARY KEY) ENGINE ARIA;
|
||||
--let after_aria_table_copy_test_t_rename_3=begin not atomic RENAME TABLE test.t_rename_3 TO test.t_rename_new_3; RENAME TABLE test.t_rename_new_3 TO test.t_rename_new_new_3; end
|
||||
|
||||
CREATE TABLE t_rename_4(i INT PRIMARY KEY) ENGINE ARIA;
|
||||
--let after_aria_table_copy_test_t_rename_4=begin not atomic RENAME TABLE test.t_rename_4 TO test.t_rename_new_4; RENAME TABLE test.t_rename_new_4 TO test.t_rename_new_new_4; RENAME TABLE test.t_rename_new_new_4 TO test.t_rename_new_4; end
|
||||
|
||||
CREATE TABLE t_delete(i INT PRIMARY KEY) ENGINE ARIA;
|
||||
--let after_aria_table_copy_test_t_delete=DROP TABLE test.t_delete
|
||||
|
||||
CREATE TABLE t_delete_2(i INT PRIMARY KEY) ENGINE ARIA;
|
||||
--let after_aria_table_copy_test_t_delete_2=ALTER TABLE test.t_delete_2 ENGINE=Innodb
|
||||
|
||||
CREATE TABLE t_rename_alter(i INT PRIMARY KEY) ENGINE ARIA;
|
||||
--let after_aria_table_copy_test_t_rename_alter=begin not atomic RENAME TABLE test.t_rename_alter TO test.t_rename_alter_2; ALTER TABLE test.t_rename_alter_2 ADD COLUMN c INT; end
|
||||
|
||||
CREATE TABLE t_rename_create(i INT PRIMARY KEY) ENGINE ARIA;
|
||||
--let after_aria_table_copy_test_t_rename_create=begin not atomic RENAME TABLE test.t_rename_create TO test.t_rename_create_new; CREATE TABLE test.t_rename_create(d INT PRIMARY KEY) ENGINE ARIA; end
|
||||
|
||||
CREATE TABLE t_part_create(i INT PRIMARY KEY) ENGINE ARIA;
|
||||
--let after_aria_table_copy_test_t_part_create=create table test.t_part_create_2 (i int) engine=Aria PARTITION BY HASH(i) PARTITIONS 2
|
||||
|
||||
CREATE TABLE t_part_add_part(i INT PRIMARY KEY) ENGINE ARIA;
|
||||
--let after_aria_table_copy_test_t_part_add_part=alter table test.t_part_add_part PARTITION BY HASH(i) PARTITIONS 2
|
||||
|
||||
CREATE TABLE t_part_change_eng(i INT PRIMARY KEY) ENGINE ARIA PARTITION BY HASH(i) PARTITIONS 2;
|
||||
--let after_aria_table_copy_test_t_part_change_eng=alter table test.t_part_change_eng ENGINE=InnoDB
|
||||
|
||||
CREATE TABLE t_part_change_eng_2(i INT PRIMARY KEY) ENGINE InnoDB PARTITION BY HASH(i) PARTITIONS 2;
|
||||
CREATE TABLE t_part_change_eng_3(i INT PRIMARY KEY) ENGINE Aria;
|
||||
--let after_aria_table_copy_test_t_part_change_eng_3=alter table test.t_part_change_eng_2 ENGINE=Aria
|
||||
|
||||
CREATE TABLE t_part_alter(i INT PRIMARY KEY) ENGINE Aria PARTITION BY HASH(i) PARTITIONS 2;
|
||||
--let after_aria_table_copy_test_t_part_alter=alter table test.t_part_alter ADD COLUMN c INT
|
||||
|
||||
CREATE TABLE t_part_alter_2(i INT PRIMARY KEY) ENGINE Aria PARTITION BY HASH(i) PARTITIONS 3;
|
||||
--let after_aria_table_copy_test_t_part_alter_2=alter table test.t_part_alter_2 COALESCE PARTITION 1
|
||||
|
||||
CREATE TABLE t_part_drop(i INT PRIMARY KEY) ENGINE Aria PARTITION BY HASH(i) PARTITIONS 2;
|
||||
--let after_aria_table_copy_test_t_part_drop=DROP table test.t_part_drop
|
||||
|
||||
CREATE TABLE t_part_rename(i INT PRIMARY KEY) ENGINE Aria PARTITION BY HASH(i) PARTITIONS 2;
|
||||
--let after_aria_table_copy_test_t_part_rename=RENAME TABLE test.t_part_rename TO test.t_part_rename_2
|
||||
|
||||
CREATE TABLE t_part_rename_3(i INT PRIMARY KEY) ENGINE Aria PARTITION BY HASH(i) PARTITIONS 2;
|
||||
--let after_aria_table_copy_test_t_part_rename_3=RENAME TABLE test.t_part_rename_3 TO test_for_rename.t_part_rename_4
|
||||
|
||||
CREATE TABLE t_part_rm_part(i INT PRIMARY KEY) ENGINE Aria PARTITION BY HASH(i) PARTITIONS 2;
|
||||
--let after_aria_table_copy_test_t_part_rm_part=begin not atomic ALTER TABLE test.t_part_rm_part REMOVE PARTITIONING; ALTER TABLE test.t_part_rm_part ADD COLUMN c INT; end
|
||||
|
||||
SET SESSION debug_dbug="+d,maria_flush_whole_log";
|
||||
SET GLOBAL aria_checkpoint_interval=10000;
|
||||
|
||||
--mkdir $targetdir
|
||||
|
||||
if ($backup_variant == $backup_stream) {
|
||||
--echo ### Backup to stream
|
||||
--let $streamfile=$MYSQLTEST_VARDIR/tmp/backup.xb
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --parallel=10 --target-dir=$targetdir --dbug=+d,mariabackup_events --stream=xbstream > $streamfile 2>$targetdir/backup_stream.log;
|
||||
--disable_result_log
|
||||
exec $XBSTREAM -x -C $targetdir < $streamfile;
|
||||
--enable_result_log
|
||||
}
|
||||
|
||||
if ($backup_variant == $backup_dir) {
|
||||
--echo ### Backup to dir
|
||||
--disable_result_log
|
||||
--exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --parallel=10 --target-dir=$targetdir --dbug=+d,mariabackup_events
|
||||
--enable_result_log
|
||||
}
|
||||
|
||||
--let $t_logs_1_records_count_before_backup=`SELECT COUNT(*) FROM t_logs_1`
|
||||
--let $t_logs_2_records_count_before_backup=`SELECT COUNT(*) FROM t_logs_2`
|
||||
--let $t_bulk_ins_records_count_before_backup=`SELECT COUNT(*) FROM t_bulk_ins`
|
||||
|
||||
--echo # xtrabackup prepare
|
||||
--disable_result_log
|
||||
--exec $XTRABACKUP --prepare --target-dir=$targetdir
|
||||
--source include/restart_and_restore.inc
|
||||
--enable_result_log
|
||||
|
||||
--echo ### Result for DDL test
|
||||
SHOW CREATE TABLE t_alter;
|
||||
SELECT * FROM t_alter;
|
||||
SHOW CREATE TABLE t_change_engine;
|
||||
SELECT * FROM t_change_engine;
|
||||
SELECT * FROM t_trunc;
|
||||
SELECT * FROM t_ch_i;
|
||||
SELECT * FROM t_rename_new;
|
||||
SELECT * FROM test_for_rename.t_rename_new_2;
|
||||
SELECT * FROM t_rename_new_new_3;
|
||||
SELECT * FROM t_rename_new_4;
|
||||
--error ER_NO_SUCH_TABLE
|
||||
SELECT * FROM t_delete;
|
||||
SHOW CREATE TABLE t_delete_2;
|
||||
SELECT * FROM t_rename_alter_2;
|
||||
SELECT * FROM t_rename_create;
|
||||
SELECT * FROM t_rename_create_new;
|
||||
SHOW CREATE TABLE t_part_create_2;
|
||||
SELECT * FROM t_part_create_2;
|
||||
SHOW CREATE TABLE t_part_add_part;
|
||||
SELECT * FROM t_part_add_part;
|
||||
SHOW CREATE TABLE t_part_change_eng;
|
||||
SELECT * FROM t_part_change_eng;
|
||||
SHOW CREATE TABLE t_part_change_eng_2;
|
||||
SELECT * FROM t_part_change_eng_2;
|
||||
SELECT * FROM t_part_alter;
|
||||
SHOW CREATE TABLE t_part_alter_2;
|
||||
SELECT * FROM t_part_alter_2;
|
||||
--error ER_NO_SUCH_TABLE
|
||||
SELECT * FROM t_part_drop;
|
||||
--error ER_NO_SUCH_TABLE
|
||||
SELECT * FROM t_part_rename;
|
||||
SELECT * FROM t_part_rename_2;
|
||||
--error ER_NO_SUCH_TABLE
|
||||
SELECT * FROM t_part_rename_3;
|
||||
SELECT * FROM test_for_rename.t_part_rename_4;
|
||||
SHOW CREATE TABLE t_part_rm_part;
|
||||
SELECT * FROM t_part_rm_part;
|
||||
--sorted_result
|
||||
SHOW DATABASES;
|
||||
|
||||
--echo ### Clean up for DDL test
|
||||
DROP DATABASE test_for_db_create;
|
||||
DROP TABLE t_db_create;
|
||||
DROP TABLE t_change_engine;
|
||||
DROP TABLE t_alter;
|
||||
DROP TABLE t_trunc;
|
||||
DROP TABLE t_ch_i;
|
||||
DROP TABLE t_rename_new;
|
||||
DROP TABLE t_rename_new_new_3;
|
||||
DROP TABLE t_rename_new_4;
|
||||
DROP TABLE t_delete_2;
|
||||
DROP TABLE t_rename_alter_2;
|
||||
DROP TABLE t_rename_create;
|
||||
DROP TABLE t_rename_create_new;
|
||||
DROP TABLE t_part_create;
|
||||
DROP TABLE t_part_create_2;
|
||||
DROP TABLE t_part_add_part;
|
||||
DROP TABLE t_part_change_eng;
|
||||
DROP TABLE t_part_change_eng_2;
|
||||
DROP TABLE t_part_change_eng_3;
|
||||
DROP TABLE t_part_alter;
|
||||
DROP TABLE t_part_alter_2;
|
||||
DROP TABLE t_part_rename_2;
|
||||
DROP TABLE t_part_rm_part;
|
||||
DROP DATABASE test_for_rename;
|
||||
--let after_aria_table_copy_test_for_db_drop_t=
|
||||
--let after_aria_table_copy_test_t_db_create=
|
||||
--let after_aria_table_copy_test_t_alter=
|
||||
--let after_aria_background=
|
||||
--let after_aria_table_copy_test_t_trunc=
|
||||
--let after_aria_table_copy_test_t_ch_i=
|
||||
--let after_aria_table_copy_test_t_rename=
|
||||
--let after_aria_table_copy_test_t_rename_2=
|
||||
--let after_aria_table_copy_test_t_rename_3=
|
||||
--let after_aria_table_copy_test_t_rename_4=
|
||||
--let after_aria_table_copy_test_t_delete=
|
||||
--let after_aria_table_copy_test_t_delete_2=
|
||||
--let after_aria_table_copy_test_t_rename_alter=
|
||||
--let after_aria_table_copy_test_t_rename_create=
|
||||
--let after_aria_table_copy_test_t_part_create=
|
||||
--let after_aria_table_copy_test_t_part_add_part=
|
||||
--let after_aria_table_copy_test_t_part_change_eng=
|
||||
--let after_aria_table_copy_test_t_part_change_eng_3=
|
||||
--let after_aria_table_copy_test_t_part_alter=
|
||||
--let after_aria_table_copy_test_t_part_alter_2=
|
||||
--let after_aria_table_copy_test_t_part_drop=
|
||||
--let after_aria_table_copy_test_t_part_rename=
|
||||
--let after_aria_table_copy_test_t_part_rename_3=
|
||||
--let after_aria_table_copy_test_t_part_rm_part=
|
||||
|
||||
--echo ### Result for DML test
|
||||
SELECT * FROM t_dml_ins;
|
||||
SELECT * FROM t_dml_upd;
|
||||
SELECT * FROM t_dml_del;
|
||||
|
||||
--echo ### Clean up for DML test
|
||||
DROP TABLE t_dml_ins;
|
||||
DROP TABLE t_dml_upd;
|
||||
DROP TABLE t_dml_del;
|
||||
--let after_aria_table_copy_test_t_dml_ins=
|
||||
--let after_aria_table_copy_test_t_dml_upd=
|
||||
--let after_aria_table_copy_test_t_dml_del=
|
||||
|
||||
--echo ### Result for redo log files backup
|
||||
--let $t_logs_1_records_count_after_backup=`SELECT COUNT(*) FROM t_logs_1`
|
||||
--let $t_logs_2_records_count_after_backup=`SELECT COUNT(*) FROM t_logs_2`
|
||||
--let $t_bulk_ins_records_count_after_backup=`SELECT COUNT(*) FROM t_bulk_ins`
|
||||
if ($t_logs_1_records_count_after_backup == $t_logs_1_records_count_before_backup) {
|
||||
--echo # ok
|
||||
}
|
||||
if ($t_logs_1_records_count_after_backup != $t_logs_1_records_count_before_backup) {
|
||||
--echo # failed
|
||||
}
|
||||
if ($t_logs_2_records_count_after_backup == $t_logs_2_records_count_before_backup) {
|
||||
--echo # ok
|
||||
}
|
||||
if ($t_logs_2_records_count_after_backup != $t_logs_2_records_count_before_backup) {
|
||||
--echo # failed
|
||||
}
|
||||
if ($t_bulk_ins_records_count_after_backup == $t_bulk_ins_records_count_before_backup) {
|
||||
--echo # ok
|
||||
}
|
||||
if ($t_bulk_ins_records_count_after_backup != $t_bulk_ins_records_count_before_backup) {
|
||||
--echo # failed
|
||||
}
|
||||
|
||||
--echo ### Cleanup for redo log files backup
|
||||
DROP TABLE t_logs_1;
|
||||
DROP TABLE t_logs_2;
|
||||
DROP TABLE t_bulk_ins;
|
||||
--let $t_logs_1_records_count_before_backup=
|
||||
--let $t_logs_1_records_count_after_backup=
|
||||
--let $t_logs_2_records_count_before_backup=
|
||||
--let $t_logs_2_records_count_after_backup=
|
||||
--let $t_bulk_ins_records_count_before_backup=
|
||||
--let $t_bulk_ins_records_count_after_backup=
|
||||
|
||||
--echo ### Result for online/offline tables test
|
||||
SELECT * FROM t_default;
|
||||
SELECT * FROM t_tr_p_ch;
|
||||
SELECT * FROM t_tr_p_nch;
|
||||
SELECT * FROM t_p_ch;
|
||||
SELECT * FROM t_p_nch;
|
||||
SELECT * FROM t_fixed;
|
||||
SELECT * FROM t_dyn;
|
||||
SELECT * FROM t_part_online;
|
||||
SELECT * FROM t_part_offline;
|
||||
SELECT * FROM `t 1 t-1`;
|
||||
SELECT * FROM `t-part online`;
|
||||
|
||||
--echo ### Cleanup for online/offline tables test
|
||||
DROP TABLE t_default;
|
||||
DROP TABLE t_tr_p_ch;
|
||||
DROP TABLE t_tr_p_nch;
|
||||
DROP TABLE t_p_ch;
|
||||
DROP TABLE t_p_nch;
|
||||
DROP TABLE t_fixed;
|
||||
DROP TABLE t_dyn;
|
||||
DROP TABLE t_part_online;
|
||||
DROP TABLE t_part_offline;
|
||||
DROP TABLE `t 1 t-1`;
|
||||
DROP TABLE `t-part online`;
|
||||
|
||||
if ($backup_variant == $backup_stream) {
|
||||
--remove_file $streamfile
|
||||
}
|
||||
--rmdir $targetdir
|
||||
--dec $backup_variant
|
||||
}
|
||||
|
1
mysql-test/suite/mariabackup/aria_log.opt
Normal file
1
mysql-test/suite/mariabackup/aria_log.opt
Normal file
@ -0,0 +1 @@
|
||||
--loose-aria-log-file-size=8388608
|
@ -35,7 +35,6 @@ DROP TABLE t1;
|
||||
SET @@global.aria_checkpoint_interval=DEFAULT /*Force checkpoint*/;
|
||||
SHOW ENGINE aria logs;
|
||||
Type Name Status
|
||||
Aria aria_log.00000001 free
|
||||
Aria aria_log.00000002 in use
|
||||
# Restarting mariadbd with default parameters
|
||||
# restart
|
||||
|
@ -48,7 +48,6 @@ SET @@global.aria_checkpoint_interval=DEFAULT /*Force checkpoint*/;
|
||||
--replace_regex /Size +[0-9]+ ; .+aria_log/aria_log/
|
||||
SHOW ENGINE aria logs;
|
||||
|
||||
|
||||
--echo # mariadb-backup --backup
|
||||
--disable_result_log
|
||||
--mkdir $targetdir
|
||||
@ -61,7 +60,6 @@ SHOW ENGINE aria logs;
|
||||
--exec $XTRABACKUP --prepare --target-dir=$targetdir
|
||||
--enable_result_log
|
||||
|
||||
|
||||
--echo # shutdown server
|
||||
--disable_result_log
|
||||
--source include/shutdown_mysqld.inc
|
||||
@ -70,12 +68,14 @@ SHOW ENGINE aria logs;
|
||||
--echo # remove aria-log-dir-path
|
||||
--rmdir $ARIA_LOGDIR_FS
|
||||
|
||||
|
||||
--echo # mariadb-backup --copy-back
|
||||
--let $mariadb_backup_parameters=--defaults-file=$MYSQLTEST_VARDIR/my.cnf --copy-back --datadir=$datadir --target-dir=$targetdir --parallel=2 --throttle=1 --aria-log-dir-path=$ARIA_LOGDIR_MARIADB
|
||||
--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
|
||||
--exec echo "# with parameters: $mariadb_backup_parameters"
|
||||
--exec $XTRABACKUP $mariadb_backup_parameters
|
||||
|
||||
|
||||
--echo # starting server
|
||||
--let $restart_parameters=$server_parameters
|
||||
--source include/start_mysqld.inc
|
||||
@ -91,7 +91,7 @@ DROP TABLE t1;
|
||||
--echo # Testing aria log files after --copy-back
|
||||
SET @@global.aria_checkpoint_interval=DEFAULT /*Force checkpoint*/;
|
||||
--file_exists $ARIA_LOGDIR_FS/aria_log_control
|
||||
--file_exists $ARIA_LOGDIR_FS/aria_log.00000001
|
||||
#--file_exists $ARIA_LOGDIR_FS/aria_log.00000001
|
||||
--file_exists $ARIA_LOGDIR_FS/aria_log.00000002
|
||||
--error 1
|
||||
--file_exists $ARIA_LOGDIR_FS/aria_log.00000003
|
||||
|
@ -35,7 +35,6 @@ DROP TABLE t1;
|
||||
SET @@global.aria_checkpoint_interval=DEFAULT /*Force checkpoint*/;
|
||||
SHOW ENGINE aria logs;
|
||||
Type Name Status
|
||||
Aria aria_log.00000001 free
|
||||
Aria aria_log.00000002 in use
|
||||
# Restarting mariadbd with default parameters
|
||||
# restart
|
||||
|
@ -0,0 +1,2 @@
|
||||
--loose-aria-log-file-size=8388608
|
||||
--loose-restart-for-aria_log_rotate_during_backup="This is needed to recreate datadir, to have Aria start logs from aria_log.00000001"
|
@ -0,0 +1,58 @@
|
||||
SHOW VARIABLES LIKE 'aria_log_file_size';
|
||||
Variable_name Value
|
||||
aria_log_file_size 8388608
|
||||
CREATE PROCEDURE display_aria_log_control(ctrl BLOB)
|
||||
BEGIN
|
||||
SELECT HEX(REVERSE(SUBSTRING(ctrl, 42, 4))) AS last_logno;
|
||||
END;
|
||||
$$
|
||||
CREATE PROCEDURE populate_t1()
|
||||
BEGIN
|
||||
FOR id IN 0..9 DO
|
||||
INSERT INTO test.t1 (id, txt) VALUES (id, REPEAT(id,1024*1024));
|
||||
END FOR;
|
||||
END;
|
||||
$$
|
||||
CREATE TABLE test.t1(id INT, txt LONGTEXT) ENGINE=Aria;
|
||||
# MYSQLD_DATADIR/aria_log_control before --backup
|
||||
CALL display_aria_log_control(@aria_log_control);
|
||||
last_logno
|
||||
00000001
|
||||
# Running --backup
|
||||
# MYSQLD_DATADIR/aria_log_control after --backup
|
||||
CALL display_aria_log_control(@aria_log_control);
|
||||
last_logno
|
||||
00000002
|
||||
# targetdir/aria_log_control after --backup
|
||||
CALL display_aria_log_control(@aria_log_control);
|
||||
last_logno
|
||||
00000001
|
||||
# Running --prepare
|
||||
# targetdir/aria_log_control after --prepare
|
||||
CALL display_aria_log_control(@aria_log_control);
|
||||
last_logno
|
||||
00000002
|
||||
# shutdown server
|
||||
# remove datadir
|
||||
# xtrabackup move back
|
||||
# restart
|
||||
# MYSQLD_DATADIR/aria_log_control after --copy-back
|
||||
CALL display_aria_log_control(@aria_log_control);
|
||||
last_logno
|
||||
00000002
|
||||
# Checking that after --restore all t1 data is there
|
||||
SELECT id, LENGTH(txt) FROM t1 ORDER BY id;
|
||||
id LENGTH(txt)
|
||||
0 1048576
|
||||
1 1048576
|
||||
2 1048576
|
||||
3 1048576
|
||||
4 1048576
|
||||
5 1048576
|
||||
6 1048576
|
||||
7 1048576
|
||||
8 1048576
|
||||
9 1048576
|
||||
DROP TABLE t1;
|
||||
DROP PROCEDURE populate_t1;
|
||||
DROP PROCEDURE display_aria_log_control;
|
@ -0,0 +1,82 @@
|
||||
--source include/have_debug.inc
|
||||
--source include/have_aria.inc
|
||||
|
||||
SHOW VARIABLES LIKE 'aria_log_file_size';
|
||||
|
||||
--let $MYSQLD_DATADIR= `select @@datadir`
|
||||
--let $targetdir=$MYSQLTEST_VARDIR/tmp/backup
|
||||
mkdir $targetdir;
|
||||
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PROCEDURE display_aria_log_control(ctrl BLOB)
|
||||
BEGIN
|
||||
SELECT HEX(REVERSE(SUBSTRING(ctrl, 42, 4))) AS last_logno;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PROCEDURE populate_t1()
|
||||
BEGIN
|
||||
FOR id IN 0..9 DO
|
||||
INSERT INTO test.t1 (id, txt) VALUES (id, REPEAT(id,1024*1024));
|
||||
END FOR;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
|
||||
CREATE TABLE test.t1(id INT, txt LONGTEXT) ENGINE=Aria;
|
||||
|
||||
--echo # MYSQLD_DATADIR/aria_log_control before --backup
|
||||
--let ARIA_DATADIR=$MYSQLD_DATADIR
|
||||
--source include/aria_log_control_load.inc
|
||||
CALL display_aria_log_control(@aria_log_control);
|
||||
|
||||
|
||||
--echo # Running --backup
|
||||
--let after_scanning_log_files=CALL test.populate_t1
|
||||
--disable_result_log
|
||||
--exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --parallel=10 --target-dir=$targetdir --dbug=+d,mariabackup_events 2>&1
|
||||
--let after_scanning_log_files=
|
||||
--enable_result_log
|
||||
|
||||
--echo # MYSQLD_DATADIR/aria_log_control after --backup
|
||||
--let ARIA_DATADIR=$MYSQLD_DATADIR
|
||||
--source include/aria_log_control_load.inc
|
||||
CALL display_aria_log_control(@aria_log_control);
|
||||
|
||||
--echo # targetdir/aria_log_control after --backup
|
||||
--let ARIA_DATADIR=$targetdir
|
||||
--source include/aria_log_control_load.inc
|
||||
CALL display_aria_log_control(@aria_log_control);
|
||||
|
||||
|
||||
--echo # Running --prepare
|
||||
--disable_result_log
|
||||
--exec $XTRABACKUP --prepare --target-dir=$targetdir
|
||||
--enable_result_log
|
||||
|
||||
--echo # targetdir/aria_log_control after --prepare
|
||||
--let ARIA_DATADIR=$targetdir
|
||||
--source include/aria_log_control_load.inc
|
||||
CALL display_aria_log_control(@aria_log_control);
|
||||
|
||||
|
||||
--disable_result_log
|
||||
--source include/restart_and_restore.inc
|
||||
--enable_result_log
|
||||
|
||||
--echo # MYSQLD_DATADIR/aria_log_control after --copy-back
|
||||
--let ARIA_DATADIR=$MYSQLD_DATADIR
|
||||
--source include/aria_log_control_load.inc
|
||||
CALL display_aria_log_control(@aria_log_control);
|
||||
|
||||
--echo # Checking that after --restore all t1 data is there
|
||||
SELECT id, LENGTH(txt) FROM t1 ORDER BY id;
|
||||
DROP TABLE t1;
|
||||
rmdir $targetdir;
|
||||
|
||||
DROP PROCEDURE populate_t1;
|
||||
DROP PROCEDURE display_aria_log_control;
|
@ -22,7 +22,7 @@ eval GRANT ALL PRIVILEGES ON *.* to '$USERNAME';
|
||||
|
||||
let $targetdir=$MYSQLTEST_VARDIR/tmp/backup;
|
||||
--disable_result_log
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf -u $USERNAME --backup --protocol=pipe --target-dir=$targetdir;
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf -u $USERNAME --backup --parallel=10 --protocol=pipe --target-dir=$targetdir;
|
||||
--enable_result_log
|
||||
--replace_result $USERNAME USERNAME
|
||||
eval DROP USER '$USERNAME';
|
||||
|
@ -6,8 +6,6 @@ GRANT RELOAD, PROCESS on *.* to backup@localhost;
|
||||
FOUND 1 /missing required privilege REPLICA MONITOR/ in backup.log
|
||||
GRANT REPLICA MONITOR ON *.* TO backup@localhost;
|
||||
REVOKE REPLICA MONITOR ON *.* FROM backup@localhost;
|
||||
FOUND 1 /missing required privilege CONNECTION ADMIN/ in backup.log
|
||||
GRANT CONNECTION ADMIN ON *.* TO backup@localhost;
|
||||
FOUND 1 /missing required privilege REPLICATION SLAVE ADMIN/ in backup.log
|
||||
FOUND 1 /missing required privilege REPLICA MONITOR/ in backup.log
|
||||
GRANT REPLICATION SLAVE ADMIN ON *.* TO backup@localhost;
|
||||
|
@ -3,14 +3,14 @@ CREATE user backup@localhost;
|
||||
|
||||
# backup possible for unprivileges user, with --no-lock
|
||||
--disable_result_log
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup -ubackup --no-lock --target-dir=$targetdir;
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --parallel=10 -ubackup --no-lock --target-dir=$targetdir;
|
||||
--enable_result_log
|
||||
rmdir $targetdir;
|
||||
|
||||
# backup fails without --no-lock, because of FTWRL
|
||||
--disable_result_log
|
||||
error 1;
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup -ubackup --target-dir=$targetdir > $MYSQLTEST_VARDIR/tmp/backup.log 2>&1;
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --parallel=10 -ubackup --target-dir=$targetdir > $MYSQLTEST_VARDIR/tmp/backup.log 2>&1;
|
||||
--enable_result_log
|
||||
|
||||
let SEARCH_FILE=$MYSQLTEST_VARDIR/tmp/backup.log;
|
||||
@ -23,7 +23,7 @@ let SEARCH_FILE=$MYSQLTEST_VARDIR/tmp/backup.log;
|
||||
# backup succeeds with RELOAD privilege
|
||||
GRANT RELOAD, PROCESS on *.* to backup@localhost;
|
||||
--disable_result_log
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup -ubackup --target-dir=$targetdir;
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --parallel=10 -ubackup --target-dir=$targetdir;
|
||||
--enable_result_log
|
||||
rmdir $targetdir;
|
||||
|
||||
@ -45,24 +45,6 @@ exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup -ubackup --sl
|
||||
rmdir $targetdir;
|
||||
REVOKE REPLICA MONITOR ON *.* FROM backup@localhost;
|
||||
|
||||
# TODO need a query that would delay a BACKUP STAGE START/ BACKUP STAGE BLOCK_COMMIT longer than the kill-long-queries-timeout
|
||||
#--send SELECT SLEEP(9) kill_me
|
||||
|
||||
# kill-long-query-type=(not empty) requires CONNECTION ADMIN
|
||||
--disable_result_log
|
||||
--exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup -ubackup --kill-long-query-type=ALL --kill-long-queries-timeout=4 --target-dir=$targetdir > $MYSQLTEST_VARDIR/tmp/backup.log 2>&1;
|
||||
--enable_result_log
|
||||
rmdir $targetdir;
|
||||
|
||||
--let SEARCH_PATTERN= missing required privilege CONNECTION ADMIN
|
||||
--source include/search_pattern_in_file.inc
|
||||
|
||||
GRANT CONNECTION ADMIN ON *.* TO backup@localhost;
|
||||
--disable_result_log
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup -ubackup --kill-long-query-type=all --kill-long-queries-timeout=1 --target-dir=$targetdir;
|
||||
--enable_result_log
|
||||
rmdir $targetdir;
|
||||
|
||||
# --safe-slave-backup requires REPLICATION SLAVE ADMIN, and REPLICA MONITOR
|
||||
--disable_result_log
|
||||
error 1;
|
||||
|
@ -3,7 +3,7 @@ FLUSH PRIVILEGES;
|
||||
echo # xtrabackup backup;
|
||||
let $targetdir=$MYSQLTEST_VARDIR/tmp/backup;
|
||||
--disable_result_log
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --user=backup_user --password=x --ssl --backup --target-dir=$targetdir;
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --user=backup_user --password=x --ssl --backup --parallel=10 --target-dir=$targetdir;
|
||||
--enable_result_log
|
||||
|
||||
echo # xtrabackup prepare;
|
||||
|
@ -9,7 +9,7 @@ INSERT INTO t VALUES(1);
|
||||
SHOW VARIABLES like 'log_bin';
|
||||
|
||||
--disable_result_log
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$basedir;
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --parallel=10 --target-dir=$basedir;
|
||||
--enable_result_log
|
||||
|
||||
exec $XTRABACKUP --prepare --binlog-info=1 --target-dir=$basedir ;
|
||||
|
@ -4,7 +4,7 @@ echo # xtrabackup backup;
|
||||
let $targetdir=$MYSQLTEST_VARDIR/tmp/backup;
|
||||
|
||||
--disable_result_log
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --compress --target-dir=$targetdir;
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --parallel=10 --compress --target-dir=$targetdir;
|
||||
--enable_result_log
|
||||
|
||||
INSERT INTO t VALUES(2);
|
||||
|
@ -7,7 +7,7 @@ mkdir $targetdir;
|
||||
|
||||
echo # xtrabackup backup;
|
||||
--disable_result_log
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir --dbug=+d,mariabackup_events;
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --parallel=10 --target-dir=$targetdir --dbug=+d,mariabackup_events;
|
||||
--enable_result_log
|
||||
|
||||
--let after_load_tables=
|
||||
|
@ -8,7 +8,7 @@ mkdir $table_data_dir;
|
||||
echo # xtrabackup backup;
|
||||
let $targetdir=$MYSQLTEST_VARDIR/tmp/backup;
|
||||
--disable_result_log
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir --dbug=+d,mariabackup_events;
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --parallel=10 --target-dir=$targetdir --dbug=+d,mariabackup_events;
|
||||
--enable_result_log
|
||||
--source include/shutdown_mysqld.inc
|
||||
echo # xtrabackup prepare;
|
||||
|
@ -7,7 +7,7 @@ INSERT INTO t VALUES(1);
|
||||
echo # xtrabackup backup;
|
||||
let $targetdir=$MYSQLTEST_VARDIR/tmp/backup;
|
||||
--disable_result_log
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir;
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --parallel=10 --target-dir=$targetdir;
|
||||
--enable_result_log
|
||||
--source include/shutdown_mysqld.inc
|
||||
echo # xtrabackup prepare;
|
||||
@ -21,6 +21,7 @@ rmdir $table_data_dir;
|
||||
SELECT * FROM t;
|
||||
DROP TABLE t;
|
||||
rmdir $targetdir;
|
||||
rmdir $table_data_dir;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-18200 MariaBackup full backup failed with InnoDB: Failing assertion: success
|
||||
@ -32,8 +33,8 @@ chmod 0000 $DATADIR/ibdata1;
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir;
|
||||
--enable_result_log
|
||||
chmod 0755 $DATADIR/ibdata1;
|
||||
rmdir $table_data_dir;
|
||||
rmdir $targetdir;
|
||||
|
||||
--echo #
|
||||
--echo # End of 10.4 tests
|
||||
--echo #
|
||||
|
67
mysql-test/suite/mariabackup/ddl_for_common_engine.result
Normal file
67
mysql-test/suite/mariabackup/ddl_for_common_engine.result
Normal file
@ -0,0 +1,67 @@
|
||||
CREATE TABLE t1 (a INT NOT NULL) ENGINE=CSV;
|
||||
CREATE TABLE t2 (a INT NOT NULL) ENGINE=CSV;
|
||||
CREATE TABLE t3 (a INT NOT NULL) ENGINE=CSV;
|
||||
### Backup to dir
|
||||
# xtrabackup prepare
|
||||
# shutdown server
|
||||
# remove datadir
|
||||
# xtrabackup move back
|
||||
# restart
|
||||
SELECT * FROM t4;
|
||||
a
|
||||
SELECT * FROM t2;
|
||||
ERROR 42S02: Table 'test.t2' doesn't exist
|
||||
SELECT * FROM t3;
|
||||
ERROR 42S02: Table 'test.t3' doesn't exist
|
||||
SELECT * FROM t5;
|
||||
a
|
||||
SELECT * FROM t1;
|
||||
a
|
||||
DROP TABLE t4, t5, t1;
|
||||
CREATE TABLE t1_m1 (a INT NOT NULL) ENGINE=MyISAM;
|
||||
CREATE TABLE t1_m2 (a INT NOT NULL) ENGINE=MyISAM;
|
||||
CREATE TABLE t1 (a INT NOT NULL) ENGINE=MERGE UNION=(t1_m1, t1_m2) INSERT_METHOD=LAST;
|
||||
CREATE TABLE t2_m1 (a INT NOT NULL) ENGINE=MyISAM;
|
||||
CREATE TABLE t2_m2 (a INT NOT NULL) ENGINE=MyISAM;
|
||||
CREATE TABLE t2 (a INT NOT NULL) ENGINE=MERGE UNION=(t2_m1, t2_m2) INSERT_METHOD=LAST;
|
||||
CREATE TABLE t3_m1 (a INT NOT NULL) ENGINE=MyISAM;
|
||||
CREATE TABLE t3_m2 (a INT NOT NULL) ENGINE=MyISAM;
|
||||
CREATE TABLE t3 (a INT NOT NULL) ENGINE=MERGE UNION=(t3_m1, t3_m2) INSERT_METHOD=LAST;
|
||||
### Backup to dir
|
||||
# xtrabackup prepare
|
||||
# shutdown server
|
||||
# remove datadir
|
||||
# xtrabackup move back
|
||||
# restart
|
||||
SELECT * FROM t4;
|
||||
a
|
||||
SELECT * FROM t2;
|
||||
ERROR 42S02: Table 'test.t2' doesn't exist
|
||||
SELECT * FROM t3;
|
||||
ERROR 42S02: Table 'test.t3' doesn't exist
|
||||
SELECT * FROM t5;
|
||||
a
|
||||
SELECT * FROM t1;
|
||||
a
|
||||
DROP TABLE t4, t5, t1;
|
||||
DROP TABLE t1_m1, t1_m2, t2_m1, t2_m2, t3_m1, t3_m2;
|
||||
CREATE TABLE t1 (a INT NOT NULL) ENGINE=MyISAM;
|
||||
CREATE TABLE t2 (a INT NOT NULL) ENGINE=MyISAM;
|
||||
CREATE TABLE t3 (a INT NOT NULL) ENGINE=MyISAM;
|
||||
### Backup to dir
|
||||
# xtrabackup prepare
|
||||
# shutdown server
|
||||
# remove datadir
|
||||
# xtrabackup move back
|
||||
# restart
|
||||
SELECT * FROM t4;
|
||||
a
|
||||
SELECT * FROM t2;
|
||||
ERROR 42S02: Table 'test.t2' doesn't exist
|
||||
SELECT * FROM t3;
|
||||
ERROR 42S02: Table 'test.t3' doesn't exist
|
||||
SELECT * FROM t5;
|
||||
a
|
||||
SELECT * FROM t1;
|
||||
a
|
||||
DROP TABLE t4, t5, t1;
|
79
mysql-test/suite/mariabackup/ddl_for_common_engine.test
Normal file
79
mysql-test/suite/mariabackup/ddl_for_common_engine.test
Normal file
@ -0,0 +1,79 @@
|
||||
# This test is just to ensure the DDL processing works for common engines like
|
||||
# MyISAM, ARCHIVE, CSV etc. The more complex test for different cases is
|
||||
# implemented in aria_backup.test.
|
||||
--source include/have_archive.inc
|
||||
--source include/have_csv.inc
|
||||
--source include/have_debug.inc
|
||||
|
||||
--let $targetdir=$MYSQLTEST_VARDIR/tmp/backup
|
||||
|
||||
--let $e_myisam = 1
|
||||
--let $e_merge = 2
|
||||
--let $e_csv = 3
|
||||
--let $e_archive = 4
|
||||
# 'rename' is not logged in $e_archive, return when fix
|
||||
--let $e_var = $e_csv
|
||||
|
||||
while ($e_var) {
|
||||
if ($e_var == $e_csv) {
|
||||
--let $engine = CSV
|
||||
}
|
||||
if ($e_var == $e_archive) {
|
||||
--let $engine = ARCHIVE
|
||||
}
|
||||
if ($e_var == $e_merge) {
|
||||
--let $engine = MERGE
|
||||
}
|
||||
if ($e_var == $e_myisam) {
|
||||
--let $engine = MyISAM
|
||||
}
|
||||
|
||||
if ($e_var == $e_merge) {
|
||||
CREATE TABLE t1_m1 (a INT NOT NULL) ENGINE=MyISAM;
|
||||
CREATE TABLE t1_m2 (a INT NOT NULL) ENGINE=MyISAM;
|
||||
CREATE TABLE t1 (a INT NOT NULL) ENGINE=MERGE UNION=(t1_m1, t1_m2) INSERT_METHOD=LAST;
|
||||
CREATE TABLE t2_m1 (a INT NOT NULL) ENGINE=MyISAM;
|
||||
CREATE TABLE t2_m2 (a INT NOT NULL) ENGINE=MyISAM;
|
||||
CREATE TABLE t2 (a INT NOT NULL) ENGINE=MERGE UNION=(t2_m1, t2_m2) INSERT_METHOD=LAST;
|
||||
CREATE TABLE t3_m1 (a INT NOT NULL) ENGINE=MyISAM;
|
||||
CREATE TABLE t3_m2 (a INT NOT NULL) ENGINE=MyISAM;
|
||||
CREATE TABLE t3 (a INT NOT NULL) ENGINE=MERGE UNION=(t3_m1, t3_m2) INSERT_METHOD=LAST;
|
||||
}
|
||||
if ($e_var != $e_merge) {
|
||||
eval CREATE TABLE t1 (a INT NOT NULL) ENGINE=$engine;
|
||||
eval CREATE TABLE t2 (a INT NOT NULL) ENGINE=$engine;
|
||||
eval CREATE TABLE t3 (a INT NOT NULL) ENGINE=$engine;
|
||||
}
|
||||
|
||||
--let after_ce_table_copy_test_t1=begin not atomic CREATE TABLE test.t4 LIKE test.t1; DROP TABLE test.t2; RENAME TABLE test.t3 TO test.t5; end
|
||||
|
||||
--mkdir $targetdir
|
||||
--echo ### Backup to dir
|
||||
--disable_result_log
|
||||
--exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --parallel=10 --target-dir=$targetdir --dbug=+d,mariabackup_events
|
||||
--enable_result_log
|
||||
|
||||
--echo # xtrabackup prepare
|
||||
--disable_result_log
|
||||
--exec $XTRABACKUP --prepare --target-dir=$targetdir
|
||||
--source include/restart_and_restore.inc
|
||||
--enable_result_log
|
||||
--rmdir $targetdir
|
||||
|
||||
SELECT * FROM t4;
|
||||
--error ER_NO_SUCH_TABLE
|
||||
SELECT * FROM t2;
|
||||
--error ER_NO_SUCH_TABLE
|
||||
SELECT * FROM t3;
|
||||
SELECT * FROM t5;
|
||||
SELECT * FROM t1;
|
||||
|
||||
DROP TABLE t4, t5, t1;
|
||||
|
||||
if ($e_var == $e_merge) {
|
||||
DROP TABLE t1_m1, t1_m2, t2_m1, t2_m2, t3_m1, t3_m2;
|
||||
}
|
||||
--let after_ce_table_copy_test_t1=
|
||||
--dec $e_var
|
||||
}
|
||||
|
@ -1 +1,3 @@
|
||||
log_page_corruption : MDEV-26210
|
||||
mariabackup.xb_compressed_encrypted : MDEV-26154 (error 194 "Tablespace is missing for a table")
|
||||
innodb_ddl_on_intermediate_table : MENT-1213
|
||||
|
@ -37,7 +37,7 @@ echo # xtrabackup backup;
|
||||
let $targetdir=$MYSQLTEST_VARDIR/tmp/backup;
|
||||
let $backuplog=$MYSQLTEST_VARDIR/tmp/backup.log;
|
||||
--error 1
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir --core-file > $backuplog;
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --parallel=10 --target-dir=$targetdir --core-file > $backuplog;
|
||||
--enable_result_log
|
||||
|
||||
--let SEARCH_PATTERN=Database page corruption detected.*
|
||||
|
@ -65,7 +65,7 @@ if (`select @@innodb_checksum_algorithm LIKE '%full_crc32'`)
|
||||
}
|
||||
--disable_result_log
|
||||
--error $expect_error
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --extended-validation --target-dir=$targetdir --core-file > $backuplog;
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --parallel=10 --extended-validation --target-dir=$targetdir --core-file > $backuplog;
|
||||
--enable_result_log
|
||||
|
||||
|
||||
@ -77,7 +77,7 @@ rmdir $targetdir;
|
||||
|
||||
# Due to very constructed nature of the "corruption" (faking checksums), the "corruption" won't be found without --extended-validation
|
||||
--disable_result_log
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir;
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --parallel=10 --target-dir=$targetdir;
|
||||
--enable_result_log
|
||||
|
||||
drop table t1;
|
||||
|
@ -2,7 +2,7 @@ let $targetdir=$MYSQLTEST_VARDIR/tmp/backup;
|
||||
let $extra_lsndir=$MYSQLTEST_VARDIR/tmp/extra_lsndir;
|
||||
mkdir $extra_lsndir;
|
||||
--disable_result_log
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir --extra-lsndir=$extra_lsndir;
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --parallel=10 --target-dir=$targetdir --extra-lsndir=$extra_lsndir;
|
||||
--enable_result_log
|
||||
list_files $extra_lsndir;
|
||||
rmdir $extra_lsndir;
|
||||
|
38
mysql-test/suite/mariabackup/full_backup.result.orig
Normal file
38
mysql-test/suite/mariabackup/full_backup.result.orig
Normal file
@ -0,0 +1,38 @@
|
||||
CREATE TABLE t(i INT) ENGINE INNODB;
|
||||
INSERT INTO t VALUES(1);
|
||||
# xtrabackup backup
|
||||
NOT FOUND /InnoDB: Allocated tablespace ID/ in backup.log
|
||||
INSERT INTO t VALUES(2);
|
||||
# xtrabackup prepare
|
||||
# shutdown server
|
||||
# remove datadir
|
||||
# xtrabackup move back
|
||||
# restart
|
||||
SELECT * FROM t;
|
||||
i
|
||||
1
|
||||
DROP TABLE t;
|
||||
#
|
||||
# MDEV-27121 mariabackup incompatible with disabled dedicated
|
||||
# undo log tablespaces
|
||||
#
|
||||
call mtr.add_suppression("InnoDB: innodb_undo_tablespaces=0 disables dedicated undo log tablespaces");
|
||||
call mtr.add_suppression("InnoDB: Cannot change innodb_undo_tablespaces=0 because previous shutdown was not with innodb_fast_shutdown=0");
|
||||
call mtr.add_suppression("Found 1 prepared XA transactions");
|
||||
CREATE TABLE t(f1 INT NOT NULL)ENGINE=InnoDB;
|
||||
XA START 'zombie';
|
||||
INSERT INTO t VALUES(1);
|
||||
XA END 'zombie';
|
||||
XA PREPARE 'zombie';
|
||||
# restart: --innodb_undo_tablespaces=0
|
||||
# xtrabackup backup
|
||||
# xtrabackup prepare
|
||||
# shutdown server
|
||||
# remove datadir
|
||||
# xtrabackup move back
|
||||
# restart: --innodb_undo_tablespaces=0
|
||||
# Display undo log files from target directory
|
||||
undo001
|
||||
undo002
|
||||
XA COMMIT 'zombie';
|
||||
DROP TABLE t;
|
10
mysql-test/suite/mariabackup/full_backup.result.rej
Normal file
10
mysql-test/suite/mariabackup/full_backup.result.rej
Normal file
@ -0,0 +1,10 @@
|
||||
--- mysql-test/suite/mariabackup/full_backup.result
|
||||
+++ mysql-test/suite/mariabackup/full_backup.result
|
||||
@@ -17,6 +17,7 @@ DROP TABLE t;
|
||||
# undo log tablespaces
|
||||
#
|
||||
call mtr.add_suppression("InnoDB: innodb_undo_tablespaces=0 disables dedicated undo log tablespaces");
|
||||
+call mtr.add_suppression("InnoDB: Cannot change innodb_undo_tablespaces=0 because previous shutdown was not with innodb_fast_shutdown=0");
|
||||
# restart: --innodb_undo_tablespaces=0
|
||||
# xtrabackup backup
|
||||
# xtrabackup prepare
|
@ -7,7 +7,7 @@ let $targetdir=$MYSQLTEST_VARDIR/tmp/backup;
|
||||
--let $backup_log=$MYSQLTEST_VARDIR/tmp/backup.log
|
||||
|
||||
--disable_result_log
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir > $backup_log 2>&1;
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir --parallel=10 > $backup_log 2>&1;
|
||||
--enable_result_log
|
||||
|
||||
# The following warning must not appear after MDEV-27343 fix
|
||||
|
65
mysql-test/suite/mariabackup/full_backup.test.orig
Normal file
65
mysql-test/suite/mariabackup/full_backup.test.orig
Normal file
@ -0,0 +1,65 @@
|
||||
--source include/innodb_page_size.inc
|
||||
|
||||
CREATE TABLE t(i INT) ENGINE INNODB;
|
||||
INSERT INTO t VALUES(1);
|
||||
echo # xtrabackup backup;
|
||||
let $targetdir=$MYSQLTEST_VARDIR/tmp/backup;
|
||||
--let $backup_log=$MYSQLTEST_VARDIR/tmp/backup.log
|
||||
|
||||
--disable_result_log
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir > $backup_log 2>&1;
|
||||
--enable_result_log
|
||||
|
||||
# The following warning must not appear after MDEV-27343 fix
|
||||
--let SEARCH_PATTERN=InnoDB: Allocated tablespace ID
|
||||
--let SEARCH_FILE=$backup_log
|
||||
--source include/search_pattern_in_file.inc
|
||||
--remove_file $backup_log
|
||||
|
||||
INSERT INTO t VALUES(2);
|
||||
|
||||
|
||||
echo # xtrabackup prepare;
|
||||
--disable_result_log
|
||||
exec $XTRABACKUP --prepare --target-dir=$targetdir;
|
||||
-- source include/restart_and_restore.inc
|
||||
--enable_result_log
|
||||
|
||||
SELECT * FROM t;
|
||||
DROP TABLE t;
|
||||
rmdir $targetdir;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-27121 mariabackup incompatible with disabled dedicated
|
||||
--echo # undo log tablespaces
|
||||
--echo #
|
||||
call mtr.add_suppression("InnoDB: innodb_undo_tablespaces=0 disables dedicated undo log tablespaces");
|
||||
call mtr.add_suppression("InnoDB: Cannot change innodb_undo_tablespaces=0 because previous shutdown was not with innodb_fast_shutdown=0");
|
||||
call mtr.add_suppression("Found 1 prepared XA transactions");
|
||||
|
||||
CREATE TABLE t(f1 INT NOT NULL)ENGINE=InnoDB;
|
||||
XA START 'zombie';
|
||||
INSERT INTO t VALUES(1);
|
||||
XA END 'zombie';
|
||||
XA PREPARE 'zombie';
|
||||
|
||||
let $restart_parameters=--innodb_undo_tablespaces=0;
|
||||
--source include/restart_mysqld.inc
|
||||
|
||||
echo # xtrabackup backup;
|
||||
--disable_result_log
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir;
|
||||
--enable_result_log
|
||||
|
||||
echo # xtrabackup prepare;
|
||||
--disable_result_log
|
||||
exec $XTRABACKUP --prepare --target-dir=$targetdir;
|
||||
-- source include/restart_and_restore.inc
|
||||
--enable_result_log
|
||||
|
||||
--echo # Display undo log files from target directory
|
||||
list_files $targetdir undo*;
|
||||
|
||||
XA COMMIT 'zombie';
|
||||
DROP TABLE t;
|
||||
rmdir $targetdir;
|
10
mysql-test/suite/mariabackup/full_backup.test.rej
Normal file
10
mysql-test/suite/mariabackup/full_backup.test.rej
Normal file
@ -0,0 +1,10 @@
|
||||
--- mysql-test/suite/mariabackup/full_backup.test
|
||||
+++ mysql-test/suite/mariabackup/full_backup.test
|
||||
@@ -34,6 +34,7 @@ rmdir $targetdir;
|
||||
--echo # undo log tablespaces
|
||||
--echo #
|
||||
call mtr.add_suppression("InnoDB: innodb_undo_tablespaces=0 disables dedicated undo log tablespaces");
|
||||
+call mtr.add_suppression("InnoDB: Cannot change innodb_undo_tablespaces=0 because previous shutdown was not with innodb_fast_shutdown=0");
|
||||
|
||||
let $restart_parameters=--innodb_undo_tablespaces=0;
|
||||
--source include/restart_mysqld.inc
|
@ -79,7 +79,7 @@ INSERT INTO t VALUES(1);
|
||||
echo # xtrabackup backup;
|
||||
let $targetdir=$MYSQLTEST_VARDIR/tmp/backup;
|
||||
--disable_result_log
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir;
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --parallel=10 --target-dir=$targetdir;
|
||||
--enable_result_log
|
||||
SET GLOBAL innodb_flush_log_at_trx_commit=1;
|
||||
INSERT INTO t VALUES(2);
|
||||
|
114
mysql-test/suite/mariabackup/huge_lsn.test.orig
Normal file
114
mysql-test/suite/mariabackup/huge_lsn.test.orig
Normal file
@ -0,0 +1,114 @@
|
||||
--source include/not_embedded.inc
|
||||
--source include/have_file_key_management.inc
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-13416 mariabackup fails with EFAULT "Bad Address"
|
||||
--echo #
|
||||
|
||||
let INNODB_PAGE_SIZE=`select @@innodb_page_size`;
|
||||
let MYSQLD_DATADIR=`select @@datadir`;
|
||||
|
||||
let $targetdir_old=$MYSQLTEST_VARDIR/tmp/backup_1;
|
||||
--disable_result_log
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir_old;
|
||||
--enable_result_log
|
||||
--source include/shutdown_mysqld.inc
|
||||
|
||||
if ($MTR_COMBINATION_STRICT_CRC32) {
|
||||
perl;
|
||||
my $file= "$ENV{MYSQLD_DATADIR}/ibdata1";
|
||||
open(FILE, "+<", $file) or die "Unable to open $file\n";
|
||||
binmode FILE;
|
||||
my $ps= $ENV{INNODB_PAGE_SIZE};
|
||||
my $page;
|
||||
die "Unable to read $file" unless sysread(FILE, $page, $ps) == $ps;
|
||||
substr($page,26,8) = pack("NN", 4096, ~1024);
|
||||
sysseek(FILE, 0, 0) || die "Unable to rewind $file\n";
|
||||
syswrite(FILE, $page, $ps)==$ps || die "Unable to write $file\n";
|
||||
close(FILE) || die "Unable to close $file\n";
|
||||
|
||||
$file= "$ENV{MYSQLD_DATADIR}/ib_logfile0";
|
||||
open(FILE, ">", $file) || die "Unable to truncate $file\n";
|
||||
close(FILE) || "Unable to close $file\n";
|
||||
EOF
|
||||
--let SEARCH_PATTERN= redo log: [0-9.]*[KMGT]iB; LSN=17596481010687\\b
|
||||
}
|
||||
|
||||
if (!$MTR_COMBINATION_STRICT_CRC32) {
|
||||
perl;
|
||||
do "$ENV{MTR_SUITE_DIR}/../innodb/include/crc32.pl";
|
||||
my $file= "$ENV{MYSQLD_DATADIR}/ib_logfile0";
|
||||
open(FILE, ">", $file) or die "Unable to open $file\n";
|
||||
binmode FILE;
|
||||
my $extra_repeat = 139820;
|
||||
# The desired log sequence number is 17596481011216 (0x1000fffffe10).
|
||||
my $file_size=4<<20;
|
||||
my $lsn_hi=4096,$lsn_lo=0xfffffe00 - $extra_repeat * 15;
|
||||
my $polynomial = 0x82f63b78; # CRC-32C
|
||||
my ($header, $checkpoint, $log);
|
||||
$header = "Phys" . pack("x[4]NN", $lsn_hi, $lsn_lo - $file_size + 0x300f) .
|
||||
"some Perl code" . pack("x[478]");
|
||||
$header .= pack("Nx[3584]", mycrc32($header, 0, $polynomial));
|
||||
$checkpoint = pack("NNNNx[44]", $lsn_hi, $lsn_lo, $lsn_hi, $lsn_lo);
|
||||
$checkpoint .= pack("Nx[8128]", mycrc32($checkpoint, 0, $polynomial));
|
||||
$log = pack("CxxNN", 0xfa, $lsn_hi, $lsn_lo);
|
||||
$log .= pack("CN", 0, mycrc32($log, 0, $polynomial));
|
||||
|
||||
# Write more than 2MiB of FILE_MODIFY mini-transactions to exercise the parser.
|
||||
my $extra = pack("CCxa*", 0xb9, 127, "a/b.ibd");
|
||||
$extra .= pack("CN", 0, mycrc32($extra, 0, $polynomial));
|
||||
|
||||
print FILE $header, $checkpoint, $extra x ($extra_repeat - 1), $log;
|
||||
seek(FILE, $file_size - 15, 0);
|
||||
$extra = pack("CCxa*", 0xb9, 127, "c/d.ibd");
|
||||
$extra .= pack("CN", 1, mycrc32($extra, 0, $polynomial));
|
||||
print FILE $extra;
|
||||
close(FILE) or die "Unable to close $file\n";
|
||||
EOF
|
||||
--let SEARCH_PATTERN= InnoDB: log sequence number 17596481011216
|
||||
--let $restart_parameters=--innodb-log-file-size=4M --innodb-encrypt-log=0
|
||||
}
|
||||
|
||||
--source include/start_mysqld.inc
|
||||
let SEARCH_FILE= $MYSQLTEST_VARDIR/log/mysqld.1.err;
|
||||
--source include/search_pattern_in_file.inc
|
||||
|
||||
CREATE TABLE t(i INT) ENGINE=INNODB ENCRYPTED=YES;
|
||||
INSERT INTO t VALUES(1);
|
||||
|
||||
echo # xtrabackup backup;
|
||||
let $targetdir=$MYSQLTEST_VARDIR/tmp/backup;
|
||||
--disable_result_log
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir;
|
||||
--enable_result_log
|
||||
SET GLOBAL innodb_flush_log_at_trx_commit=1;
|
||||
INSERT INTO t VALUES(2);
|
||||
echo # xtrabackup prepare;
|
||||
--disable_result_log
|
||||
exec $XTRABACKUP --prepare --target-dir=$targetdir;
|
||||
--let $restart_parameters=
|
||||
--source include/restart_and_restore.inc
|
||||
--enable_result_log
|
||||
SELECT * FROM t;
|
||||
FLUSH TABLE t FOR EXPORT;
|
||||
copy_file $_datadir/test/t.ibd $_datadir/test/t_copy.ibd;
|
||||
copy_file $_datadir/test/t.cfg $_datadir/test/t_copy.cfg;
|
||||
UNLOCK TABLES;
|
||||
ALTER TABLE t DISCARD TABLESPACE;
|
||||
move_file $_datadir/test/t_copy.ibd $_datadir/test/t.ibd;
|
||||
move_file $_datadir/test/t_copy.cfg $_datadir/test/t.cfg;
|
||||
ALTER TABLE t IMPORT TABLESPACE;
|
||||
FLUSH TABLE t FOR EXPORT;
|
||||
copy_file $_datadir/test/t.ibd $_datadir/test/t_copy.ibd;
|
||||
copy_file $_datadir/test/t.cfg $_datadir/test/t_copy.cfg;
|
||||
UNLOCK TABLES;
|
||||
ALTER TABLE t DISCARD TABLESPACE;
|
||||
move_file $_datadir/test/t_copy.ibd $_datadir/test/t.ibd;
|
||||
move_file $_datadir/test/t_copy.cfg $_datadir/test/t.cfg;
|
||||
ALTER TABLE t IMPORT TABLESPACE;
|
||||
DROP TABLE t;
|
||||
rmdir $targetdir;
|
||||
let $targetdir= $targetdir_old;
|
||||
exec $XTRABACKUP --prepare --target-dir=$targetdir;
|
||||
--source include/restart_and_restore.inc
|
||||
rmdir $targetdir_old;
|
@ -18,7 +18,7 @@ INSERT INTO t VALUES(1);
|
||||
|
||||
echo # Create full backup , modify table, then create incremental/differential backup;
|
||||
--disable_result_log
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$basedir;
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --parallel=10 --target-dir=$basedir;
|
||||
--enable_result_log
|
||||
|
||||
SET GLOBAL innodb_flush_log_at_trx_commit = 1;
|
||||
@ -26,7 +26,7 @@ INSERT INTO t VALUES(2);
|
||||
SELECT * FROM t;
|
||||
|
||||
--disable_result_log
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$incremental_dir --incremental-basedir=$basedir;
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --parallel=10 --target-dir=$incremental_dir --incremental-basedir=$basedir;
|
||||
echo # Prepare full backup, apply incremental one;
|
||||
exec $XTRABACKUP --prepare --target-dir=$basedir;
|
||||
exec $XTRABACKUP --prepare --target-dir=$basedir --incremental-dir=$incremental_dir;
|
||||
|
@ -0,0 +1,5 @@
|
||||
CREATE TABLE IF NOT EXISTS t1 ( col1 INT, col_text TEXT ) ENGINE = InnoDB;
|
||||
ALTER TABLE t1 ADD FULLTEXT KEY `ftidx1` ( col_text );
|
||||
# xtrabackup backup
|
||||
SET debug_sync='RESET';
|
||||
DROP TABLE t1;
|
@ -0,0 +1,18 @@
|
||||
--source include/have_debug.inc
|
||||
--source include/have_innodb.inc
|
||||
--source include/have_debug_sync.inc
|
||||
|
||||
--let $targetdir=$MYSQLTEST_VARDIR/tmp/backup
|
||||
--mkdir $targetdir
|
||||
|
||||
CREATE TABLE IF NOT EXISTS t1 ( col1 INT, col_text TEXT ) ENGINE = InnoDB;
|
||||
ALTER TABLE t1 ADD FULLTEXT KEY `ftidx1` ( col_text );
|
||||
|
||||
echo # xtrabackup backup;
|
||||
--disable_result_log
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --parallel=10 --target-dir=$targetdir --dbug=+d,mariabackup_events,emulate_ddl_on_intermediate_table;
|
||||
--enable_result_log
|
||||
|
||||
SET debug_sync='RESET';
|
||||
rmdir $targetdir;
|
||||
DROP TABLE t1;
|
@ -16,7 +16,7 @@ CREATE TABLE `bobby``tables` (id INT, name VARCHAR(50), purchased DATE) ENGINE I
|
||||
set global innodb_log_checkpoint_now = 1;
|
||||
|
||||
--disable_result_log
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir --lock-ddl-per-table=1 --dbug=+d,check_mdl_lock_works;
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --parallel=10 --target-dir=$targetdir --lock-ddl-per-table=1 --dbug=+d,check_mdl_lock_works;
|
||||
--enable_result_log
|
||||
DROP TABLE t;
|
||||
DROP TABLE `bobby``tables`;
|
||||
|
@ -7,7 +7,7 @@ let $targetdir=$MYSQLTEST_VARDIR/tmp/backup;
|
||||
let $backuplog=$MYSQLTEST_VARDIR/tmp/backup.log;
|
||||
|
||||
--disable_result_log
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir --dbug=+d,log_intermittent_checksum_mismatch --core-file > $backuplog;
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --parallel=10 --target-dir=$targetdir --dbug=+d,log_intermittent_checksum_mismatch --core-file > $backuplog;
|
||||
--enable_result_log
|
||||
|
||||
--let SEARCH_RANGE = 10000000
|
||||
|
@ -0,0 +1,20 @@
|
||||
#
|
||||
# Start of 10.5 tests
|
||||
#
|
||||
#
|
||||
# MENT-1587 mariabackup failing due to aria log file copy
|
||||
#
|
||||
CREATE TABLE t1(i INT PRIMARY KEY) ENGINE=ARIA;
|
||||
INSERT INTO t1 VALUES (10);
|
||||
# Prepare full backup
|
||||
# shutdown server
|
||||
# remove datadir
|
||||
# xtrabackup move back
|
||||
# restart
|
||||
SELECT * FROM t1;
|
||||
i
|
||||
10
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# End of 10.5 tests
|
||||
#
|
@ -0,0 +1,47 @@
|
||||
--let $MYSQLD_DATADIR=`select @@datadir`
|
||||
|
||||
--echo #
|
||||
--echo # Start of 10.5 tests
|
||||
--echo #
|
||||
|
||||
--echo #
|
||||
--echo # MENT-1587 mariabackup failing due to aria log file copy
|
||||
--echo #
|
||||
|
||||
|
||||
--let $basedir=$MYSQLTEST_VARDIR/tmp/backup
|
||||
--let $incremental_dir=$MYSQLTEST_VARDIR/tmp/backup_inc1
|
||||
|
||||
CREATE TABLE t1(i INT PRIMARY KEY) ENGINE=ARIA;
|
||||
INSERT INTO t1 VALUES (10);
|
||||
|
||||
#
|
||||
# Add a log file with a number outside of last_log_number
|
||||
# specified in aria_log_control.
|
||||
# The actual file number written in the header is 4.
|
||||
# Let's rename it to 100 for test purposes.
|
||||
# Hopefully 100 should be enough.
|
||||
#
|
||||
--copy_file suite/mariabackup/std_data/ment1587_aria_log.00000004 $MYSQLD_DATADIR/aria_log.00000100
|
||||
|
||||
--disable_result_log
|
||||
--exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$basedir
|
||||
--enable_result_log
|
||||
|
||||
--disable_result_log
|
||||
--echo # Prepare full backup
|
||||
--exec $XTRABACKUP --prepare --target-dir=$basedir
|
||||
--enable_result_log
|
||||
|
||||
--let $targetdir=$basedir
|
||||
--source include/restart_and_restore.inc
|
||||
--enable_result_log
|
||||
--rmdir $basedir
|
||||
|
||||
SELECT * FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # End of 10.5 tests
|
||||
--echo #
|
24
mysql-test/suite/mariabackup/log_tables.result
Normal file
24
mysql-test/suite/mariabackup/log_tables.result
Normal file
@ -0,0 +1,24 @@
|
||||
CREATE TABLE t(i INT)
|
||||
ENGINE ARIA TRANSACTIONAL=1 ROW_FORMAT=PAGE PAGE_CHECKSUM=1;
|
||||
SET GLOBAL general_log = 1;
|
||||
SET GLOBAL log_output = 'TABLE';
|
||||
INSERT INTO t VALUES (1);
|
||||
SELECT * FROM mysql.general_log
|
||||
WHERE argument LIKE "INSERT INTO %" AND
|
||||
(command_type = "Query" OR command_type = "Execute") ;
|
||||
event_time user_host thread_id server_id command_type argument
|
||||
TIMESTAMP USER_HOST THREAD_ID 1 Query INSERT INTO t VALUES (1)
|
||||
# Insert new row into general_log table after it has been copied on BLOCK_DDL.
|
||||
# Backup to dir.
|
||||
# Xtrabackup prepare.
|
||||
# shutdown server
|
||||
# remove datadir
|
||||
# xtrabackup move back
|
||||
# restart
|
||||
SELECT * FROM mysql.general_log
|
||||
WHERE argument LIKE "INSERT INTO %" AND
|
||||
(command_type = "Query" OR command_type = "Execute") ;
|
||||
event_time user_host thread_id server_id command_type argument
|
||||
TIMESTAMP USER_HOST THREAD_ID 1 Query INSERT INTO t VALUES (1)
|
||||
TIMESTAMP USER_HOST THREAD_ID 1 Query INSERT INTO test.t VALUES (2)
|
||||
DROP TABLE t;
|
49
mysql-test/suite/mariabackup/log_tables.test
Normal file
49
mysql-test/suite/mariabackup/log_tables.test
Normal file
@ -0,0 +1,49 @@
|
||||
# Test for copying log tables tail
|
||||
--source include/have_aria.inc
|
||||
--source include/have_debug.inc
|
||||
|
||||
--let $targetdir=$MYSQLTEST_VARDIR/tmp/backup
|
||||
|
||||
CREATE TABLE t(i INT)
|
||||
ENGINE ARIA TRANSACTIONAL=1 ROW_FORMAT=PAGE PAGE_CHECKSUM=1;
|
||||
|
||||
--let $general_log_old = `SELECT @@global.general_log`
|
||||
--let $log_output_old = `SELECT @@global.log_output`
|
||||
|
||||
SET GLOBAL general_log = 1;
|
||||
SET GLOBAL log_output = 'TABLE';
|
||||
|
||||
INSERT INTO t VALUES (1);
|
||||
|
||||
--replace_column 1 TIMESTAMP 2 USER_HOST 3 THREAD_ID 5 Query
|
||||
--sorted_result
|
||||
SELECT * FROM mysql.general_log
|
||||
WHERE argument LIKE "INSERT INTO %" AND
|
||||
(command_type = "Query" OR command_type = "Execute") ;
|
||||
|
||||
--echo # Insert new row into general_log table after it has been copied on BLOCK_DDL.
|
||||
--let after_stage_block_ddl=INSERT INTO test.t VALUES (2)
|
||||
|
||||
--echo # Backup to dir.
|
||||
--disable_result_log
|
||||
--exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --parallel=10 --target-dir=$targetdir --dbug=+d,mariabackup_events
|
||||
--enable_result_log
|
||||
|
||||
--echo # Xtrabackup prepare.
|
||||
--disable_result_log
|
||||
--exec $XTRABACKUP --prepare --target-dir=$targetdir
|
||||
--source include/restart_and_restore.inc
|
||||
--enable_result_log
|
||||
|
||||
--replace_column 1 TIMESTAMP 2 USER_HOST 3 THREAD_ID 5 Query
|
||||
--sorted_result
|
||||
SELECT * FROM mysql.general_log
|
||||
WHERE argument LIKE "INSERT INTO %" AND
|
||||
(command_type = "Query" OR command_type = "Execute") ;
|
||||
|
||||
--rmdir $targetdir
|
||||
DROP TABLE t;
|
||||
--disable_query_log
|
||||
--eval SET GLOBAL general_log = $general_log_old
|
||||
--eval SET GLOBAL log_output = $log_output_old
|
||||
--enable_query_log
|
@ -11,7 +11,7 @@ CREATE TABLE t(a varchar(40) PRIMARY KEY, b varchar(40), c varchar(40), d varcha
|
||||
|
||||
echo # Create full backup , modify table, then create incremental/differential backup;
|
||||
--disable_result_log
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$basedir;
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --parallel=10 --target-dir=$basedir;
|
||||
--enable_result_log
|
||||
|
||||
SET debug_dbug='+d,skip_page_checksum',foreign_key_checks=0,unique_checks=0;
|
||||
|
@ -24,7 +24,7 @@ call mtr.add_suppression('InnoDB: Ignoring tablespace for test/t1 because it cou
|
||||
echo # xtrabackup backup;
|
||||
let $targetdir=$MYSQLTEST_VARDIR/tmp/backup;
|
||||
--disable_result_log
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir;
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --parallel=10 --target-dir=$targetdir;
|
||||
--enable_result_log
|
||||
|
||||
rmdir $targetdir;
|
||||
|
@ -9,6 +9,6 @@ CREATE TABLE t1(i int) ENGINE=INNODB;
|
||||
echo # xtrabackup backup;
|
||||
--disable_result_log
|
||||
error 1;
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir --no-lock --dbug=+d,mariabackup_events;
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --parallel=10 --target-dir=$targetdir --no-lock --dbug=+d,mariabackup_events;
|
||||
--enable_result_log
|
||||
rmdir $targetdir;
|
||||
|
@ -14,7 +14,7 @@ echo # xtrabackup backup;
|
||||
|
||||
let targetdir=$MYSQLTEST_VARDIR/tmp/backup;
|
||||
--disable_result_log
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup "--tables=test.*1" --target-dir=$targetdir;
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --parallel=10 "--tables=test.*1" --target-dir=$targetdir;
|
||||
--enable_result_log
|
||||
list_files $targetdir/test *.ibd;
|
||||
list_files $targetdir/test *.new;
|
||||
|
@ -28,7 +28,7 @@ echo # xtrabackup backup;
|
||||
|
||||
let $targetdir=$MYSQLTEST_VARDIR/tmp/backup;
|
||||
--disable_result_log
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup "--tables-exclude=test.*2" "--databases-exclude=db2" --target-dir=$targetdir;
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --parallel=10 "--tables-exclude=test.*2" "--databases-exclude=db2" --target-dir=$targetdir;
|
||||
--enable_result_log
|
||||
|
||||
COMMIT;
|
||||
|
@ -14,7 +14,7 @@ PARTITION BY RANGE (i)
|
||||
PARTITION p3 VALUES LESS THAN (400) DATA DIRECTORY = '$MYSQLTEST_VARDIR/partitdata',
|
||||
PARTITION p4 VALUES LESS THAN MAXVALUE);
|
||||
INSERT INTO t VALUES (1), (101), (201), (301), (401);
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir;
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --parallel=10 --target-dir=$targetdir;
|
||||
exec $XTRABACKUP --prepare --target-dir=$targetdir;
|
||||
DROP TABLE t;
|
||||
rmdir $MYSQLTEST_VARDIR/partitdata;
|
||||
|
@ -16,7 +16,7 @@ echo # xtrabackup backup;
|
||||
|
||||
let $targetdir=$MYSQLTEST_VARDIR/tmp/backup;
|
||||
--disable_result_log
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup "--tables=test.t1" --target-dir=$targetdir;
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --parallel=10 "--tables=test.t1" --target-dir=$targetdir;
|
||||
--enable_result_log
|
||||
INSERT INTO t1 VALUES (1), (101), (201), (301);
|
||||
|
||||
|
@ -3,7 +3,7 @@ let $targetdir=$MYSQLTEST_VARDIR/tmp/backup;
|
||||
mkdir $targetdir;
|
||||
CREATE TABLE t1(i int) ENGINE INNODB;
|
||||
set global innodb_log_checkpoint_now = 1;
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir --lock-ddl-per-table --dbug=+d,rename_during_mdl_lock_table;
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --parallel=10 --target-dir=$targetdir --lock-ddl-per-table --dbug=+d,rename_during_mdl_lock_table;
|
||||
|
||||
echo # xtrabackup prepare;
|
||||
--disable_result_log
|
||||
|
13
mysql-test/suite/mariabackup/skip_innodb.test.orig
Normal file
13
mysql-test/suite/mariabackup/skip_innodb.test.orig
Normal file
@ -0,0 +1,13 @@
|
||||
--source include/innodb_undo_tablespaces.inc
|
||||
let $targetdir=$MYSQLTEST_VARDIR/tmp/backup;
|
||||
CREATE TABLE t(i int);
|
||||
INSERT INTO t VALUES(1);
|
||||
--disable_result_log
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir;
|
||||
exec $XTRABACKUP --prepare --target-dir=$targetdir;
|
||||
-- source include/restart_and_restore.inc
|
||||
--enable_result_log
|
||||
SELECT * from t;
|
||||
DROP TABLE t;
|
||||
|
||||
rmdir $targetdir;
|
17
mysql-test/suite/mariabackup/skip_innodb.test.rej
Normal file
17
mysql-test/suite/mariabackup/skip_innodb.test.rej
Normal file
@ -0,0 +1,17 @@
|
||||
--- mysql-test/suite/mariabackup/skip_innodb.test
|
||||
+++ mysql-test/suite/mariabackup/skip_innodb.test
|
||||
@@ -1,12 +1,13 @@
|
||||
+--source include/innodb_undo_tablespaces.inc
|
||||
let $targetdir=$MYSQLTEST_VARDIR/tmp/backup;
|
||||
CREATE TABLE t(i int);
|
||||
INSERT INTO t VALUES(1);
|
||||
--disable_result_log
|
||||
-exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir;
|
||||
+exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --parallel=10 --target-dir=$targetdir;
|
||||
exec $XTRABACKUP --prepare --target-dir=$targetdir;
|
||||
-- source include/restart_and_restore.inc
|
||||
--enable_result_log
|
||||
SELECT * from t;
|
||||
DROP TABLE t;
|
||||
|
||||
-rmdir $targetdir;+rmdir $targetdir;
|
@ -13,7 +13,7 @@ echo #backup;
|
||||
|
||||
let $targetdir=$MYSQLTEST_VARDIR/tmp/backup;
|
||||
--disable_result_log
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir;
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --parallel=10 --target-dir=$targetdir;
|
||||
--enable_result_log
|
||||
remove_file $_datadir/test/small.ibd;
|
||||
rmdir $targetdir;
|
||||
|
@ -5,7 +5,7 @@ update t set a=2;
|
||||
let $targetdir=$MYSQLTEST_VARDIR/tmp/backup;
|
||||
|
||||
--disable_result_log
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir;
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --parallel=10 --target-dir=$targetdir;
|
||||
--enable_result_log
|
||||
|
||||
insert into t values (3);
|
||||
@ -32,7 +32,7 @@ insert into t values (1);
|
||||
update t set a=2;
|
||||
|
||||
--disable_result_log
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir;
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --parallel=10 --target-dir=$targetdir;
|
||||
--enable_result_log
|
||||
|
||||
insert into t values (3);
|
||||
|
@ -7,7 +7,7 @@ CREATE TABLE t1 ENGINE=InnoDB SELECT 1;
|
||||
--let after_load_tablespaces=TRUNCATE test.t1
|
||||
|
||||
--disable_result_log
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir --dbug=+d,mariabackup_events;
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --parallel=10 --target-dir=$targetdir --dbug=+d,mariabackup_events;
|
||||
--enable_result_log
|
||||
|
||||
--let after_load_tablespaces=
|
||||
|
@ -11,7 +11,7 @@ INSERT INTO t1 VALUES(1);
|
||||
|
||||
--echo # xtrabackup backup
|
||||
--disable_result_log
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$basedir;
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --parallel=10 --target-dir=$basedir;
|
||||
--enable_result_log
|
||||
--echo # Display undo log files from target directory
|
||||
list_files $basedir undo*;
|
||||
|
19
mysql-test/suite/mariabackup/undo_upgrade.result.orig
Normal file
19
mysql-test/suite/mariabackup/undo_upgrade.result.orig
Normal file
@ -0,0 +1,19 @@
|
||||
set global innodb_fast_shutdown=0;
|
||||
# restart: --innodb_undo_tablespaces=2
|
||||
CREATE TABLE t1(a varchar(60)) ENGINE INNODB;
|
||||
start transaction;
|
||||
INSERT INTO t1 VALUES(1);
|
||||
# xtrabackup backup
|
||||
# Restart the server with 4 undo tablespaces
|
||||
set global innodb_fast_shutdown=0;
|
||||
# restart: --innodb_undo_tablespaces=4
|
||||
# incremental backup should fail
|
||||
FOUND 1 /--incremental backup is impossible if the server had been restarted with different innodb_undo_tablespaces/ in backup.log
|
||||
# Take full backup again
|
||||
# Prepare full backup
|
||||
# Display 4 undo log files from target directory
|
||||
undo001
|
||||
undo002
|
||||
undo003
|
||||
undo004
|
||||
DROP TABLE t1;
|
22
mysql-test/suite/mariabackup/undo_upgrade.result.rej
Normal file
22
mysql-test/suite/mariabackup/undo_upgrade.result.rej
Normal file
@ -0,0 +1,22 @@
|
||||
--- mysql-test/suite/mariabackup/undo_upgrade.result
|
||||
+++ mysql-test/suite/mariabackup/undo_upgrade.result
|
||||
@@ -0,0 +1,19 @@
|
||||
+set global innodb_fast_shutdown=0;
|
||||
+# restart: --innodb_undo_tablespaces=2
|
||||
+CREATE TABLE t1(a varchar(60)) ENGINE INNODB;
|
||||
+start transaction;
|
||||
+INSERT INTO t1 VALUES(1);
|
||||
+# xtrabackup backup
|
||||
+# Restart the server with 4 undo tablespaces
|
||||
+set global innodb_fast_shutdown=0;
|
||||
+# restart: --innodb_undo_tablespaces=4
|
||||
+# incremental backup should fail
|
||||
+FOUND 1 /--incremental backup is impossible if the server had been restarted with different innodb_undo_tablespaces./ in backup.log
|
||||
+# Take full backup again
|
||||
+# Prepare full backup
|
||||
+# Display 4 undo log files from target directory
|
||||
+undo001
|
||||
+undo002
|
||||
+undo003
|
||||
+undo004
|
||||
+DROP TABLE t1;
|
50
mysql-test/suite/mariabackup/undo_upgrade.test.orig
Normal file
50
mysql-test/suite/mariabackup/undo_upgrade.test.orig
Normal file
@ -0,0 +1,50 @@
|
||||
--source include/have_innodb.inc
|
||||
--source include/innodb_page_size.inc
|
||||
|
||||
let basedir=$MYSQLTEST_VARDIR/tmp/backup;
|
||||
let incremental_dir=$MYSQLTEST_VARDIR/tmp/backup_inc1;
|
||||
|
||||
set global innodb_fast_shutdown=0;
|
||||
let $restart_parameters=--innodb_undo_tablespaces=2;
|
||||
--source include/restart_mysqld.inc
|
||||
|
||||
CREATE TABLE t1(a varchar(60)) ENGINE INNODB;
|
||||
start transaction;
|
||||
INSERT INTO t1 VALUES(1);
|
||||
|
||||
--echo # xtrabackup backup
|
||||
--disable_result_log
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$basedir;
|
||||
--enable_result_log
|
||||
|
||||
--echo # Restart the server with 4 undo tablespaces
|
||||
let $restart_parameters=--innodb_undo_tablespaces=4;
|
||||
set global innodb_fast_shutdown=0;
|
||||
--source include/restart_mysqld.inc
|
||||
|
||||
let $backuplog=$MYSQLTEST_VARDIR/tmp/backup.log;
|
||||
--echo # incremental backup should fail
|
||||
--error 1
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$incremental_dir --incremental-basedir=$basedir 2> $backuplog;
|
||||
|
||||
--let SEARCH_PATTERN=--incremental backup is impossible if the server had been restarted with different innodb_undo_tablespaces
|
||||
--let SEARCH_FILE=$backuplog
|
||||
--source include/search_pattern_in_file.inc
|
||||
remove_file $backuplog;
|
||||
rmdir $incremental_dir;
|
||||
rmdir $basedir;
|
||||
|
||||
--echo # Take full backup again
|
||||
--disable_result_log
|
||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$basedir;
|
||||
--enable_result_log
|
||||
--disable_result_log
|
||||
|
||||
echo # Prepare full backup;
|
||||
exec $XTRABACKUP --prepare --target-dir=$basedir;
|
||||
|
||||
--echo # Display 4 undo log files from target directory
|
||||
list_files $basedir undo*;
|
||||
|
||||
DROP TABLE t1;
|
||||
rmdir $basedir;
|
53
mysql-test/suite/mariabackup/undo_upgrade.test.rej
Normal file
53
mysql-test/suite/mariabackup/undo_upgrade.test.rej
Normal file
@ -0,0 +1,53 @@
|
||||
--- mysql-test/suite/mariabackup/undo_upgrade.test
|
||||
+++ mysql-test/suite/mariabackup/undo_upgrade.test
|
||||
@@ -0,0 +1,50 @@
|
||||
+--source include/have_innodb.inc
|
||||
+--source include/innodb_page_size.inc
|
||||
+
|
||||
+let basedir=$MYSQLTEST_VARDIR/tmp/backup;
|
||||
+let incremental_dir=$MYSQLTEST_VARDIR/tmp/backup_inc1;
|
||||
+
|
||||
+set global innodb_fast_shutdown=0;
|
||||
+let $restart_parameters=--innodb_undo_tablespaces=2;
|
||||
+--source include/restart_mysqld.inc
|
||||
+
|
||||
+CREATE TABLE t1(a varchar(60)) ENGINE INNODB;
|
||||
+start transaction;
|
||||
+INSERT INTO t1 VALUES(1);
|
||||
+
|
||||
+--echo # xtrabackup backup
|
||||
+--disable_result_log
|
||||
+exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$basedir;
|
||||
+--enable_result_log
|
||||
+
|
||||
+--echo # Restart the server with 4 undo tablespaces
|
||||
+let $restart_parameters=--innodb_undo_tablespaces=4;
|
||||
+set global innodb_fast_shutdown=0;
|
||||
+--source include/restart_mysqld.inc
|
||||
+
|
||||
+let $backuplog=$MYSQLTEST_VARDIR/tmp/backup.log;
|
||||
+--echo # incremental backup should fail
|
||||
+--error 1
|
||||
+exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$incremental_dir --incremental-basedir=$basedir 2> $backuplog;
|
||||
+
|
||||
+--let SEARCH_PATTERN=--incremental backup is impossible if the server had been restarted with different innodb_undo_tablespaces.
|
||||
+--let SEARCH_FILE=$backuplog
|
||||
+--source include/search_pattern_in_file.inc
|
||||
+remove_file $backuplog;
|
||||
+rmdir $incremental_dir;
|
||||
+rmdir $basedir;
|
||||
+
|
||||
+--echo # Take full backup again
|
||||
+--disable_result_log
|
||||
+exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$basedir;
|
||||
+--enable_result_log
|
||||
+--disable_result_log
|
||||
+
|
||||
+echo # Prepare full backup;
|
||||
+exec $XTRABACKUP --prepare --target-dir=$basedir;
|
||||
+
|
||||
+--echo # Display 4 undo log files from target directory
|
||||
+list_files $basedir undo*;
|
||||
+
|
||||
+DROP TABLE t1;
|
||||
+rmdir $basedir;
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user