summaryrefslogtreecommitdiff
path: root/client/mysqldump.c
diff options
context:
space:
mode:
Diffstat (limited to 'client/mysqldump.c')
-rw-r--r--client/mysqldump.c215
1 files changed, 151 insertions, 64 deletions
diff --git a/client/mysqldump.c b/client/mysqldump.c
index cdda4f7a61d..6834d16bde7 100644
--- a/client/mysqldump.c
+++ b/client/mysqldump.c
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2000, 2012, Oracle and/or its affiliates.
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
@@ -38,7 +38,7 @@
** 10 Jun 2003: SET NAMES and --no-set-names by Alexander Barkov
*/
-#define DUMP_VERSION "10.13"
+#define DUMP_VERSION "10.14"
#include <my_global.h>
#include <my_sys.h>
@@ -55,8 +55,6 @@
#include <welcome_copyright_notice.h> /* ORACLE_WELCOME_COPYRIGHT_NOTICE */
-#include <welcome_copyright_notice.h> /* ORACLE_WELCOME_COPYRIGHT_NOTICE */
-
/* Exit codes */
#define EX_USAGE 1
@@ -85,6 +83,9 @@
#define IGNORE_DATA 0x01 /* don't dump data for this table */
#define IGNORE_INSERT_DELAYED 0x02 /* table doesn't support INSERT DELAYED */
+/* Chars needed to store LONGLONG, excluding trailing '\0'. */
+#define LONGLONG_LEN 20
+
static void add_load_option(DYNAMIC_STRING *str, const char *option,
const char *option_value);
static ulong find_set(TYPELIB *lib, const char *x, uint length,
@@ -222,8 +223,8 @@ static struct my_option my_long_options[] =
&opt_slave_apply, &opt_slave_apply, 0, GET_BOOL, NO_ARG,
0, 0, 0, 0, 0, 0},
{"character-sets-dir", OPT_CHARSETS_DIR,
- "Directory for character set files.", &charsets_dir,
- &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ "Directory for character set files.", (char**) &charsets_dir,
+ (char**) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"comments", 'i', "Write additional information.",
&opt_comments, &opt_comments, 0, GET_BOOL, NO_ARG,
1, 0, 0, 0, 0, 0},
@@ -260,8 +261,8 @@ static struct my_option my_long_options[] =
{"debug", '#', "This is a non-debug version. Catch this and exit.",
0,0, 0, GET_DISABLED, OPT_ARG, 0, 0, 0, 0, 0, 0},
#else
- {"debug", '#', "Output debug log.", &default_dbug_option,
- &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
+ {"debug", '#', "Output debug log.", (char**) &default_dbug_option,
+ (char**) &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
#endif
{"debug-check", OPT_DEBUG_CHECK, "Check memory and open file usage at exit.",
&debug_check_flag, &debug_check_flag, 0,
@@ -375,9 +376,9 @@ static struct my_option my_long_options[] =
"This causes the binary log position and filename to be appended to the "
"output. If equal to 1, will print it as a CHANGE MASTER command; if equal"
" to 2, that command will be prefixed with a comment symbol. "
- "This option will turn --lock-all-tables on, unless "
- "--single-transaction is specified too (in which case a "
- "global read lock is only taken a short time at the beginning of the dump; "
+ "This option will turn --lock-all-tables on, unless --single-transaction "
+ "is specified too (on servers before MariaDB 5.3 this will still take a "
+ "global read lock for a short time at the beginning of the dump; "
"don't forget to read about --single-transaction below). In all cases, "
"any action on logs will happen at the exact moment of the dump. "
"Option automatically turns --lock-tables off.",
@@ -517,7 +518,8 @@ static struct my_option my_long_options[] =
{0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};
-static const char *load_default_groups[]= { "mysqldump","client",0 };
+static const char *load_default_groups[]=
+{ "mysqldump", "client", "client-server", "client-mariadb", 0 };
static void maybe_exit(int error);
static void die(int error, const char* reason, ...);
@@ -588,24 +590,25 @@ void check_io(FILE *file)
static void print_version(void)
{
- printf("%s Ver %s Distrib %s, for %s (%s)\n",my_progname,DUMP_VERSION,
+ printf("%s Ver %s Distrib %s, for %s (%s)\n",my_progname_short,DUMP_VERSION,
MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
} /* print_version */
static void short_usage_sub(void)
{
- printf("Usage: %s [OPTIONS] database [tables]\n", my_progname);
+ printf("Usage: %s [OPTIONS] database [tables]\n", my_progname_short);
printf("OR %s [OPTIONS] --databases [OPTIONS] DB1 [DB2 DB3...]\n",
- my_progname);
- printf("OR %s [OPTIONS] --all-databases [OPTIONS]\n", my_progname);
+ my_progname_short);
+ printf("OR %s [OPTIONS] --all-databases [OPTIONS]\n", my_progname_short);
}
static void usage(void)
{
print_version();
- puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000, 2011"));
+ puts("By Igor Romanenko, Monty, Jani & Sinisa and others.");
+ puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,\nand you are welcome to modify and redistribute it under the GPL license.\n");
puts("Dumping structure and contents of MySQL databases and tables.");
short_usage_sub();
print_defaults("my",load_default_groups);
@@ -617,7 +620,7 @@ static void usage(void)
static void short_usage(void)
{
short_usage_sub();
- printf("For more options, use %s --help\n", my_progname);
+ printf("For more options, use %s --help\n", my_progname_short);
}
@@ -666,8 +669,13 @@ static void write_header(FILE *sql_file, char *db_name)
if (!path)
{
+ if (!opt_no_create_info)
+ {
+ /* We don't need unique checks as the table is created just before */
+ fprintf(md_result_file,"\
+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;\n");
+ }
fprintf(md_result_file,"\
-/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;\n\
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;\n\
");
}
@@ -697,8 +705,12 @@ static void write_footer(FILE *sql_file)
if (!path)
{
fprintf(md_result_file,"\
-/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;\n\
+/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;\n");
+ if (!opt_no_create_info)
+ {
+ fprintf(md_result_file,"\
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;\n");
+ }
}
if (opt_set_charset)
fprintf(sql_file,
@@ -935,7 +947,7 @@ static int get_options(int *argc, char ***argv)
fields_terminated))
{
fprintf(stderr,
- "%s: You must use option --tab with --fields-...\n", my_progname);
+ "%s: You must use option --tab with --fields-...\n", my_progname_short);
return(EX_USAGE);
}
@@ -953,7 +965,7 @@ static int get_options(int *argc, char ***argv)
if (opt_single_transaction && opt_lock_all_tables)
{
fprintf(stderr, "%s: You can't use --single-transaction and "
- "--lock-all-tables at the same time.\n", my_progname);
+ "--lock-all-tables at the same time.\n", my_progname_short);
return(EX_USAGE);
}
if (opt_master_data)
@@ -965,14 +977,14 @@ static int get_options(int *argc, char ***argv)
lock_tables= 0;
if (enclosed && opt_enclosed)
{
- fprintf(stderr, "%s: You can't use ..enclosed.. and ..optionally-enclosed.. at the same time.\n", my_progname);
+ fprintf(stderr, "%s: You can't use ..enclosed.. and ..optionally-enclosed.. at the same time.\n", my_progname_short);
return(EX_USAGE);
}
if ((opt_databases || opt_alldbs) && path)
{
fprintf(stderr,
"%s: --databases or --all-databases can't be used with --tab.\n",
- my_progname);
+ my_progname_short);
return(EX_USAGE);
}
if (strcmp(default_charset, charset_info->csname) &&
@@ -996,7 +1008,7 @@ static int get_options(int *argc, char ***argv)
static void DB_error(MYSQL *mysql_arg, const char *when)
{
DBUG_ENTER("DB_error");
- maybe_die(EX_MYSQLERR, "Got error: %d: %s %s",
+ maybe_die(EX_MYSQLERR, "Got error: %d: \"%s\" %s",
mysql_errno(mysql_arg), mysql_error(mysql_arg), when);
DBUG_VOID_RETURN;
}
@@ -1024,7 +1036,7 @@ static void die(int error_num, const char* fmt_reason, ...)
my_vsnprintf(buffer, sizeof(buffer), fmt_reason, args);
va_end(args);
- fprintf(stderr, "%s: %s\n", my_progname, buffer);
+ fprintf(stderr, "%s: %s\n", my_progname_short, buffer);
fflush(stderr);
ignore_errors= 0; /* force the exit */
@@ -1058,7 +1070,7 @@ static void maybe_die(int error_num, const char* fmt_reason, ...)
my_vsnprintf(buffer, sizeof(buffer), fmt_reason, args);
va_end(args);
- fprintf(stderr, "%s: %s\n", my_progname, buffer);
+ fprintf(stderr, "%s: %s\n", my_progname_short, buffer);
fflush(stderr);
maybe_exit(error_num);
@@ -1141,6 +1153,44 @@ static int fetch_db_collation(const char *db_name,
}
+/*
+ Check if server supports non-blocking binlog position using the
+ binlog_snapshot_file and binlog_snapshot_position status variables. If it
+ does, also return the position obtained if output pointers are non-NULL.
+ Returns 1 if position available, 0 if not.
+*/
+static int
+check_consistent_binlog_pos(char *binlog_pos_file, char *binlog_pos_offset)
+{
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ int found;
+
+ if (mysql_query_with_error_report(mysql, &res,
+ "SHOW STATUS LIKE 'binlog_snapshot_%'"))
+ return 1;
+
+ found= 0;
+ while ((row= mysql_fetch_row(res)))
+ {
+ if (0 == strcmp(row[0], "binlog_snapshot_file"))
+ {
+ if (binlog_pos_file)
+ strmake(binlog_pos_file, row[1], FN_REFLEN-1);
+ found++;
+ }
+ else if (0 == strcmp(row[0], "binlog_snapshot_position"))
+ {
+ if (binlog_pos_offset)
+ strmake(binlog_pos_offset, row[1], LONGLONG_LEN);
+ found++;
+ }
+ }
+ mysql_free_result(res);
+
+ return (found == 2);
+}
+
static char *my_case_str(const char *str,
uint str_len,
const char *token,
@@ -1427,6 +1477,7 @@ static void free_resources()
if (md_result_file && md_result_file != stdout)
my_fclose(md_result_file, MYF(0));
my_free(opt_password);
+ my_free(current_host);
if (my_hash_inited(&ignore_table))
my_hash_free(&ignore_table);
if (extended_insert)
@@ -1435,6 +1486,7 @@ static void free_resources()
dynstr_free(&insert_pat);
if (defaults_argv)
free_defaults(defaults_argv);
+ mysql_library_end();
my_end(my_end_arg);
}
@@ -1486,9 +1538,9 @@ static int connect_to_db(char *host, char *user,char *passwd)
if (opt_default_auth && *opt_default_auth)
mysql_options(&mysql_connection, MYSQL_DEFAULT_AUTH, opt_default_auth);
- if (!(mysql= mysql_real_connect(&mysql_connection,host,user,passwd,
- NULL,opt_mysql_port,opt_mysql_unix_port,
- 0)))
+ mysql= &mysql_connection; /* So we can mysql_close() it properly */
+ if (!mysql_real_connect(&mysql_connection,host,user,passwd,
+ NULL,opt_mysql_port,opt_mysql_unix_port, 0))
{
DB_error(&mysql_connection, "when trying to connect");
DBUG_RETURN(1);
@@ -2100,7 +2152,7 @@ static uint dump_events_for_db(char *db)
if (create_delimiter(row[3], delimiter, sizeof(delimiter)) == NULL)
{
fprintf(stderr, "%s: Warning: Can't create delimiter for event '%s'\n",
- my_progname, event_name);
+ my_progname_short, event_name);
DBUG_RETURN(1);
}
@@ -2714,7 +2766,7 @@ static uint get_table_structure(char *table, char *db, char *table_type,
else
{
verbose_msg("%s: Warning: Can't set SQL_QUOTE_SHOW_CREATE option (%s)\n",
- my_progname, mysql_error(mysql));
+ my_progname_short, mysql_error(mysql));
my_snprintf(query_buff, sizeof(query_buff), show_fields_stmt, db, table);
@@ -2825,7 +2877,7 @@ static uint get_table_structure(char *table, char *db, char *table_type,
goto continue_xml;
}
fprintf(stderr, "%s: Can't get keys for table %s (%s)\n",
- my_progname, result_table, mysql_error(mysql));
+ my_progname_short, result_table, mysql_error(mysql));
if (path)
my_fclose(sql_file, MYF(MY_WME));
DBUG_RETURN(0);
@@ -3481,7 +3533,7 @@ static void dump_table(char *table, char *db)
if (mysql_num_fields(res) != num_fields)
{
fprintf(stderr,"%s: Error in field count for table: %s ! Aborting.\n",
- my_progname, result_table);
+ my_progname_short, result_table);
error= EX_CONSCHECK;
goto err;
}
@@ -3746,7 +3798,7 @@ static void dump_table(char *table, char *db)
{
my_snprintf(buf, sizeof(buf),
"%s: Error %d: %s when dumping table %s at row: %ld\n",
- my_progname,
+ my_progname_short,
mysql_errno(mysql),
mysql_error(mysql),
result_table,
@@ -3940,8 +3992,8 @@ static int dump_tablespaces(char* ts_where)
DBUG_RETURN(0);
}
- my_printf_error(0, "Error: '%s' when trying to dump tablespaces",
- MYF(0), mysql_error(mysql));
+ fprintf(stderr, "%s: Error: '%s' when trying to dump tablespaces\n",
+ my_progname_short, mysql_error(mysql));
DBUG_RETURN(1);
}
@@ -4086,8 +4138,8 @@ static int dump_all_databases()
if (mysql_query(mysql, "SHOW DATABASES") ||
!(tableres= mysql_store_result(mysql)))
{
- my_printf_error(0, "Error: Couldn't execute 'SHOW DATABASES': %s",
- MYF(0), mysql_error(mysql));
+ fprintf(stderr, "%s: Error: Couldn't execute 'SHOW DATABASES': %s\n",
+ my_progname_short, mysql_error(mysql));
return 1;
}
while ((row= mysql_fetch_row(tableres)))
@@ -4580,41 +4632,64 @@ static int dump_selected_tables(char *db, char **table_names, int tables)
} /* dump_selected_tables */
-static int do_show_master_status(MYSQL *mysql_con)
+static int do_show_master_status(MYSQL *mysql_con, int consistent_binlog_pos)
{
MYSQL_ROW row;
- MYSQL_RES *master;
+ MYSQL_RES *UNINIT_VAR(master);
+ char binlog_pos_file[FN_REFLEN];
+ char binlog_pos_offset[LONGLONG_LEN+1];
+ char *file, *offset;
const char *comment_prefix=
(opt_master_data == MYSQL_OPT_MASTER_DATA_COMMENTED_SQL) ? "-- " : "";
- if (mysql_query_with_error_report(mysql_con, &master, "SHOW MASTER STATUS"))
+
+ if (consistent_binlog_pos)
{
- return 1;
+ if(!check_consistent_binlog_pos(binlog_pos_file, binlog_pos_offset))
+ return 1;
+ file= binlog_pos_file;
+ offset= binlog_pos_offset;
}
else
{
+ if (mysql_query_with_error_report(mysql_con, &master, "SHOW MASTER STATUS"))
+ return 1;
+
row= mysql_fetch_row(master);
if (row && row[0] && row[1])
{
- /* SHOW MASTER STATUS reports file and position */
- print_comment(md_result_file, 0,
- "\n--\n-- Position to start replication or point-in-time "
- "recovery from\n--\n\n");
- fprintf(md_result_file,
- "%sCHANGE MASTER TO MASTER_LOG_FILE='%s', MASTER_LOG_POS=%s;\n",
- comment_prefix, row[0], row[1]);
- check_io(md_result_file);
+ file= row[0];
+ offset= row[1];
}
- else if (!ignore_errors)
+ else
{
- /* SHOW MASTER STATUS reports nothing and --force is not enabled */
- my_printf_error(0, "Error: Binlogging on server not active",
- MYF(0));
mysql_free_result(master);
- maybe_exit(EX_MYSQLERR);
- return 1;
+ if (!ignore_errors)
+ {
+ /* SHOW MASTER STATUS reports nothing and --force is not enabled */
+ fprintf(stderr, "%s: Error: Binlogging on server not active\n",
+ my_progname_short);
+ maybe_exit(EX_MYSQLERR);
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
}
- mysql_free_result(master);
}
+
+ /* SHOW MASTER STATUS reports file and position */
+ print_comment(md_result_file, 0,
+ "\n--\n-- Position to start replication or point-in-time "
+ "recovery from\n--\n\n");
+ fprintf(md_result_file,
+ "%sCHANGE MASTER TO MASTER_LOG_FILE='%s', MASTER_LOG_POS=%s;\n",
+ comment_prefix, file, offset);
+ check_io(md_result_file);
+
+ if (!consistent_binlog_pos)
+ mysql_free_result(master);
+
return 0;
}
@@ -4675,7 +4750,7 @@ static int do_show_slave_status(MYSQL *mysql_con)
if (!ignore_errors)
{
/* SHOW SLAVE STATUS reports nothing and --force is not enabled */
- my_printf_error(0, "Error: Slave not set up", MYF(0));
+ fprintf(stderr, "%s: Error: Slave not set up\n", my_progname_short);
}
mysql_free_result(slave);
return 1;
@@ -4735,7 +4810,7 @@ static int do_start_slave_sql(MYSQL *mysql_con)
/* now, start slave if stopped */
if (mysql_query_with_error_report(mysql_con, 0, "START SLAVE"))
{
- my_printf_error(0, "Error: Unable to start slave", MYF(0));
+ fprintf(stderr, "%s: Error: Unable to start slave\n", my_progname_short);
return 1;
}
return(0);
@@ -5172,6 +5247,7 @@ static my_bool get_view_structure(char *table, char* db)
field= mysql_fetch_field_direct(table_res, 0);
if (strcmp(field->name, "View") != 0)
{
+ mysql_free_result(table_res);
switch_character_set_results(mysql, default_charset);
verbose_msg("-- It's base table, skipped\n");
DBUG_RETURN(0);
@@ -5181,8 +5257,10 @@ static my_bool get_view_structure(char *table, char* db)
if (path)
{
if (!(sql_file= open_sql_file_for_table(table, O_WRONLY)))
+ {
+ mysql_free_result(table_res);
DBUG_RETURN(1);
-
+ }
write_header(sql_file, db);
}
@@ -5373,8 +5451,10 @@ int main(int argc, char **argv)
{
char bin_log_name[FN_REFLEN];
int exit_code;
- MY_INIT("mysqldump");
+ int consistent_binlog_pos= 0;
+ MY_INIT(argv[0]);
+ sf_leaking_memory=1; /* don't report memory leaks on early exits */
compatible_mode_normal_str[0]= 0;
default_charset= (char *)mysql_universal_client_charset;
bzero((char*) &ignore_table, sizeof(ignore_table));
@@ -5385,6 +5465,7 @@ int main(int argc, char **argv)
free_resources();
exit(exit_code);
}
+ sf_leaking_memory=0; /* from now on we cleanup properly */
/*
Disable comments in xml mode if 'comments' option is not explicitly used.
@@ -5412,7 +5493,13 @@ int main(int argc, char **argv)
if (opt_slave_data && do_stop_slave_sql(mysql))
goto err;
- if ((opt_lock_all_tables || opt_master_data ||
+ if (opt_single_transaction && opt_master_data)
+ {
+ /* See if we can avoid FLUSH TABLES WITH READ LOCK (MariaDB 5.3+). */
+ consistent_binlog_pos= check_consistent_binlog_pos(NULL, NULL);
+ }
+
+ if ((opt_lock_all_tables || (opt_master_data && !consistent_binlog_pos) ||
(opt_single_transaction && flush_logs)) &&
do_flush_tables_read_lock(mysql))
goto err;
@@ -5448,7 +5535,7 @@ int main(int argc, char **argv)
/* Add 'STOP SLAVE to beginning of dump */
if (opt_slave_apply && add_stop_slave())
goto err;
- if (opt_master_data && do_show_master_status(mysql))
+ if (opt_master_data && do_show_master_status(mysql, consistent_binlog_pos))
goto err;
if (opt_slave_data && do_show_slave_status(mysql))
goto err;