summaryrefslogtreecommitdiff
path: root/client/mysqldump.c
diff options
context:
space:
mode:
Diffstat (limited to 'client/mysqldump.c')
-rw-r--r--client/mysqldump.c185
1 files changed, 184 insertions, 1 deletions
diff --git a/client/mysqldump.c b/client/mysqldump.c
index aa81a0e98bf..95206802fd7 100644
--- a/client/mysqldump.c
+++ b/client/mysqldump.c
@@ -98,6 +98,8 @@ static my_bool verbose= 0, opt_no_create_info= 0, opt_no_data= 0,
opt_complete_insert= 0, opt_drop_database= 0,
opt_replace_into= 0,
opt_dump_triggers= 0, opt_routines=0, opt_tz_utc=1,
+ opt_slave_apply= 0,
+ opt_include_master_host_port= 0,
opt_events= 0,
opt_alltspcs=0, opt_notspcs= 0;
static my_bool insert_pat_inited= 0, debug_info_flag= 0, debug_check_flag= 0;
@@ -118,7 +120,10 @@ static my_bool server_supports_switching_charsets= TRUE;
static ulong opt_compatible_mode= 0;
#define MYSQL_OPT_MASTER_DATA_EFFECTIVE_SQL 1
#define MYSQL_OPT_MASTER_DATA_COMMENTED_SQL 2
+#define MYSQL_OPT_SLAVE_DATA_EFFECTIVE_SQL 1
+#define MYSQL_OPT_SLAVE_DATA_COMMENTED_SQL 2
static uint opt_mysql_port= 0, opt_master_data;
+static uint opt_slave_data;
static uint my_end_arg;
static char * opt_mysql_unix_port=0;
static int first_error=0;
@@ -206,6 +211,10 @@ static struct my_option my_long_options[] =
{"allow-keywords", OPT_KEYWORDS,
"Allow creation of column names that are keywords.", (uchar**) &opt_keywords,
(uchar**) &opt_keywords, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"apply-slave-statements", OPT_MYSQLDUMP_SLAVE_APPLY,
+ "Adds 'STOP SLAVE' prior to 'CHANGE MASTER' and 'START SLAVE' to bottom of dump.",
+ (uchar**) &opt_slave_apply, (uchar**) &opt_slave_apply, 0, GET_BOOL, NO_ARG,
+ 0, 0, 0, 0, 0, 0},
#ifdef __NETWARE__
{"autoclose", OPT_AUTO_CLOSE, "Auto close the screen on exit for Netware.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
@@ -264,6 +273,19 @@ static struct my_option my_long_options[] =
{"disable-keys", 'K',
"'/*!40000 ALTER TABLE tb_name DISABLE KEYS */; and '/*!40000 ALTER TABLE tb_name ENABLE KEYS */; will be put in the output.", (uchar**) &opt_disable_keys,
(uchar**) &opt_disable_keys, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
+ {"dump-slave", OPT_MYSQLDUMP_SLAVE_DATA,
+ "This causes the binary log position and filename of the master to be "
+ "appended to the dumped data output. Setting the value to 1, will print"
+ "it as a CHANGE MASTER command in the dumped data output; 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 "
+ "- 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.",
+ (uchar**) &opt_slave_data, (uchar**) &opt_slave_data, 0,
+ GET_UINT, OPT_ARG, 0, 0, MYSQL_OPT_SLAVE_DATA_COMMENTED_SQL, 0, 0, 0},
{"events", 'E', "Dump events.",
(uchar**) &opt_events, (uchar**) &opt_events, 0, GET_BOOL,
NO_ARG, 0, 0, 0, 0, 0, 0},
@@ -317,6 +339,12 @@ static struct my_option my_long_options[] =
"use the directive multiple times, once for each table. Each table must "
"be specified with both database and table names, e.g. --ignore-table=database.table",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"include-master-host-port", OPT_MYSQLDUMP_INCLUDE_MASTER_HOST_PORT,
+ "Adds 'MASTER_HOST=<host>, MASTER_PORT=<port>' to 'CHANGE MASTER TO..' in dump produced with --dump-slave.",
+ (uchar**) &opt_include_master_host_port,
+ (uchar**) &opt_include_master_host_port,
+ 0, GET_BOOL, NO_ARG,
+ 0, 0, 0, 0, 0, 0},
{"insert-ignore", OPT_INSERT_IGNORE, "Insert rows with INSERT IGNORE.",
(uchar**) &opt_ignore, (uchar**) &opt_ignore, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
0, 0},
@@ -402,7 +430,7 @@ static struct my_option my_long_options[] =
(uchar**) &opt_routines, (uchar**) &opt_routines, 0, GET_BOOL,
NO_ARG, 0, 0, 0, 0, 0, 0},
{"set-charset", OPT_SET_CHARSET,
- "Add 'SET NAMES default_character_set' to the output. Enabled by default; suppress with --skip-set-charset.",
+ "Add 'SET NAMES default_character_set' to the output.",
(uchar**) &opt_set_charset, (uchar**) &opt_set_charset, 0, GET_BOOL, NO_ARG, 1,
0, 0, 0, 0, 0},
{"set-variable", 'O',
@@ -764,6 +792,10 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
if (!argument) /* work like in old versions */
opt_master_data= MYSQL_OPT_MASTER_DATA_EFFECTIVE_SQL;
break;
+ case (int) OPT_MYSQLDUMP_SLAVE_DATA:
+ if (!argument) /* work like in old versions */
+ opt_slave_data= MYSQL_OPT_SLAVE_DATA_EFFECTIVE_SQL;
+ break;
case (int) OPT_OPTIMIZE:
extended_insert= opt_drop= opt_lock= quick= create_options=
opt_disable_keys= lock_tables= opt_set_charset= 1;
@@ -896,6 +928,14 @@ static int get_options(int *argc, char ***argv)
return(EX_USAGE);
}
+ /* We don't delete master logs if slave data option */
+ if (opt_slave_data)
+ {
+ opt_lock_all_tables= !opt_single_transaction;
+ opt_master_data= 0;
+ opt_delete_master_logs= 0;
+ }
+
/* Ensure consistency of the set of binlog & locking options */
if (opt_delete_master_logs && !opt_master_data)
opt_master_data= MYSQL_OPT_MASTER_DATA_COMMENTED_SQL;
@@ -906,7 +946,10 @@ static int get_options(int *argc, char ***argv)
return(EX_USAGE);
}
if (opt_master_data)
+ {
opt_lock_all_tables= !opt_single_transaction;
+ opt_slave_data= 0;
+ }
if (opt_single_transaction || opt_lock_all_tables)
lock_tables= 0;
if (enclosed && opt_enclosed)
@@ -4333,6 +4376,130 @@ static int do_show_master_status(MYSQL *mysql_con)
return 0;
}
+static int do_stop_slave_sql(MYSQL *mysql_con)
+{
+ MYSQL_RES *slave;
+ /* We need to check if the slave sql is running in the first place */
+ if (mysql_query_with_error_report(mysql_con, &slave, "SHOW SLAVE STATUS"))
+ return(1);
+ else
+ {
+ MYSQL_ROW row= mysql_fetch_row(slave);
+ if (row && row[11])
+ {
+ /* if SLAVE SQL is not running, we don't stop it */
+ if (!strcmp(row[11],"No"))
+ {
+ mysql_free_result(slave);
+ /* Silently assume that they don't have the slave running */
+ return(0);
+ }
+ }
+ }
+ mysql_free_result(slave);
+
+ /* now, stop slave if running */
+ if (mysql_query_with_error_report(mysql_con, 0, "STOP SLAVE SQL_THREAD"))
+ return(1);
+
+ return(0);
+}
+
+static int add_stop_slave(void)
+{
+ if (opt_comments)
+ fprintf(md_result_file,
+ "\n--\n-- stop slave statement to make a recovery dump)\n--\n\n");
+ fprintf(md_result_file, "STOP SLAVE;\n");
+ return(0);
+}
+
+static int add_slave_statements(void)
+{
+ if (opt_comments)
+ fprintf(md_result_file,
+ "\n--\n-- start slave statement to make a recovery dump)\n--\n\n");
+ fprintf(md_result_file, "START SLAVE;\n");
+ return(0);
+}
+
+static int do_show_slave_status(MYSQL *mysql_con)
+{
+ MYSQL_RES *slave;
+ const char *comment_prefix=
+ (opt_slave_data == MYSQL_OPT_SLAVE_DATA_COMMENTED_SQL) ? "-- " : "";
+ if (mysql_query_with_error_report(mysql_con, &slave, "SHOW SLAVE STATUS"))
+ {
+ if (!ignore_errors)
+ {
+ /* SHOW SLAVE STATUS reports nothing and --force is not enabled */
+ my_printf_error(0, "Error: Slave not set up", MYF(0));
+ }
+ mysql_free_result(slave);
+ return 1;
+ }
+ else
+ {
+ MYSQL_ROW row= mysql_fetch_row(slave);
+ if (row && row[9] && row[21])
+ {
+ /* SHOW MASTER STATUS reports file and position */
+ if (opt_comments)
+ fprintf(md_result_file,
+ "\n--\n-- Position to start replication or point-in-time "
+ "recovery from (the master of this slave)\n--\n\n");
+
+ fprintf(md_result_file, "%sCHANGE MASTER TO ", comment_prefix);
+
+ if (opt_include_master_host_port)
+ {
+ if (row[1])
+ fprintf(md_result_file, "MASTER_HOST='%s', ", row[1]);
+ if (row[3])
+ fprintf(md_result_file, "MASTER_PORT='%s', ", row[3]);
+ }
+ fprintf(md_result_file,
+ "MASTER_LOG_FILE='%s', MASTER_LOG_POS=%s;\n", row[9], row[21]);
+
+ check_io(md_result_file);
+ }
+ mysql_free_result(slave);
+ }
+ return 0;
+}
+
+static int do_start_slave_sql(MYSQL *mysql_con)
+{
+ MYSQL_RES *slave;
+ /* We need to check if the slave sql is stopped in the first place */
+ if (mysql_query_with_error_report(mysql_con, &slave, "SHOW SLAVE STATUS"))
+ return(1);
+ else
+ {
+ MYSQL_ROW row= mysql_fetch_row(slave);
+ if (row && row[11])
+ {
+ /* if SLAVE SQL is not running, we don't start it */
+ if (!strcmp(row[11],"Yes"))
+ {
+ mysql_free_result(slave);
+ /* Silently assume that they don't have the slave running */
+ return(0);
+ }
+ }
+ }
+ mysql_free_result(slave);
+
+ /* 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));
+ return 1;
+ }
+ return(0);
+}
+
+
static int do_flush_tables_read_lock(MYSQL *mysql_con)
{
@@ -4995,6 +5162,9 @@ int main(int argc, char **argv)
if (!path)
write_header(md_result_file, *argv);
+ if (opt_slave_data && do_stop_slave_sql(mysql))
+ goto err;
+
if ((opt_lock_all_tables || opt_master_data) &&
do_flush_tables_read_lock(mysql))
goto err;
@@ -5013,8 +5183,13 @@ int main(int argc, char **argv)
goto err;
flush_logs= 0; /* not anymore; that would not be sensible */
}
+ /* 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))
goto err;
+ if (opt_slave_data && do_show_slave_status(mysql))
+ goto err;
if (opt_single_transaction && do_unlock_tables(mysql)) /* unlock but no commit! */
goto err;
@@ -5042,6 +5217,14 @@ int main(int argc, char **argv)
dump_databases(argv);
}
+ /* if --dump-slave , start the slave sql thread */
+ if (opt_slave_data && do_start_slave_sql(mysql))
+ goto err;
+
+ /* add 'START SLAVE' to end of dump */
+ if (opt_slave_apply && add_slave_statements())
+ goto err;
+
/* ensure dumped data flushed */
if (md_result_file && fflush(md_result_file))
{