Commit 75cd25a5 authored by sasha@mysql.sashanet.com's avatar sasha@mysql.sashanet.com
Browse files

fixed --skip-slave-thread bug

added PURGE MASTER LOGS TO and SHOW MASTER LOGS
fixed the output of SHOW MASTER STATUS
updated docs
parent c5a1c3c7
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -159,3 +159,7 @@ PENDING/2000-10-11.06
BitKeeper/etc/csets-out
BitKeeper/etc/csets-in
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
+60 −0
Original line number Diff line number Diff line
@@ -24857,6 +24857,11 @@ propogation. @code{LOAD LOCAL DATA INFILE} will be skipped.
@item
Update queries that use user variables are not replication-safe (yet)
@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
master-slave relationship with @code{log-slave-updates} enabled.
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
the slave to apply updates from one database on the master to the one
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
@node Replication Options, Replication SQL, Replication Features, Replication
@@ -25125,6 +25133,34 @@ command line. (Slave)
@item @code{SHOW SLAVE STATUS}
 @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
@@ -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
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{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
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.
@item
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
@node News-3.23.27, News-3.23.26, News-3.23.28, News-3.23.x

include/.my_sys.h.swp

0 → 100644
+16 KiB

File added.

No diff preview for this file type.

+1 −0
Original line number Diff line number Diff line
@@ -233,6 +233,7 @@ static SYMBOL symbols[] = {
  { "PACK_KEYS",	SYM(PACK_KEYS_SYM),0,0},
  { "PARTIAL",		SYM(PARTIAL),0,0},
  { "PASSWORD",		SYM(PASSWORD),0,0},
  { "PURGE",		SYM(PURGE),0,0},
  { "PRECISION",	SYM(PRECISION),0,0},
  { "PRIMARY",		SYM(PRIMARY_SYM),0,0},
  { "PROCEDURE",	SYM(PROCEDURE),0,0},
+140 −1
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@

#include "mysql_priv.h"
#include "sql_acl.h"
#include "sql_repl.h"

#include <my_dir.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(!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)
	    fname[log_name_len] = 0; // to kill \n
@@ -275,6 +277,137 @@ int MYSQL_LOG::find_first_log(LOG_INFO* linfo, const char* log_name)
  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)
{
  // 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 ;
  
  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)
    {
      error = LOG_INFO_SEEK;
Loading