mirror of
https://github.com/MariaDB/server.git
synced 2025-01-30 18:41:56 +01:00
fixed --skip-slave-thread bug
added PURGE MASTER LOGS TO and SHOW MASTER LOGS fixed the output of SHOW MASTER STATUS updated docs
This commit is contained in:
parent
c5a1c3c7df
commit
75cd25a579
13 changed files with 431 additions and 6 deletions
|
@ -159,3 +159,7 @@ PENDING/2000-10-11.06
|
||||||
BitKeeper/etc/csets-out
|
BitKeeper/etc/csets-out
|
||||||
BitKeeper/etc/csets-in
|
BitKeeper/etc/csets-in
|
||||||
support-files/mysql-3.23.26-beta.spec
|
support-files/mysql-3.23.26-beta.spec
|
||||||
|
include/.my_sys.h.swp
|
||||||
|
PENDING/2000-10-25.01
|
||||||
|
PENDING/2000-10-25.02
|
||||||
|
support-files/mysql-3.23.27-beta.spec
|
||||||
|
|
|
@ -24857,6 +24857,11 @@ propogation. @code{LOAD LOCAL DATA INFILE} will be skipped.
|
||||||
@item
|
@item
|
||||||
Update queries that use user variables are not replication-safe (yet)
|
Update queries that use user variables are not replication-safe (yet)
|
||||||
@item
|
@item
|
||||||
|
Temporary tables will not work if the table with the same name
|
||||||
|
is used in more than one thread - we plan on fixing this soon. For
|
||||||
|
now the only thing you can do is turn off logging of the trouble
|
||||||
|
queries with @code{SET SQL_LOG_BIN=0}
|
||||||
|
@item
|
||||||
Starting in 3.23.26, it is safe to connect servers in a circular
|
Starting in 3.23.26, it is safe to connect servers in a circular
|
||||||
master-slave relationship with @code{log-slave-updates} enabled.
|
master-slave relationship with @code{log-slave-updates} enabled.
|
||||||
Note, however, that many queries will not work right in this kind of
|
Note, however, that many queries will not work right in this kind of
|
||||||
|
@ -24918,6 +24923,9 @@ databases should not be logged to the binary log with @code{binlog-ignore-db}
|
||||||
Starting in 3.23.26, you can use @code{replicate-rewrite-db} to tell
|
Starting in 3.23.26, you can use @code{replicate-rewrite-db} to tell
|
||||||
the slave to apply updates from one database on the master to the one
|
the slave to apply updates from one database on the master to the one
|
||||||
with a different name on the slave
|
with a different name on the slave
|
||||||
|
@item
|
||||||
|
Starting in 3.23.28, you can use @code{PURGE MASTER LOGS TO 'log-name'}
|
||||||
|
to get rid of old logs while the slave is running
|
||||||
@end itemize
|
@end itemize
|
||||||
|
|
||||||
@node Replication Options, Replication SQL, Replication Features, Replication
|
@node Replication Options, Replication SQL, Replication Features, Replication
|
||||||
|
@ -25125,6 +25133,34 @@ command line. (Slave)
|
||||||
|
|
||||||
@item @code{SHOW SLAVE STATUS}
|
@item @code{SHOW SLAVE STATUS}
|
||||||
@tab Provides status info on essential parameters of the slave thread. (Slave)
|
@tab Provides status info on essential parameters of the slave thread. (Slave)
|
||||||
|
@item @code{SHOW MASTER LOGS}
|
||||||
|
@tab Only available starting in 3.23.28. Lists the binary logs on the master. You should use this command
|
||||||
|
prior to @code{PURGE MASTER LOGS TO} to find out how far you should go.
|
||||||
|
|
||||||
|
@item @code{PURGE MASTER LOGS TO 'logname'}
|
||||||
|
@tab Available starting in 3.23.28. Deletes all the
|
||||||
|
replication logs that are listed in the log
|
||||||
|
index as being prior to the specified log, and removed them from the
|
||||||
|
log index, so that the given log now becomes first. Example:
|
||||||
|
|
||||||
|
@example
|
||||||
|
PURGE MASTER LOGS TO 'mysql-bin.010'
|
||||||
|
@end example
|
||||||
|
|
||||||
|
This command will do nothing and fail with an error
|
||||||
|
if you have an active slave that
|
||||||
|
is currently reading one of the logs you are trying to delete. However,
|
||||||
|
if you have a dormant slave, and happen to purge one of the logs it
|
||||||
|
wants to read, the slave will be unable to replicate once it comes up.
|
||||||
|
The command is safe to run while slaves are replicating - you do not
|
||||||
|
need to stop them.
|
||||||
|
|
||||||
|
You must first check all the slaves with @code{SHOW SLAVE STATUS} to
|
||||||
|
see which log they are on, then do a listing of the logs on the
|
||||||
|
master with @code{SHOW MASTER LOGS}, find the earliest log among all
|
||||||
|
the slaves ( if all the slaves are up to date, this will be the
|
||||||
|
last log on the list), backup all the logs you are about to delete
|
||||||
|
(optional) and purge up to the target log.
|
||||||
|
|
||||||
@end multitable
|
@end multitable
|
||||||
|
|
||||||
|
@ -25164,7 +25200,20 @@ In 3.23.26 we added @code{server-id} to each replication server, and
|
||||||
now all the old zombie threads are killed on the master when a new replication thread
|
now all the old zombie threads are killed on the master when a new replication thread
|
||||||
connects from the same slave
|
connects from the same slave
|
||||||
|
|
||||||
|
@strong{Q}: How do I rotate replication logs?
|
||||||
|
|
||||||
|
@strong{A}: In 3.23.28 you should use @code{PURGE MASTER LOGS TO}
|
||||||
|
command after determining which logs can be deleted, and optionally
|
||||||
|
backing them up first. In earlier versions the process is much more
|
||||||
|
painful, and cannot be safely done without stopping all the slaves in
|
||||||
|
the case that you plan to re-use log names .
|
||||||
|
You will need to stop the slave threads, edit the binary log index
|
||||||
|
file, delete all the old logs, restart the master, start slave threads,
|
||||||
|
and then remove the old log files.
|
||||||
|
|
||||||
|
|
||||||
@strong{Q}: How do I upgrade on a hot replication setup?
|
@strong{Q}: How do I upgrade on a hot replication setup?
|
||||||
|
|
||||||
@strong{A}: If you are upgrading pre-3.23.26 versions, you should just
|
@strong{A}: If you are upgrading pre-3.23.26 versions, you should just
|
||||||
lock the master tables, let the slave catch up, then run @code{FLUSH
|
lock the master tables, let the slave catch up, then run @code{FLUSH
|
||||||
MASTER} on the master, and @code{FLUSH SLAVE} on the slave to reset the
|
MASTER} on the master, and @code{FLUSH SLAVE} on the slave to reset the
|
||||||
|
@ -38194,6 +38243,17 @@ though, so 3.23 is not released as a stable version yet.
|
||||||
Fixed bug in a BDB key compare function when comparing part keys.
|
Fixed bug in a BDB key compare function when comparing part keys.
|
||||||
@item
|
@item
|
||||||
Added variable @code{bdb_lock_max} to @code{mysqld}.
|
Added variable @code{bdb_lock_max} to @code{mysqld}.
|
||||||
|
@item
|
||||||
|
@code{SLAVE START} did not work if you started with
|
||||||
|
@code{--skip-slave-start} and had not explicitly run @code{CHANGE
|
||||||
|
MASTER TO}
|
||||||
|
@item
|
||||||
|
Fixed the output of @code{SHOW MASTER STATUS} to be consistent with
|
||||||
|
@code{SHOW SLAVE STATUS} ( no directory in the log name)
|
||||||
|
@item
|
||||||
|
Added @code{PURGE MASTER LOGS TO}
|
||||||
|
@item
|
||||||
|
Added @code{SHOW MASTER LOGS}
|
||||||
@end itemize
|
@end itemize
|
||||||
|
|
||||||
@node News-3.23.27, News-3.23.26, News-3.23.28, News-3.23.x
|
@node News-3.23.27, News-3.23.26, News-3.23.28, News-3.23.x
|
||||||
|
|
BIN
include/.my_sys.h.swp
Normal file
BIN
include/.my_sys.h.swp
Normal file
Binary file not shown.
|
@ -233,6 +233,7 @@ static SYMBOL symbols[] = {
|
||||||
{ "PACK_KEYS", SYM(PACK_KEYS_SYM),0,0},
|
{ "PACK_KEYS", SYM(PACK_KEYS_SYM),0,0},
|
||||||
{ "PARTIAL", SYM(PARTIAL),0,0},
|
{ "PARTIAL", SYM(PARTIAL),0,0},
|
||||||
{ "PASSWORD", SYM(PASSWORD),0,0},
|
{ "PASSWORD", SYM(PASSWORD),0,0},
|
||||||
|
{ "PURGE", SYM(PURGE),0,0},
|
||||||
{ "PRECISION", SYM(PRECISION),0,0},
|
{ "PRECISION", SYM(PRECISION),0,0},
|
||||||
{ "PRIMARY", SYM(PRIMARY_SYM),0,0},
|
{ "PRIMARY", SYM(PRIMARY_SYM),0,0},
|
||||||
{ "PROCEDURE", SYM(PROCEDURE),0,0},
|
{ "PROCEDURE", SYM(PROCEDURE),0,0},
|
||||||
|
|
141
sql/log.cc
141
sql/log.cc
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
#include "mysql_priv.h"
|
#include "mysql_priv.h"
|
||||||
#include "sql_acl.h"
|
#include "sql_acl.h"
|
||||||
|
#include "sql_repl.h"
|
||||||
|
|
||||||
#include <my_dir.h>
|
#include <my_dir.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
@ -256,7 +257,8 @@ int MYSQL_LOG::find_first_log(LOG_INFO* linfo, const char* log_name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the log entry matches, empty string matching anything
|
// if the log entry matches, empty string matching anything
|
||||||
if(!log_name_len || (fname[log_name_len] == '\n' && !memcmp(fname, log_name, log_name_len)))
|
if(!log_name_len || (fname[log_name_len] == '\n' &&
|
||||||
|
!memcmp(fname, log_name, log_name_len)))
|
||||||
{
|
{
|
||||||
if(log_name_len)
|
if(log_name_len)
|
||||||
fname[log_name_len] = 0; // to kill \n
|
fname[log_name_len] = 0; // to kill \n
|
||||||
|
@ -275,6 +277,137 @@ err:
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int MYSQL_LOG::purge_logs(THD* thd, const char* to_log)
|
||||||
|
{
|
||||||
|
if(!index_file) return LOG_INFO_INVALID;
|
||||||
|
if(no_rotate) return LOG_INFO_PURGE_NO_ROTATE;
|
||||||
|
int error;
|
||||||
|
char fname[FN_REFLEN];
|
||||||
|
char* fname_end, *p;
|
||||||
|
uint fname_len, i;
|
||||||
|
bool logs_to_purge_inited = 0, logs_to_keep_inited = 0, found_log = 0;
|
||||||
|
DYNAMIC_ARRAY logs_to_purge, logs_to_keep;
|
||||||
|
my_off_t purge_offset ;
|
||||||
|
pthread_mutex_lock(&LOCK_index);
|
||||||
|
|
||||||
|
if(my_fseek(index_file, 0, MY_SEEK_SET,
|
||||||
|
MYF(MY_WME) ) == MY_FILEPOS_ERROR)
|
||||||
|
{
|
||||||
|
error = LOG_INFO_SEEK;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(init_dynamic_array(&logs_to_purge, sizeof(char*), 1024, 1024))
|
||||||
|
{
|
||||||
|
error = LOG_INFO_MEM;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
logs_to_purge_inited = 1;
|
||||||
|
|
||||||
|
if(init_dynamic_array(&logs_to_keep, sizeof(char*), 1024, 1024))
|
||||||
|
{
|
||||||
|
error = LOG_INFO_MEM;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
logs_to_keep_inited = 1;
|
||||||
|
|
||||||
|
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
if(!fgets(fname, FN_REFLEN, index_file))
|
||||||
|
{
|
||||||
|
if(feof(index_file))
|
||||||
|
break;
|
||||||
|
else
|
||||||
|
error = LOG_INFO_IO;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
*(fname_end = (strend(fname) - 1)) = 0; // kill \n
|
||||||
|
fname_len = (uint)(fname_end - fname);
|
||||||
|
|
||||||
|
if(!memcmp(fname, to_log, fname_len + 1 ))
|
||||||
|
{
|
||||||
|
found_log = 1;
|
||||||
|
purge_offset = my_ftell(index_file, MYF(MY_WME)) - fname_len - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!found_log && log_in_use(fname))
|
||||||
|
// if one of the logs before the target is in use
|
||||||
|
{
|
||||||
|
error = LOG_INFO_IN_USE;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = sql_memdup(fname, (uint)(fname_end - fname) + 1);
|
||||||
|
if((found_log) ?
|
||||||
|
insert_dynamic(&logs_to_keep, (gptr) &p) :
|
||||||
|
insert_dynamic(&logs_to_purge, (gptr) &p)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
error = LOG_INFO_MEM;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!found_log)
|
||||||
|
{
|
||||||
|
error = LOG_INFO_EOF;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i = 0; i < logs_to_purge.elements; i++)
|
||||||
|
{
|
||||||
|
char* l;
|
||||||
|
get_dynamic(&logs_to_purge, (gptr)&l, i);
|
||||||
|
if(my_delete(l, MYF(MY_WME)))
|
||||||
|
sql_print_error("Error deleting %s during purge", l);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we get killed -9 here, the sysadmin would have to do a small
|
||||||
|
// vi job on the log index file after restart - otherwise, this should
|
||||||
|
// be safe
|
||||||
|
my_fclose(index_file, MYF(MY_WME));
|
||||||
|
if(!(index_file = my_fopen(index_file_name, O_BINARY|O_WRONLY,
|
||||||
|
MYF(MY_WME))))
|
||||||
|
{
|
||||||
|
sql_print_error("Ouch! Could not re-open the binlog index file \
|
||||||
|
during log purge for write");
|
||||||
|
error = LOG_INFO_FATAL;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i = 0; i < logs_to_keep.elements; i++)
|
||||||
|
{
|
||||||
|
char* l;
|
||||||
|
get_dynamic(&logs_to_keep, (gptr)&l, i);
|
||||||
|
fprintf(index_file, "%s\n", l);
|
||||||
|
}
|
||||||
|
my_fclose(index_file, MYF(MY_WME));
|
||||||
|
|
||||||
|
if(!(index_file = my_fopen(index_file_name, O_BINARY|O_RDWR|O_APPEND,
|
||||||
|
MYF(MY_WME))))
|
||||||
|
{
|
||||||
|
sql_print_error("Ouch! Could not re-open the binlog index file \
|
||||||
|
during log purge for append");
|
||||||
|
error = LOG_INFO_FATAL;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
// now update offsets
|
||||||
|
adjust_linfo_offsets(purge_offset);
|
||||||
|
error = 0;
|
||||||
|
err:
|
||||||
|
pthread_mutex_unlock(&LOCK_index);
|
||||||
|
if(logs_to_purge_inited)
|
||||||
|
delete_dynamic(&logs_to_purge);
|
||||||
|
if(logs_to_keep_inited)
|
||||||
|
delete_dynamic(&logs_to_keep);
|
||||||
|
|
||||||
|
return error;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
int MYSQL_LOG::find_next_log(LOG_INFO* linfo)
|
int MYSQL_LOG::find_next_log(LOG_INFO* linfo)
|
||||||
{
|
{
|
||||||
// mutex needed because we need to make sure the file pointer does not move
|
// mutex needed because we need to make sure the file pointer does not move
|
||||||
|
@ -285,6 +418,12 @@ int MYSQL_LOG::find_next_log(LOG_INFO* linfo)
|
||||||
char* end ;
|
char* end ;
|
||||||
|
|
||||||
pthread_mutex_lock(&LOCK_index);
|
pthread_mutex_lock(&LOCK_index);
|
||||||
|
if(linfo->fatal)
|
||||||
|
{
|
||||||
|
error = LOG_INFO_FATAL;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
if(my_fseek(index_file, linfo->index_file_offset, MY_SEEK_SET, MYF(MY_WME) ) == MY_FILEPOS_ERROR)
|
if(my_fseek(index_file, linfo->index_file_offset, MY_SEEK_SET, MYF(MY_WME) ) == MY_FILEPOS_ERROR)
|
||||||
{
|
{
|
||||||
error = LOG_INFO_SEEK;
|
error = LOG_INFO_SEEK;
|
||||||
|
|
|
@ -158,6 +158,8 @@ static bool opt_log,opt_update_log,opt_bin_log,opt_slow_log,opt_noacl,
|
||||||
opt_disable_networking=0, opt_bootstrap=0,opt_skip_show_db=0,
|
opt_disable_networking=0, opt_bootstrap=0,opt_skip_show_db=0,
|
||||||
opt_ansi_mode=0,opt_myisam_log=0;
|
opt_ansi_mode=0,opt_myisam_log=0;
|
||||||
bool opt_sql_bin_update = 0, opt_log_slave_updates = 0;
|
bool opt_sql_bin_update = 0, opt_log_slave_updates = 0;
|
||||||
|
extern MASTER_INFO glob_mi;
|
||||||
|
extern int init_master_info(MASTER_INFO* mi);
|
||||||
|
|
||||||
// if sql_bin_update is true, SQL_LOG_UPDATE and SQL_LOG_BIN are kept in sync, and are
|
// if sql_bin_update is true, SQL_LOG_UPDATE and SQL_LOG_BIN are kept in sync, and are
|
||||||
// treated as aliases for each other
|
// treated as aliases for each other
|
||||||
|
@ -1618,6 +1620,8 @@ int main(int argc, char **argv)
|
||||||
if(!opt_skip_slave_start &&
|
if(!opt_skip_slave_start &&
|
||||||
pthread_create(&hThread, &connection_attrib, handle_slave, 0))
|
pthread_create(&hThread, &connection_attrib, handle_slave, 0))
|
||||||
sql_print_error("Warning: Can't create thread to handle slave");
|
sql_print_error("Warning: Can't create thread to handle slave");
|
||||||
|
else if(opt_skip_slave_start)
|
||||||
|
init_master_info(&glob_mi);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
sql_print_error("Server id is not set, slave thread will not be started");
|
sql_print_error("Server id is not set, slave thread will not be started");
|
||||||
|
|
|
@ -94,6 +94,7 @@ THD::THD()
|
||||||
options=thd_startup_options;
|
options=thd_startup_options;
|
||||||
update_lock_default= low_priority_updates ? TL_WRITE_LOW_PRIORITY : TL_WRITE;
|
update_lock_default= low_priority_updates ? TL_WRITE_LOW_PRIORITY : TL_WRITE;
|
||||||
start_time=(time_t) 0;
|
start_time=(time_t) 0;
|
||||||
|
current_linfo = 0;
|
||||||
last_nx_table = last_nx_db = 0;
|
last_nx_table = last_nx_db = 0;
|
||||||
inactive_timeout=net_wait_timeout;
|
inactive_timeout=net_wait_timeout;
|
||||||
open_options=ha_open_options;
|
open_options=ha_open_options;
|
||||||
|
|
|
@ -34,12 +34,20 @@ enum enum_log_type { LOG_CLOSED, LOG_NORMAL, LOG_NEW, LOG_BIN };
|
||||||
#define LOG_INFO_IO -2
|
#define LOG_INFO_IO -2
|
||||||
#define LOG_INFO_INVALID -3
|
#define LOG_INFO_INVALID -3
|
||||||
#define LOG_INFO_SEEK -4
|
#define LOG_INFO_SEEK -4
|
||||||
|
#define LOG_INFO_PURGE_NO_ROTATE -5
|
||||||
|
#define LOG_INFO_MEM -6
|
||||||
|
#define LOG_INFO_FATAL -7
|
||||||
|
#define LOG_INFO_IN_USE -8
|
||||||
|
|
||||||
typedef struct st_log_info
|
typedef struct st_log_info
|
||||||
{
|
{
|
||||||
char log_file_name[FN_REFLEN];
|
char log_file_name[FN_REFLEN];
|
||||||
my_off_t index_file_offset;
|
my_off_t index_file_offset;
|
||||||
my_off_t pos;
|
my_off_t pos;
|
||||||
|
bool fatal; // if the purge happens to give us a negative offset
|
||||||
|
pthread_mutex_t lock;
|
||||||
|
st_log_info():fatal(0) { pthread_mutex_init(&lock, NULL);}
|
||||||
|
~st_log_info() { pthread_mutex_destroy(&lock);}
|
||||||
} LOG_INFO;
|
} LOG_INFO;
|
||||||
|
|
||||||
typedef struct st_master_info
|
typedef struct st_master_info
|
||||||
|
@ -114,6 +122,7 @@ public:
|
||||||
int generate_new_name(char *new_name,const char *old_name);
|
int generate_new_name(char *new_name,const char *old_name);
|
||||||
void make_log_name(char* buf, const char* log_ident);
|
void make_log_name(char* buf, const char* log_ident);
|
||||||
bool is_active(const char* log_file_name);
|
bool is_active(const char* log_file_name);
|
||||||
|
int purge_logs(THD* thd, const char* to_log);
|
||||||
void flush(void);
|
void flush(void);
|
||||||
void close(bool exiting = 0); // if we are exiting, we also want to close the
|
void close(bool exiting = 0); // if we are exiting, we also want to close the
|
||||||
// index file
|
// index file
|
||||||
|
@ -126,6 +135,9 @@ public:
|
||||||
inline bool is_open() { return log_type != LOG_CLOSED; }
|
inline bool is_open() { return log_type != LOG_CLOSED; }
|
||||||
char* get_index_fname() { return index_file_name;}
|
char* get_index_fname() { return index_file_name;}
|
||||||
char* get_log_fname() { return log_file_name; }
|
char* get_log_fname() { return log_file_name; }
|
||||||
|
void lock_index() { pthread_mutex_lock(&LOCK_index);}
|
||||||
|
void unlock_index() { pthread_mutex_unlock(&LOCK_index);}
|
||||||
|
FILE* get_index_file() { return index_file;}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* character conversion tables */
|
/* character conversion tables */
|
||||||
|
@ -295,6 +307,10 @@ public:
|
||||||
bool volatile killed,bootstrap;
|
bool volatile killed,bootstrap;
|
||||||
bool system_thread,in_lock_tables,global_read_lock;
|
bool system_thread,in_lock_tables,global_read_lock;
|
||||||
bool query_error;
|
bool query_error;
|
||||||
|
LOG_INFO* current_linfo;
|
||||||
|
// if we do a purge of binary logs, log index info of the threads
|
||||||
|
// that are currently reading it needs to be adjusted. To do that
|
||||||
|
// each thread that is using LOG_INFO needs to adjust the pointer to it
|
||||||
THD();
|
THD();
|
||||||
~THD();
|
~THD();
|
||||||
bool store_globals();
|
bool store_globals();
|
||||||
|
|
|
@ -48,7 +48,7 @@ enum enum_sql_command {
|
||||||
SQLCOM_BEGIN, SQLCOM_LOAD_MASTER_TABLE, SQLCOM_SHOW_CREATE,
|
SQLCOM_BEGIN, SQLCOM_LOAD_MASTER_TABLE, SQLCOM_SHOW_CREATE,
|
||||||
SQLCOM_SHOW_MASTER_STAT, SQLCOM_SHOW_SLAVE_STAT, SQLCOM_CHANGE_MASTER,
|
SQLCOM_SHOW_MASTER_STAT, SQLCOM_SHOW_SLAVE_STAT, SQLCOM_CHANGE_MASTER,
|
||||||
SQLCOM_RENAME_TABLE, SQLCOM_BACKUP_TABLE, SQLCOM_RESTORE_TABLE,
|
SQLCOM_RENAME_TABLE, SQLCOM_BACKUP_TABLE, SQLCOM_RESTORE_TABLE,
|
||||||
SQLCOM_RESET
|
SQLCOM_RESET, SQLCOM_PURGE, SQLCOM_SHOW_BINLOGS
|
||||||
};
|
};
|
||||||
|
|
||||||
enum lex_states { STATE_START, STATE_CHAR, STATE_IDENT,
|
enum lex_states { STATE_START, STATE_CHAR, STATE_IDENT,
|
||||||
|
@ -97,6 +97,7 @@ typedef struct st_lex {
|
||||||
char *length,*dec,*change,*name;
|
char *length,*dec,*change,*name;
|
||||||
char *db,*db1,*table1,*db2,*table2; /* For outer join using .. */
|
char *db,*db1,*table1,*db2,*table2; /* For outer join using .. */
|
||||||
char *backup_dir; /* For RESTORE/BACKUP */
|
char *backup_dir; /* For RESTORE/BACKUP */
|
||||||
|
char* to_log; /* For PURGE MASTER LOGS TO */
|
||||||
String *wild;
|
String *wild;
|
||||||
sql_exchange *exchange;
|
sql_exchange *exchange;
|
||||||
ha_rows select_limit,offset_limit;
|
ha_rows select_limit,offset_limit;
|
||||||
|
|
|
@ -927,6 +927,13 @@ mysql_execute_command(void)
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case SQLCOM_PURGE:
|
||||||
|
{
|
||||||
|
if(check_access(thd, PROCESS_ACL, any_db))
|
||||||
|
goto error;
|
||||||
|
res = purge_master_logs(thd, lex->to_log);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case SQLCOM_BACKUP_TABLE:
|
case SQLCOM_BACKUP_TABLE:
|
||||||
{
|
{
|
||||||
if (check_db_used(thd,tables) ||
|
if (check_db_used(thd,tables) ||
|
||||||
|
@ -1183,6 +1190,18 @@ mysql_execute_command(void)
|
||||||
res= -1;
|
res= -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case SQLCOM_SHOW_BINLOGS:
|
||||||
|
#ifdef DONT_ALLOW_SHOW_COMMANDS
|
||||||
|
send_error(&thd->net,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
|
#else
|
||||||
|
{
|
||||||
|
if(check_access(thd, PROCESS_ACL, any_db))
|
||||||
|
goto error;
|
||||||
|
res = show_binlogs(thd);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
case SQLCOM_SHOW_CREATE:
|
case SQLCOM_SHOW_CREATE:
|
||||||
#ifdef DONT_ALLOW_SHOW_COMMANDS
|
#ifdef DONT_ALLOW_SHOW_COMMANDS
|
||||||
send_error(&thd->net,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */
|
send_error(&thd->net,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */
|
||||||
|
|
166
sql/sql_repl.cc
166
sql/sql_repl.cc
|
@ -93,6 +93,87 @@ static int send_file(THD *thd)
|
||||||
DBUG_RETURN(error);
|
DBUG_RETURN(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void adjust_linfo_offsets(my_off_t purge_offset)
|
||||||
|
{
|
||||||
|
THD *tmp;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&LOCK_thread_count);
|
||||||
|
I_List_iterator<THD> it(threads);
|
||||||
|
|
||||||
|
while((tmp=it++))
|
||||||
|
{
|
||||||
|
LOG_INFO* linfo;
|
||||||
|
if((linfo = tmp->current_linfo))
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&linfo->lock);
|
||||||
|
// no big deal if we just started reading the log
|
||||||
|
// nothing to adjust
|
||||||
|
if(linfo->index_file_offset < purge_offset)
|
||||||
|
linfo->fatal = (linfo->index_file_offset != 0);
|
||||||
|
else
|
||||||
|
linfo->index_file_offset -= purge_offset;
|
||||||
|
pthread_mutex_unlock(&linfo->lock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&LOCK_thread_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool log_in_use(const char* log_name)
|
||||||
|
{
|
||||||
|
int log_name_len = strlen(log_name) + 1;
|
||||||
|
THD *tmp;
|
||||||
|
bool result = 0;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&LOCK_thread_count);
|
||||||
|
I_List_iterator<THD> it(threads);
|
||||||
|
|
||||||
|
while((tmp=it++))
|
||||||
|
{
|
||||||
|
LOG_INFO* linfo;
|
||||||
|
if((linfo = tmp->current_linfo))
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&linfo->lock);
|
||||||
|
result = !memcmp(log_name, linfo->log_file_name, log_name_len);
|
||||||
|
pthread_mutex_unlock(&linfo->lock);
|
||||||
|
if(result) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&LOCK_thread_count);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int purge_master_logs(THD* thd, const char* to_log)
|
||||||
|
{
|
||||||
|
char search_file_name[FN_REFLEN];
|
||||||
|
mysql_bin_log.make_log_name(search_file_name, to_log);
|
||||||
|
int res = mysql_bin_log.purge_logs(thd, search_file_name);
|
||||||
|
char* errmsg = 0;
|
||||||
|
switch(res)
|
||||||
|
{
|
||||||
|
case 0: break;
|
||||||
|
case LOG_INFO_EOF: errmsg = "Target log not found in binlog index"; break;
|
||||||
|
case LOG_INFO_IO: errmsg = "I/O error reading log index file"; break;
|
||||||
|
case LOG_INFO_INVALID: errmsg = "Server configuration does not permit \
|
||||||
|
binlog purge"; break;
|
||||||
|
case LOG_INFO_SEEK: errmsg = "Failed on fseek()"; break;
|
||||||
|
case LOG_INFO_PURGE_NO_ROTATE: errmsg = "Cannot purge unrotatable log";
|
||||||
|
break;
|
||||||
|
case LOG_INFO_MEM: errmsg = "Out of memory"; break;
|
||||||
|
case LOG_INFO_FATAL: errmsg = "Fatal error during purge"; break;
|
||||||
|
case LOG_INFO_IN_USE: errmsg = "A purgable log is in use, will not purge";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
errmsg = "Unknown error during purge"; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(errmsg)
|
||||||
|
send_error(&thd->net, 0, errmsg);
|
||||||
|
else
|
||||||
|
send_ok(&thd->net);
|
||||||
|
}
|
||||||
|
|
||||||
void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags)
|
void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags)
|
||||||
{
|
{
|
||||||
LOG_INFO linfo;
|
LOG_INFO linfo;
|
||||||
|
@ -118,6 +199,9 @@ void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags)
|
||||||
else
|
else
|
||||||
search_file_name[0] = 0;
|
search_file_name[0] = 0;
|
||||||
|
|
||||||
|
linfo.index_file_offset = 0;
|
||||||
|
thd->current_linfo = &linfo;
|
||||||
|
|
||||||
if(mysql_bin_log.find_first_log(&linfo, search_file_name))
|
if(mysql_bin_log.find_first_log(&linfo, search_file_name))
|
||||||
{
|
{
|
||||||
errmsg = "Could not find first log";
|
errmsg = "Could not find first log";
|
||||||
|
@ -366,9 +450,20 @@ sweepstakes if you report the bug";
|
||||||
|
|
||||||
send_eof(&thd->net);
|
send_eof(&thd->net);
|
||||||
thd->proc_info = "waiting to finalize termination";
|
thd->proc_info = "waiting to finalize termination";
|
||||||
|
pthread_mutex_lock(&LOCK_thread_count);
|
||||||
|
thd->current_linfo = 0;
|
||||||
|
pthread_mutex_unlock(&LOCK_thread_count);
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
err:
|
err:
|
||||||
thd->proc_info = "waiting to finalize termination";
|
thd->proc_info = "waiting to finalize termination";
|
||||||
|
pthread_mutex_lock(&LOCK_thread_count);
|
||||||
|
// exclude iteration through thread list
|
||||||
|
// this is needed for purge_logs() - it will iterate through
|
||||||
|
// thread list and update thd->current_linfo->index_file_offset
|
||||||
|
// this mutex will make sure that it never tried to update our linfo
|
||||||
|
// after we return from this stack frame
|
||||||
|
thd->current_linfo = 0;
|
||||||
|
pthread_mutex_unlock(&LOCK_thread_count);
|
||||||
if(log)
|
if(log)
|
||||||
(void) my_fclose(log, MYF(MY_WME));
|
(void) my_fclose(log, MYF(MY_WME));
|
||||||
send_error(&thd->net, 0, errmsg);
|
send_error(&thd->net, 0, errmsg);
|
||||||
|
@ -594,7 +689,8 @@ int show_binlog_info(THD* thd)
|
||||||
{
|
{
|
||||||
LOG_INFO li;
|
LOG_INFO li;
|
||||||
mysql_bin_log.get_current_log(&li);
|
mysql_bin_log.get_current_log(&li);
|
||||||
net_store_data(packet, li.log_file_name);
|
int dir_len = dirname_length(li.log_file_name);
|
||||||
|
net_store_data(packet, li.log_file_name + dir_len);
|
||||||
net_store_data(packet, (longlong)li.pos);
|
net_store_data(packet, (longlong)li.pos);
|
||||||
net_store_data(packet, &binlog_do_db);
|
net_store_data(packet, &binlog_do_db);
|
||||||
net_store_data(packet, &binlog_ignore_db);
|
net_store_data(packet, &binlog_ignore_db);
|
||||||
|
@ -613,3 +709,71 @@ int show_binlog_info(THD* thd)
|
||||||
send_eof(&thd->net);
|
send_eof(&thd->net);
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int show_binlogs(THD* thd)
|
||||||
|
{
|
||||||
|
const char* errmsg = 0;
|
||||||
|
FILE* index_file;
|
||||||
|
char fname[FN_REFLEN];
|
||||||
|
NET* net = &thd->net;
|
||||||
|
List<Item> field_list;
|
||||||
|
String* packet = &thd->packet;
|
||||||
|
|
||||||
|
if(!mysql_bin_log.is_open())
|
||||||
|
{
|
||||||
|
errmsg = "binlog is not open";
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
field_list.push_back(new Item_empty_string("Log_name", 128));
|
||||||
|
if(send_fields(thd, field_list, 1))
|
||||||
|
{
|
||||||
|
sql_print_error("Failed in send_fields");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
mysql_bin_log.lock_index();
|
||||||
|
index_file = mysql_bin_log.get_index_file();
|
||||||
|
if(!index_file)
|
||||||
|
{
|
||||||
|
errmsg = "Uninitialized index file pointer";
|
||||||
|
mysql_bin_log.unlock_index();
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
if(my_fseek(index_file, 0, MY_SEEK_SET, MYF(MY_WME)))
|
||||||
|
{
|
||||||
|
errmsg = "Failed on fseek()";
|
||||||
|
mysql_bin_log.unlock_index();
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
while(fgets(fname, sizeof(fname), index_file))
|
||||||
|
{
|
||||||
|
char* fname_end;
|
||||||
|
*(fname_end = (strend(fname) - 1)) = 0;
|
||||||
|
int dir_len = dirname_length(fname);
|
||||||
|
packet->length(0);
|
||||||
|
net_store_data(packet, fname + dir_len, (fname_end - fname)-dir_len);
|
||||||
|
if(my_net_write(net, (char*) packet->ptr(), packet->length()))
|
||||||
|
{
|
||||||
|
sql_print_error("Failed in my_net_write");
|
||||||
|
mysql_bin_log.unlock_index();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mysql_bin_log.unlock_index();
|
||||||
|
send_eof(net);
|
||||||
|
err:
|
||||||
|
if(errmsg)
|
||||||
|
{
|
||||||
|
send_error(net, 0, errmsg);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
send_ok(net);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,10 @@ int stop_slave(THD* thd = 0, bool net_report = 1);
|
||||||
int change_master(THD* thd);
|
int change_master(THD* thd);
|
||||||
void reset_slave();
|
void reset_slave();
|
||||||
void reset_master();
|
void reset_master();
|
||||||
|
int purge_master_logs(THD* thd, const char* to_log);
|
||||||
|
bool log_in_use(const char* log_name);
|
||||||
|
void adjust_linfo_offsets(my_off_t purge_offset);
|
||||||
|
int show_binlogs(THD* thd);
|
||||||
extern int init_master_info(MASTER_INFO* mi);
|
extern int init_master_info(MASTER_INFO* mi);
|
||||||
void kill_zombie_dump_threads(uint32 slave_server_id);
|
void kill_zombie_dump_threads(uint32 slave_server_id);
|
||||||
|
|
||||||
|
|
|
@ -107,6 +107,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
|
||||||
%token MASTER_SYM
|
%token MASTER_SYM
|
||||||
%token REPAIR
|
%token REPAIR
|
||||||
%token RESET_SYM
|
%token RESET_SYM
|
||||||
|
%token PURGE
|
||||||
%token SLAVE
|
%token SLAVE
|
||||||
%token START_SYM
|
%token START_SYM
|
||||||
%token STOP_SYM
|
%token STOP_SYM
|
||||||
|
@ -493,7 +494,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
|
||||||
%type <NONE>
|
%type <NONE>
|
||||||
query verb_clause create change select drop insert replace insert2
|
query verb_clause create change select drop insert replace insert2
|
||||||
insert_values update delete show describe load alter optimize flush
|
insert_values update delete show describe load alter optimize flush
|
||||||
reset begin commit rollback slave master_def master_defs
|
reset purge begin commit rollback slave master_def master_defs
|
||||||
repair restore backup analyze check rename
|
repair restore backup analyze check rename
|
||||||
field_list field_list_item field_spec kill
|
field_list field_list_item field_spec kill
|
||||||
select_item_list select_item values_list no_braces
|
select_item_list select_item values_list no_braces
|
||||||
|
@ -549,6 +550,7 @@ verb_clause:
|
||||||
| lock
|
| lock
|
||||||
| kill
|
| kill
|
||||||
| optimize
|
| optimize
|
||||||
|
| purge
|
||||||
| rename
|
| rename
|
||||||
| repair
|
| repair
|
||||||
| replace
|
| replace
|
||||||
|
@ -2147,6 +2149,10 @@ show_param:
|
||||||
if (!add_table_to_list($3,NULL))
|
if (!add_table_to_list($3,NULL))
|
||||||
YYABORT;
|
YYABORT;
|
||||||
}
|
}
|
||||||
|
| MASTER_SYM LOGS_SYM
|
||||||
|
{
|
||||||
|
Lex->sql_command = SQLCOM_SHOW_BINLOGS;
|
||||||
|
}
|
||||||
| keys_or_index FROM table_ident opt_db
|
| keys_or_index FROM table_ident opt_db
|
||||||
{
|
{
|
||||||
Lex->sql_command= SQLCOM_SHOW_KEYS;
|
Lex->sql_command= SQLCOM_SHOW_KEYS;
|
||||||
|
@ -2246,6 +2252,13 @@ reset_option:
|
||||||
SLAVE { Lex->type|= REFRESH_SLAVE; }
|
SLAVE { Lex->type|= REFRESH_SLAVE; }
|
||||||
| MASTER_SYM { Lex->type|= REFRESH_MASTER; }
|
| MASTER_SYM { Lex->type|= REFRESH_MASTER; }
|
||||||
|
|
||||||
|
purge:
|
||||||
|
PURGE { Lex->sql_command = SQLCOM_PURGE; Lex->type=0;}
|
||||||
|
MASTER_SYM LOGS_SYM TO_SYM TEXT_STRING
|
||||||
|
{
|
||||||
|
Lex->to_log = $6.str;
|
||||||
|
}
|
||||||
|
|
||||||
/* kill threads */
|
/* kill threads */
|
||||||
|
|
||||||
kill:
|
kill:
|
||||||
|
|
Loading…
Add table
Reference in a new issue