Commit d471469b authored by Vladislav Vaintroub's avatar Vladislav Vaintroub

MDEV-13466 Implement --export option for MariaDB Backup

full server recovery is performed .
We start "mysqld" with  --bootstrap
and pass bootstrap script consisting of several FLUSH TABLES FOR export/
UNLOCK TABLES
parent d26fb96a
...@@ -139,6 +139,7 @@ char xtrabackup_real_incremental_basedir[FN_REFLEN]; ...@@ -139,6 +139,7 @@ char xtrabackup_real_incremental_basedir[FN_REFLEN];
char xtrabackup_real_extra_lsndir[FN_REFLEN]; char xtrabackup_real_extra_lsndir[FN_REFLEN];
char xtrabackup_real_incremental_dir[FN_REFLEN]; char xtrabackup_real_incremental_dir[FN_REFLEN];
char *xtrabackup_tmpdir; char *xtrabackup_tmpdir;
char *xtrabackup_tables; char *xtrabackup_tables;
...@@ -332,6 +333,9 @@ const char *opt_history = NULL; ...@@ -332,6 +333,9 @@ const char *opt_history = NULL;
my_bool opt_ssl_verify_server_cert = FALSE; my_bool opt_ssl_verify_server_cert = FALSE;
#endif #endif
char mariabackup_exe[FN_REFLEN];
char orig_argv1[FN_REFLEN];
/* Whether xtrabackup_binlog_info should be created on recovery */ /* Whether xtrabackup_binlog_info should be created on recovery */
static bool recover_binlog_info; static bool recover_binlog_info;
...@@ -348,6 +352,11 @@ xtrabackup_add_datasink(ds_ctxt_t *ds) ...@@ -348,6 +352,11 @@ xtrabackup_add_datasink(ds_ctxt_t *ds)
datasinks[actual_datasinks] = ds; actual_datasinks++; datasinks[actual_datasinks] = ds; actual_datasinks++;
} }
typedef void (*process_single_tablespace_func_t)(const char *dirname, const char *filname, bool is_remote);
static dberr_t enumerate_ibd_files(process_single_tablespace_func_t callback);
/* ======== Datafiles iterator ======== */ /* ======== Datafiles iterator ======== */
struct datafiles_iter_t { struct datafiles_iter_t {
fil_system_t *system; fil_system_t *system;
...@@ -1123,6 +1132,109 @@ debug_sync_point(const char *name) ...@@ -1123,6 +1132,109 @@ debug_sync_point(const char *name)
#endif #endif
} }
static std::vector<std::string> tables_for_export;
static void append_export_table(const char *dbname, const char *tablename, bool is_remote)
{
if(dbname && tablename && !is_remote)
{
char buf[3*FN_REFLEN];
char db_utf8[FN_REFLEN];
char table_utf8[FN_REFLEN];
snprintf(buf,sizeof(buf),"%s/%s",dbname, tablename);
// trim .ibd
char *p=strrchr(buf, '.');
if (p) *p=0;
dict_fs2utf8(buf, db_utf8, sizeof(db_utf8),table_utf8,sizeof(table_utf8));
snprintf(buf,sizeof(buf),"`%s`.`%s`",db_utf8,table_utf8);
tables_for_export.push_back(buf);
}
}
#define BOOTSTRAP_FILENAME "mariabackup_prepare_for_export.sql"
static int create_bootstrap_file()
{
FILE *f= fopen(BOOTSTRAP_FILENAME,"wb");
if(!f)
return -1;
fputs("SET NAMES UTF8;\n",f);
enumerate_ibd_files(append_export_table);
for (size_t i= 0; i < tables_for_export.size(); i++)
{
const char *tab = tables_for_export[i].c_str();
fprintf(f,
"BEGIN NOT ATOMIC "
"DECLARE CONTINUE HANDLER FOR NOT FOUND,SQLEXCEPTION BEGIN END;"
"FLUSH TABLES %s FOR EXPORT;"
"END;\n"
"UNLOCK TABLES;\n",
tab);
}
fclose(f);
return 0;
}
static int prepare_export()
{
int err= -1;
char cmdline[2*FN_REFLEN];
FILE *outf;
if (create_bootstrap_file())
return -1;
// Process defaults-file , it can have some --lc-language stuff,
// which is* unfortunately* still necessary to get mysqld up
if (strncmp(orig_argv1,"--defaults-file=",16) == 0)
{
sprintf(cmdline,
IF_WIN("\"","") "\"%s\" --mysqld \"%s\" --defaults-group-suffix=%s"
" --defaults-extra-file=./backup-my.cnf --datadir=."
" --innodb --innodb-fast-shutdown=0"
" --innodb_purge_rseg_truncate_frequency=1 --innodb-buffer-pool-size=%llu"
" --console --log-error= --bootstrap < " BOOTSTRAP_FILENAME IF_WIN("\"",""),
mariabackup_exe,
orig_argv1, (my_defaults_group_suffix?my_defaults_group_suffix:""),
xtrabackup_use_memory);
}
else
{
sprintf(cmdline,
IF_WIN("\"","") "\"%s\" --mysqld"
" --defaults-file=./backup-my.cnf --datadir=."
" --innodb --innodb-fast-shutdown=0"
" --innodb_purge_rseg_truncate_frequency=1 --innodb-buffer-pool-size=%llu"
" --console --log-error= --bootstrap < " BOOTSTRAP_FILENAME IF_WIN("\"",""),
mariabackup_exe,
xtrabackup_use_memory);
}
msg("Prepare export : executing %s\n", cmdline);
fflush(stderr);
outf= popen(cmdline,"r");
if (!outf)
goto end;
char outline[FN_REFLEN];
while(fgets(outline, sizeof(outline)-1, outf))
fprintf(stderr,"%s",outline);
err = pclose(outf);
end:
unlink(BOOTSTRAP_FILENAME);
return err;
}
static const char *xb_client_default_groups[]= static const char *xb_client_default_groups[]=
{ "xtrabackup", "client", 0, 0, 0 }; { "xtrabackup", "client", 0, 0, 0 };
...@@ -2520,6 +2632,7 @@ xb_new_datafile(const char *name, bool is_remote) ...@@ -2520,6 +2632,7 @@ xb_new_datafile(const char *name, bool is_remote)
} }
} }
static static
void void
xb_load_single_table_tablespace( xb_load_single_table_tablespace(
...@@ -2581,7 +2694,7 @@ xb_load_single_table_tablespace( ...@@ -2581,7 +2694,7 @@ xb_load_single_table_tablespace(
ut_a(space != NULL); ut_a(space != NULL);
if (!fil_node_create(file->filepath(), n_pages, space, if (!fil_node_create(file->filepath(), ulint(n_pages), space,
false, false)) { false, false)) {
ut_error; ut_error;
} }
...@@ -2610,9 +2723,8 @@ xb_load_single_table_tablespace( ...@@ -2610,9 +2723,8 @@ xb_load_single_table_tablespace(
/** Scan the database directories under the MySQL datadir, looking for /** Scan the database directories under the MySQL datadir, looking for
.ibd files and determining the space id in each of them. .ibd files and determining the space id in each of them.
@return DB_SUCCESS or error number */ @return DB_SUCCESS or error number */
static
dberr_t static dberr_t enumerate_ibd_files(process_single_tablespace_func_t callback)
xb_load_single_table_tablespaces()
{ {
int ret; int ret;
char* dbpath = NULL; char* dbpath = NULL;
...@@ -2650,8 +2762,7 @@ xb_load_single_table_tablespaces() ...@@ -2650,8 +2762,7 @@ xb_load_single_table_tablespaces()
&& !strcmp(dbinfo.name + len - 4, ".ibd"); && !strcmp(dbinfo.name + len - 4, ".ibd");
if (is_isl || is_ibd) { if (is_isl || is_ibd) {
xb_load_single_table_tablespace( (*callback)(NULL, dbinfo.name, is_isl);
NULL, dbinfo.name, is_isl);
} }
} }
...@@ -2710,9 +2821,7 @@ xb_load_single_table_tablespaces() ...@@ -2710,9 +2821,7 @@ xb_load_single_table_tablespaces()
if (len > 4 if (len > 4
&& !strcmp(fileinfo.name + len - 4, && !strcmp(fileinfo.name + len - 4,
".ibd")) { ".ibd")) {
xb_load_single_table_tablespace( (*callback)(dbinfo.name, fileinfo.name, false);
dbinfo.name, fileinfo.name,
false);
} }
} }
...@@ -2807,7 +2916,7 @@ xb_load_tablespaces() ...@@ -2807,7 +2916,7 @@ xb_load_tablespaces()
msg("xtrabackup: Generating a list of tablespaces\n"); msg("xtrabackup: Generating a list of tablespaces\n");
err = xb_load_single_table_tablespaces(); err = enumerate_ibd_files(xb_load_single_table_tablespace);
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {
return(err); return(err);
} }
...@@ -3232,7 +3341,7 @@ open_or_create_log_file( ...@@ -3232,7 +3341,7 @@ open_or_create_log_file(
ut_a(fil_validate()); ut_a(fil_validate());
ut_a(fil_node_create(name, srv_log_file_size >> srv_page_size_shift, ut_a(fil_node_create(name, ulint(srv_log_file_size >> srv_page_size_shift),
space, false, false)); space, false, false));
return(DB_SUCCESS); return(DB_SUCCESS);
...@@ -4505,349 +4614,6 @@ xtrabackup_apply_deltas() ...@@ -4505,349 +4614,6 @@ xtrabackup_apply_deltas()
xtrabackup_apply_delta); xtrabackup_apply_delta);
} }
/*********************************************************************//**
Write the meta data (index user fields) config file.
@return true in case of success otherwise false. */
static
bool
xb_export_cfg_write_index_fields(
/*===========================*/
const dict_index_t* index, /*!< in: write the meta data for
this index */
FILE* file) /*!< in: file to write to */
{
byte row[sizeof(ib_uint32_t) * 2];
for (ulint i = 0; i < index->n_fields; ++i) {
byte* ptr = row;
const dict_field_t* field = &index->fields[i];
mach_write_to_4(ptr, field->prefix_len);
ptr += sizeof(ib_uint32_t);
mach_write_to_4(ptr, field->fixed_len);
if (fwrite(row, 1, sizeof(row), file) != sizeof(row)) {
msg("xtrabackup: Error: writing index fields.");
return(false);
}
/* Include the NUL byte in the length. */
ib_uint32_t len = (ib_uint32_t)strlen(field->name) + 1;
ut_a(len > 1);
mach_write_to_4(row, len);
if (fwrite(row, 1, sizeof(len), file) != sizeof(len)
|| fwrite(field->name, 1, len, file) != len) {
msg("xtrabackup: Error: writing index column.");
return(false);
}
}
return(true);
}
/*********************************************************************//**
Write the meta data config file index information.
@return true in case of success otherwise false. */
static __attribute__((nonnull, warn_unused_result))
bool
xb_export_cfg_write_indexes(
/*======================*/
const dict_table_t* table, /*!< in: write the meta data for
this table */
FILE* file) /*!< in: file to write to */
{
{
byte row[sizeof(ib_uint32_t)];
/* Write the number of indexes in the table. */
mach_write_to_4(row, UT_LIST_GET_LEN(table->indexes));
if (fwrite(row, 1, sizeof(row), file) != sizeof(row)) {
msg("xtrabackup: Error: writing index count.");
return(false);
}
}
bool ret = true;
/* Write the index meta data. */
for (const dict_index_t* index = UT_LIST_GET_FIRST(table->indexes);
index != 0 && ret;
index = UT_LIST_GET_NEXT(indexes, index)) {
byte* ptr;
byte row[sizeof(ib_uint64_t)
+ sizeof(ib_uint32_t) * 8];
ptr = row;
ut_ad(sizeof(ib_uint64_t) == 8);
mach_write_to_8(ptr, index->id);
ptr += sizeof(ib_uint64_t);
mach_write_to_4(ptr, index->space);
ptr += sizeof(ib_uint32_t);
mach_write_to_4(ptr, index->page);
ptr += sizeof(ib_uint32_t);
mach_write_to_4(ptr, index->type);
ptr += sizeof(ib_uint32_t);
mach_write_to_4(ptr, index->trx_id_offset);
ptr += sizeof(ib_uint32_t);
mach_write_to_4(ptr, index->n_user_defined_cols);
ptr += sizeof(ib_uint32_t);
mach_write_to_4(ptr, index->n_uniq);
ptr += sizeof(ib_uint32_t);
mach_write_to_4(ptr, index->n_nullable);
ptr += sizeof(ib_uint32_t);
mach_write_to_4(ptr, index->n_fields);
if (fwrite(row, 1, sizeof(row), file) != sizeof(row)) {
msg("xtrabackup: Error: writing index meta-data.");
return(false);
}
/* Write the length of the index name.
NUL byte is included in the length. */
ib_uint32_t len = (ib_uint32_t)strlen(index->name) + 1;
ut_a(len > 1);
mach_write_to_4(row, len);
if (fwrite(row, 1, sizeof(len), file) != sizeof(len)
|| fwrite(index->name, 1, len, file) != len) {
msg("xtrabackup: Error: writing index name.");
return(false);
}
ret = xb_export_cfg_write_index_fields(index, file);
}
return(ret);
}
/*********************************************************************//**
Write the meta data (table columns) config file. Serialise the contents of
dict_col_t structure, along with the column name. All fields are serialized
as ib_uint32_t.
@return true in case of success otherwise false. */
static __attribute__((nonnull, warn_unused_result))
bool
xb_export_cfg_write_table(
/*====================*/
const dict_table_t* table, /*!< in: write the meta data for
this table */
FILE* file) /*!< in: file to write to */
{
dict_col_t* col;
byte row[sizeof(ib_uint32_t) * 7];
col = table->cols;
for (ulint i = 0; i < table->n_cols; ++i, ++col) {
byte* ptr = row;
mach_write_to_4(ptr, col->prtype);
ptr += sizeof(ib_uint32_t);
mach_write_to_4(ptr, col->mtype);
ptr += sizeof(ib_uint32_t);
mach_write_to_4(ptr, col->len);
ptr += sizeof(ib_uint32_t);
mach_write_to_4(ptr, col->mbminmaxlen);
ptr += sizeof(ib_uint32_t);
mach_write_to_4(ptr, col->ind);
ptr += sizeof(ib_uint32_t);
mach_write_to_4(ptr, col->ord_part);
ptr += sizeof(ib_uint32_t);
mach_write_to_4(ptr, col->max_prefix);
if (fwrite(row, 1, sizeof(row), file) != sizeof(row)) {
msg("xtrabackup: Error: writing table column data.");
return(false);
}
/* Write out the column name as [len, byte array]. The len
includes the NUL byte. */
ib_uint32_t len;
const char* col_name;
col_name = dict_table_get_col_name(table, dict_col_get_no(col));
/* Include the NUL byte in the length. */
len = (ib_uint32_t)strlen(col_name) + 1;
ut_a(len > 1);
mach_write_to_4(row, len);
if (fwrite(row, 1, sizeof(len), file) != sizeof(len)
|| fwrite(col_name, 1, len, file) != len) {
msg("xtrabackup: Error: writing column name.");
return(false);
}
}
return(true);
}
/*********************************************************************//**
Write the meta data config file header.
@return true in case of success otherwise false. */
static __attribute__((nonnull, warn_unused_result))
bool
xb_export_cfg_write_header(
/*=====================*/
const dict_table_t* table, /*!< in: write the meta data for
this table */
FILE* file) /*!< in: file to write to */
{
byte value[sizeof(ib_uint32_t)];
/* Write the meta-data version number. */
mach_write_to_4(value, IB_EXPORT_CFG_VERSION_V1);
if (fwrite(&value, 1, sizeof(value), file) != sizeof(value)) {
msg("xtrabackup: Error: writing meta-data version number.");
return(false);
}
/* Write the server hostname. */
ib_uint32_t len;
const char* hostname = "Hostname unknown";
/* The server hostname includes the NUL byte. */
len = (ib_uint32_t)strlen(hostname) + 1;
mach_write_to_4(value, len);
if (fwrite(&value, 1, sizeof(value), file) != sizeof(value)
|| fwrite(hostname, 1, len, file) != len) {
msg("xtrabackup: Error: writing hostname.");
return(false);
}
/* The table name includes the NUL byte. */
const char* table_name = table->name.m_name;
ut_a(table_name != 0);
len = (ib_uint32_t)strlen(table_name) + 1;
/* Write the table name. */
mach_write_to_4(value, len);
if (fwrite(&value, 1, sizeof(value), file) != sizeof(value)
|| fwrite(table_name, 1, len, file) != len) {
msg("xtrabackup: Error: writing table name.");
return(false);
}
byte row[sizeof(ib_uint32_t) * 3];
/* Write the next autoinc value. */
mach_write_to_8(row, table->autoinc);
if (fwrite(row, 1, sizeof(ib_uint64_t), file) != sizeof(ib_uint64_t)) {
msg("xtrabackup: Error: writing table autoinc value.");
return(false);
}
byte* ptr = row;
/* Write the system page size. */
mach_write_to_4(ptr, UNIV_PAGE_SIZE);
ptr += sizeof(ib_uint32_t);
/* Write the table->flags. */
mach_write_to_4(ptr, table->flags);
ptr += sizeof(ib_uint32_t);
/* Write the number of columns in the table. */
mach_write_to_4(ptr, table->n_cols);
if (fwrite(row, 1, sizeof(row), file) != sizeof(row)) {
msg("xtrabackup: Error: writing table meta-data.");
return(false);
}
return(true);
}
/*********************************************************************//**
Write MySQL 5.6-style meta data config file.
@return true in case of success otherwise false. */
static
bool
xb_export_cfg_write(
const fil_node_t* node,
const dict_table_t* table) /*!< in: write the meta data for
this table */
{
char file_path[FN_REFLEN];
FILE* file;
bool success;
strcpy(file_path, node->name);
strcpy(file_path + strlen(file_path) - 4, ".cfg");
file = fopen(file_path, "w+b");
if (file == NULL) {
msg("xtrabackup: Error: cannot open %s\n", node->name);
success = false;
} else {
success = xb_export_cfg_write_header(table, file);
if (success) {
success = xb_export_cfg_write_table(table, file);
}
if (success) {
success = xb_export_cfg_write_indexes(table, file);
}
if (fclose(file) != 0) {
msg("xtrabackup: Error: cannot close %s\n", node->name);
success = false;
}
}
return(success);
}
static static
void void
...@@ -4884,7 +4650,6 @@ store_binlog_info(const char* filename, const char* name, ulonglong pos) ...@@ -4884,7 +4650,6 @@ store_binlog_info(const char* filename, const char* name, ulonglong pos)
static bool static bool
xtrabackup_prepare_func(char** argv) xtrabackup_prepare_func(char** argv)
{ {
datafiles_iter_t *it;
char metadata_path[FN_REFLEN]; char metadata_path[FN_REFLEN];
/* cd to target-dir */ /* cd to target-dir */
...@@ -4903,6 +4668,8 @@ xtrabackup_prepare_func(char** argv) ...@@ -4903,6 +4668,8 @@ xtrabackup_prepare_func(char** argv)
xtrabackup_target_dir= mysql_data_home_buff; xtrabackup_target_dir= mysql_data_home_buff;
xtrabackup_target_dir[0]=FN_CURLIB; // all paths are relative from here xtrabackup_target_dir[0]=FN_CURLIB; // all paths are relative from here
xtrabackup_target_dir[1]=0; xtrabackup_target_dir[1]=0;
const lsn_t target_lsn = xtrabackup_incremental
? incremental_to_lsn : metadata_to_lsn;
/* /*
read metadata of target read metadata of target
...@@ -4953,9 +4720,7 @@ xtrabackup_prepare_func(char** argv) ...@@ -4953,9 +4720,7 @@ xtrabackup_prepare_func(char** argv)
srv_operation = SRV_OPERATION_RESTORE_DELTA; srv_operation = SRV_OPERATION_RESTORE_DELTA;
if (innodb_init_param()) { if (innodb_init_param()) {
error_cleanup: goto error_cleanup;
xb_filters_free();
return(false);
} }
xb_normalize_init_values(); xb_normalize_init_values();
...@@ -5028,169 +4793,6 @@ xtrabackup_prepare_func(char** argv) ...@@ -5028,169 +4793,6 @@ xtrabackup_prepare_func(char** argv)
goto error_cleanup; goto error_cleanup;
} }
if (xtrabackup_export) {
#if 1 // FIXME: remove the option or fix the logic
/* In MariaDB 10.2, undo log processing would need the
ability to evaluate indexed virtual columns, and we
have not initialized the necessary infrastructure. */
msg("xtrabackup: --export does not work!\n");
ok = false;
} else if (xtrabackup_export) {
#endif
msg("xtrabackup: export option is specified.\n");
/* To allow subsequent MariaDB server startup independent
of the value of --innodb-log-checksums,
unconditionally enable redo log checksums. */
log_checksum_algorithm_ptr = log_block_calc_checksum_crc32;
pfs_os_file_t info_file;
char info_file_path[FN_REFLEN];
bool success;
char table_name[FN_REFLEN];
byte* page;
byte* buf = NULL;
buf = static_cast<byte *>(malloc(UNIV_PAGE_SIZE * 2));
page = static_cast<byte *>(ut_align(buf, UNIV_PAGE_SIZE));
it = datafiles_iter_new(fil_system);
if (it == NULL) {
msg("xtrabackup: Error: datafiles_iter_new() "
"failed.\n");
ok = false;
} else
while (fil_node_t *node = datafiles_iter_next(it)) {
int len;
char *next, *prev, *p;
dict_table_t* table;
dict_index_t* index;
ulint n_index;
const fil_space_t* space = node->space;
/* treat file_per_table only */
if (!fil_is_user_tablespace_id(space->id)) {
continue;
}
/* node exist == file exist, here */
strcpy(info_file_path, node->name);
#ifdef _WIN32
for (int i = 0; info_file_path[i]; i++)
if (info_file_path[i] == '\\')
info_file_path[i]= '/';
#endif
strcpy(info_file_path +
strlen(info_file_path) -
4, ".exp");
len =(ib_uint32_t)strlen(info_file_path);
p = info_file_path;
prev = NULL;
while ((next = strchr(p, '/')) != NULL)
{
prev = p;
p = next + 1;
}
info_file_path[len - 4] = 0;
strncpy(table_name, prev, FN_REFLEN);
info_file_path[len - 4] = '.';
mutex_enter(&(dict_sys->mutex));
table = dict_table_get_low(table_name);
if (!table) {
msg("xtrabackup: error: "
"cannot find dictionary "
"record of table %s\n",
table_name);
goto next_node;
}
/* Write MySQL 5.6 .cfg file */
if (!xb_export_cfg_write(node, table)) {
goto next_node;
}
index = dict_table_get_first_index(table);
n_index = UT_LIST_GET_LEN(table->indexes);
if (n_index > 31) {
msg("xtrabackup: warning: table '%s' has more "
"than 31 indexes, .exp file was not "
"generated. Table will fail to import "
"on server version prior to 5.6.\n",
table->name.m_name);
goto next_node;
}
/* init exp file */
memcpy(page, "xportinf", 8);
mach_write_to_4(page + 8, n_index);
memset(page + 12, 0, UNIV_PAGE_SIZE - 12);
strncpy((char *) page + 12,
table_name, 500);
msg("xtrabackup: export metadata of "
"table '%s' to file `%s` "
"(%lu indexes)\n",
table_name, info_file_path,
n_index);
n_index = 1;
while (index) {
mach_write_to_8(page + n_index * 512, index->id);
mach_write_to_4(page + n_index * 512 + 8,
index->page);
strncpy((char *) page + n_index * 512 +
12, index->name, 500);
msg("xtrabackup: name=%s, "
"id.low=%lu, page=%lu\n",
index->name(),
(ulint)(index->id &
0xFFFFFFFFUL),
(ulint) index->page);
index = dict_table_get_next_index(index);
n_index++;
}
os_normalize_path(info_file_path);
info_file = os_file_create(
0,
info_file_path,
OS_FILE_OVERWRITE,
OS_FILE_NORMAL, OS_DATA_FILE,
false, &success);
if (!success) {
os_file_get_last_error(TRUE);
goto next_node;
}
success = os_file_write(IORequestWrite, info_file_path,
info_file, page,
0, UNIV_PAGE_SIZE);
if (!success) {
os_file_get_last_error(TRUE);
goto next_node;
}
success = os_file_flush(info_file);
if (!success) {
os_file_get_last_error(TRUE);
goto next_node;
}
next_node:
if (info_file != OS_FILE_CLOSED) {
os_file_close(info_file);
info_file = OS_FILE_CLOSED;
}
mutex_exit(&(dict_sys->mutex));
}
free(buf);
}
if (ok) { if (ok) {
mtr_t mtr; mtr_t mtr;
...@@ -5227,8 +4829,6 @@ xtrabackup_prepare_func(char** argv) ...@@ -5227,8 +4829,6 @@ xtrabackup_prepare_func(char** argv)
} }
/* Check whether the log is applied enough or not. */ /* Check whether the log is applied enough or not. */
const lsn_t target_lsn = xtrabackup_incremental
? incremental_to_lsn : metadata_to_lsn;
if ((srv_start_lsn || fil_space_get(SRV_LOG_SPACE_FIRST_ID)) if ((srv_start_lsn || fil_space_get(SRV_LOG_SPACE_FIRST_ID))
&& srv_start_lsn < target_lsn) { && srv_start_lsn < target_lsn) {
msg("xtrabackup: error: " msg("xtrabackup: error: "
...@@ -5275,6 +4875,10 @@ xtrabackup_prepare_func(char** argv) ...@@ -5275,6 +4875,10 @@ xtrabackup_prepare_func(char** argv)
if (ok) ok = apply_log_finish(); if (ok) ok = apply_log_finish();
if (ok && xtrabackup_export)
ok= (prepare_export() == 0);
error_cleanup:
xb_filters_free(); xb_filters_free();
return ok; return ok;
} }
...@@ -5594,17 +5198,41 @@ handle_options(int argc, char **argv, char ***argv_client, char ***argv_server) ...@@ -5594,17 +5198,41 @@ handle_options(int argc, char **argv, char ***argv_client, char ***argv_server)
} }
static int main_low(char** argv); static int main_low(char** argv);
static int get_exepath(char *buf, size_t size, const char *argv0);
/* ================= main =================== */ /* ================= main =================== */
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
char **client_defaults, **server_defaults; char **client_defaults, **server_defaults;
if (argc > 1 && (strcmp(argv[1], "--innobackupex") == 0))
if (get_exepath(mariabackup_exe,FN_REFLEN, argv[0]))
strncpy(mariabackup_exe,argv[0], FN_REFLEN-1);
if (argc > 1 )
{
/* In "prepare export", we need to start mysqld
Since it is not always be installed on the machine,
we start "mariabackup --mysqld", which acts as mysqld
*/
if (strcmp(argv[1], "--mysqld") == 0)
{
extern int mysqld_main(int argc, char **argv);
argc--;
argv++;
argv[0]+=2;
return mysqld_main(argc, argv);
}
if(strcmp(argv[1], "--innobackupex") == 0)
{ {
argv++; argv++;
argc--; argc--;
innobackupex_mode = true; innobackupex_mode = true;
} }
}
if (argc > 1)
strncpy(orig_argv1,argv[1],sizeof(orig_argv1) -1);
init_signals(); init_signals();
MY_INIT(argv[0]); MY_INIT(argv[0]);
...@@ -5860,3 +5488,20 @@ static int main_low(char** argv) ...@@ -5860,3 +5488,20 @@ static int main_low(char** argv)
return(EXIT_SUCCESS); return(EXIT_SUCCESS);
} }
static int get_exepath(char *buf, size_t size, const char *argv0)
{
#ifdef _WIN32
DWORD ret = GetModuleFileNameA(NULL, buf, size);
if (ret > 0)
return 0;
#elif defined(__linux__)
ssize_t ret = readlink("/proc/self/exe", buf, size-1);
if(ret > 0)
return 0;
#endif
return my_realpath(buf, argv0, 0);
}
partial : xtrabackup --export does not work
xb_page_compress : xtrabackup --export does not work
CREATE TABLE t1(i INT) ENGINE INNODB; CREATE TABLE t1(i INT) ENGINE INNODB;
INSERT INTO t1 VALUES(1); INSERT INTO t1 VALUES(1);
CREATE TABLE t21(i INT) ENGINE INNODB;
INSERT INTO t21 VALUES(1);
CREATE TABLE t2(i int) ENGINE INNODB; CREATE TABLE t2(i int) ENGINE INNODB;
# xtrabackup backup # xtrabackup backup
t1.ibd t1.ibd
t21.ibd
# xtrabackup prepare # xtrabackup prepare
t1.cfg
t21.cfg
ALTER TABLE t1 DISCARD TABLESPACE; ALTER TABLE t1 DISCARD TABLESPACE;
ALTER TABLE t1 IMPORT TABLESPACE; ALTER TABLE t1 IMPORT TABLESPACE;
SELECT * FROM t1; SELECT * FROM t1;
...@@ -11,3 +16,4 @@ i ...@@ -11,3 +16,4 @@ i
1 1
DROP TABLE t1; DROP TABLE t1;
DROP TABLE t2; DROP TABLE t2;
DROP TABLE t21;
...@@ -5,6 +5,9 @@ ...@@ -5,6 +5,9 @@
CREATE TABLE t1(i INT) ENGINE INNODB; CREATE TABLE t1(i INT) ENGINE INNODB;
INSERT INTO t1 VALUES(1); INSERT INTO t1 VALUES(1);
CREATE TABLE t21(i INT) ENGINE INNODB;
INSERT INTO t21 VALUES(1);
CREATE TABLE t2(i int) ENGINE INNODB; CREATE TABLE t2(i int) ENGINE INNODB;
echo # xtrabackup backup; echo # xtrabackup backup;
...@@ -15,13 +18,23 @@ exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup "--tables=te ...@@ -15,13 +18,23 @@ exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup "--tables=te
--enable_result_log --enable_result_log
list_files $targetdir/test *.ibd; list_files $targetdir/test *.ibd;
# Inject a junk .ibd file into backup dir to
# see if prepare does not choke on it.
write_file $targetdir/test/junk.ibd;
EOF
write_file $targetdir/test/junk.frm;
EOF
echo # xtrabackup prepare; echo # xtrabackup prepare;
--disable_result_log --disable_result_log
exec $XTRABACKUP --prepare --export --target-dir=$targetdir; exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --defaults-group-suffix=.1 --prepare --export --target-dir=$targetdir;
--enable_result_log --enable_result_log
ALTER TABLE t1 DISCARD TABLESPACE; list_files $targetdir/test *.cfg;
let $MYSQLD_DATADIR= `select @@datadir`; let $MYSQLD_DATADIR= `select @@datadir`;
ALTER TABLE t1 DISCARD TABLESPACE;
copy_file $targetdir/test/t1.ibd $MYSQLD_DATADIR/test/t1.ibd; copy_file $targetdir/test/t1.ibd $MYSQLD_DATADIR/test/t1.ibd;
copy_file $targetdir/test/t1.cfg $MYSQLD_DATADIR/test/t1.cfg; copy_file $targetdir/test/t1.cfg $MYSQLD_DATADIR/test/t1.cfg;
ALTER TABLE t1 IMPORT TABLESPACE; ALTER TABLE t1 IMPORT TABLESPACE;
...@@ -29,4 +42,5 @@ ALTER TABLE t1 IMPORT TABLESPACE; ...@@ -29,4 +42,5 @@ ALTER TABLE t1 IMPORT TABLESPACE;
SELECT * FROM t1; SELECT * FROM t1;
DROP TABLE t1; DROP TABLE t1;
DROP TABLE t2; DROP TABLE t2;
DROP TABLE t21;
rmdir $targetdir; rmdir $targetdir;
...@@ -29,7 +29,7 @@ let $targetdir=$MYSQLTEST_VARDIR/tmp/backup; ...@@ -29,7 +29,7 @@ let $targetdir=$MYSQLTEST_VARDIR/tmp/backup;
--disable_result_log --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 "--tables=test.*1" --target-dir=$targetdir;
echo # xtrabackup prepare; echo # xtrabackup prepare;
exec $XTRABACKUP --prepare --export --target-dir=$targetdir; exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --defaults-group-suffix=.1 --prepare --export --target-dir=$targetdir;
--enable_result_log --enable_result_log
ALTER TABLE t1 DISCARD TABLESPACE; ALTER TABLE t1 DISCARD TABLESPACE;
......
...@@ -4984,6 +4984,11 @@ static int init_server_components() ...@@ -4984,6 +4984,11 @@ static int init_server_components()
help information. Since the implementation of plugin server help information. Since the implementation of plugin server
variables the help output is now written much later. variables the help output is now written much later.
*/ */
#ifdef _WIN32
if (opt_console)
opt_error_log= false;
#endif
if (opt_error_log && !opt_abort) if (opt_error_log && !opt_abort)
{ {
if (!log_error_file_ptr[0]) if (!log_error_file_ptr[0])
......
...@@ -589,6 +589,7 @@ row_quiesce_table_complete( ...@@ -589,6 +589,7 @@ row_quiesce_table_complete(
++count; ++count;
} }
if (!opt_bootstrap) {
/* Remove the .cfg file now that the user has resumed /* Remove the .cfg file now that the user has resumed
normal operations. Otherwise it will cause problems when normal operations. Otherwise it will cause problems when
the user tries to drop the database (remove directory). */ the user tries to drop the database (remove directory). */
...@@ -599,6 +600,7 @@ row_quiesce_table_complete( ...@@ -599,6 +600,7 @@ row_quiesce_table_complete(
os_file_delete_if_exists(innodb_data_file_key, cfg_name, NULL); os_file_delete_if_exists(innodb_data_file_key, cfg_name, NULL);
ib::info() << "Deleting the meta-data file '" << cfg_name << "'"; ib::info() << "Deleting the meta-data file '" << cfg_name << "'";
}
if (trx_purge_state() != PURGE_STATE_DISABLED) { if (trx_purge_state() != PURGE_STATE_DISABLED) {
trx_purge_run(); trx_purge_run();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment