Commit fec70c97 authored by petr@mysql.com's avatar petr@mysql.com

WL#3153 "Split logs". Recommit with post-review fixes

parent 55ccf0fe
...@@ -428,7 +428,7 @@ static void ndbcluster_binlog_wait(THD *thd) ...@@ -428,7 +428,7 @@ static void ndbcluster_binlog_wait(THD *thd)
} }
/* /*
Called from MYSQL_LOG::reset_logs in log.cc when binlog is emptied Called from MYSQL_BIN_LOG::reset_logs in log.cc when binlog is emptied
*/ */
static int ndbcluster_reset_logs(THD *thd) static int ndbcluster_reset_logs(THD *thd)
{ {
...@@ -452,7 +452,7 @@ static int ndbcluster_reset_logs(THD *thd) ...@@ -452,7 +452,7 @@ static int ndbcluster_reset_logs(THD *thd)
} }
/* /*
Called from MYSQL_LOG::purge_logs in log.cc when the binlog "file" Called from MYSQL_BIN_LOG::purge_logs in log.cc when the binlog "file"
is removed is removed
*/ */
......
...@@ -42,7 +42,7 @@ extern char *opt_logname, *opt_slow_logname; ...@@ -42,7 +42,7 @@ extern char *opt_logname, *opt_slow_logname;
LOGGER logger; LOGGER logger;
MYSQL_LOG mysql_bin_log; MYSQL_BIN_LOG mysql_bin_log;
ulong sync_binlog_counter= 0; ulong sync_binlog_counter= 0;
static bool test_if_number(const char *str, static bool test_if_number(const char *str,
...@@ -557,9 +557,8 @@ void Log_to_file_event_handler::cleanup() ...@@ -557,9 +557,8 @@ void Log_to_file_event_handler::cleanup()
void Log_to_file_event_handler::flush() void Log_to_file_event_handler::flush()
{ {
/* reopen log files */ mysql_log.reopen_file();
mysql_log.new_file(1); mysql_slow_log.reopen_file();
mysql_slow_log.new_file(1);
} }
/* /*
...@@ -1054,7 +1053,7 @@ void Log_to_csv_event_handler:: ...@@ -1054,7 +1053,7 @@ void Log_to_csv_event_handler::
/* /*
this function is mostly a placeholder. this function is mostly a placeholder.
conceptually, binlog initialization (now mostly done in MYSQL_LOG::open) conceptually, binlog initialization (now mostly done in MYSQL_BIN_LOG::open)
should be moved here. should be moved here.
*/ */
...@@ -1128,7 +1127,7 @@ static int binlog_prepare(THD *thd, bool all) ...@@ -1128,7 +1127,7 @@ static int binlog_prepare(THD *thd, bool all)
do nothing. do nothing.
just pretend we can do 2pc, so that MySQL won't just pretend we can do 2pc, so that MySQL won't
switch to 1pc. switch to 1pc.
real work will be done in MYSQL_LOG::log() real work will be done in MYSQL_BIN_LOG::log()
*/ */
return 0; return 0;
} }
...@@ -1144,7 +1143,7 @@ static int binlog_commit(THD *thd, bool all) ...@@ -1144,7 +1143,7 @@ static int binlog_commit(THD *thd, bool all)
if (trx_data->empty()) if (trx_data->empty())
{ {
// we're here because trans_log was flushed in MYSQL_LOG::log() // we're here because trans_log was flushed in MYSQL_BIN_LOG::log()
DBUG_RETURN(0); DBUG_RETURN(0);
} }
Query_log_event qev(thd, STRING_WITH_LEN("COMMIT"), TRUE, FALSE); Query_log_event qev(thd, STRING_WITH_LEN("COMMIT"), TRUE, FALSE);
...@@ -1382,12 +1381,125 @@ static int find_uniq_filename(char *name) ...@@ -1382,12 +1381,125 @@ static int find_uniq_filename(char *name)
} }
void MYSQL_LOG::init(enum_log_type log_type_arg,
enum cache_type io_cache_type_arg)
{
DBUG_ENTER("MYSQL_LOG::init");
log_type= log_type_arg;
io_cache_type= io_cache_type_arg;
DBUG_PRINT("info",("log_type: %d", log_type));
DBUG_VOID_RETURN;
}
/*
Open a (new) log file.
SYNOPSIS
open()
log_name The name of the log to open
log_type_arg The type of the log. E.g. LOG_NORMAL
new_name The new name for the logfile. This is only needed
when the method is used to open the binlog file.
io_cache_type_arg The type of the IO_CACHE to use for this log file
DESCRIPTION
Open the logfile, init IO_CACHE and write startup messages
(in case of general and slow query logs).
RETURN VALUES
0 ok
1 error
*/
bool MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg,
const char *new_name, enum cache_type io_cache_type_arg)
{
char buff[FN_REFLEN];
File file= -1;
int open_flags= O_CREAT | O_BINARY;
DBUG_ENTER("MYSQL_LOG::open");
DBUG_PRINT("enter", ("log_type: %d", (int) log_type_arg));
write_error= 0;
init(log_type_arg, io_cache_type_arg);
if (!(name= my_strdup(log_name, MYF(MY_WME))))
{
name= (char *)log_name; // for the error message
goto err;
}
if (new_name)
strmov(log_file_name, new_name);
else if (generate_new_name(log_file_name, name))
goto err;
if (io_cache_type == SEQ_READ_APPEND)
open_flags |= O_RDWR | O_APPEND;
else
open_flags |= O_WRONLY | (log_type == LOG_BIN ? 0 : O_APPEND);
db[0]= 0;
if ((file= my_open(log_file_name, open_flags,
MYF(MY_WME | ME_WAITTANG))) < 0 ||
init_io_cache(&log_file, file, IO_SIZE, io_cache_type,
my_tell(file, MYF(MY_WME)), 0,
MYF(MY_WME | MY_NABP |
((log_type == LOG_BIN) ? MY_WAIT_IF_FULL : 0))))
goto err;
switch (log_type) {
case LOG_NORMAL:
{
char *end;
int len=my_snprintf(buff, sizeof(buff), "%s, Version: %s. "
#ifdef EMBEDDED_LIBRARY
"embedded library\n", my_progname, server_version
#elif __NT__
"started with:\nTCP Port: %d, Named Pipe: %s\n",
my_progname, server_version, mysqld_port,
mysqld_unix_port
#else
"started with:\nTcp port: %d Unix socket: %s\n",
my_progname, server_version, mysqld_port,
mysqld_unix_port
#endif
);
end= strnmov(buff + len, "Time Id Command Argument\n",
sizeof(buff) - len);
if (my_b_write(&log_file, (byte*) buff, (uint) (end-buff)) ||
flush_io_cache(&log_file))
goto err;
break;
}
case LOG_CLOSED: // Impossible
case LOG_TO_BE_OPENED:
DBUG_ASSERT(1);
break;
}
DBUG_RETURN(0);
err:
sql_print_error("Could not use %s for logging (error %d). \
Turning logging off for the whole duration of the MySQL server process. \
To turn it on again: fix the cause, \
shutdown the MySQL server and restart it.", name, errno);
if (file >= 0)
my_close(file, MYF(0));
end_io_cache(&log_file);
safeFree(name);
log_type= LOG_CLOSED;
DBUG_RETURN(1);
}
MYSQL_LOG::MYSQL_LOG() MYSQL_LOG::MYSQL_LOG()
:bytes_written(0), last_time(0), query_start(0), name(0), : name(0), log_type(LOG_CLOSED), write_error(FALSE),
prepared_xids(0), log_type(LOG_CLOSED), file_id(1), open_count(1), inited(FALSE), last_time(0)
write_error(FALSE), inited(FALSE), need_start_event(TRUE),
m_table_map_version(0),
description_event_for_exec(0), description_event_for_queue(0)
{ {
/* /*
We don't want to initialize LOCK_Log here as such initialization depends on We don't want to initialize LOCK_Log here as such initialization depends on
...@@ -1395,9 +1507,54 @@ MYSQL_LOG::MYSQL_LOG() ...@@ -1395,9 +1507,54 @@ MYSQL_LOG::MYSQL_LOG()
called only in main(). Doing initialization here would make it happen called only in main(). Doing initialization here would make it happen
before main(). before main().
*/ */
index_file_name[0] = 0; bzero((char*) &log_file, sizeof(log_file));
bzero((char*) &log_file,sizeof(log_file)); }
bzero((char*) &index_file, sizeof(index_file));
void MYSQL_LOG::init_pthread_objects()
{
DBUG_ASSERT(inited == 0);
inited= 1;
(void) pthread_mutex_init(&LOCK_log, MY_MUTEX_INIT_SLOW);
}
/*
Close the log file
SYNOPSIS
close()
exiting Bitmask. For the slow and general logs the only used bit is
LOG_CLOSE_TO_BE_OPENED. This is used if we intend to call
open at once after close.
NOTES
One can do an open on the object at once after doing a close.
The internal structures are not freed until cleanup() is called
*/
void MYSQL_LOG::close(uint exiting)
{ // One can't set log_type here!
DBUG_ENTER("MYSQL_LOG::close");
DBUG_PRINT("enter",("exiting: %d", (int) exiting));
if (log_type != LOG_CLOSED && log_type != LOG_TO_BE_OPENED)
{
end_io_cache(&log_file);
if (my_sync(log_file.file, MYF(MY_WME)) && ! write_error)
{
write_error= 1;
sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno);
}
if (my_close(log_file.file, MYF(MY_WME)) && ! write_error)
{
write_error= 1;
sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno);
}
}
log_type= (exiting & LOG_CLOSE_TO_BE_OPENED) ? LOG_TO_BE_OPENED : LOG_CLOSED;
safeFree(name);
DBUG_VOID_RETURN;
} }
/* this is called only once */ /* this is called only once */
...@@ -1408,17 +1565,57 @@ void MYSQL_LOG::cleanup() ...@@ -1408,17 +1565,57 @@ void MYSQL_LOG::cleanup()
if (inited) if (inited)
{ {
inited= 0; inited= 0;
close(LOG_CLOSE_INDEX|LOG_CLOSE_STOP_EVENT);
delete description_event_for_queue;
delete description_event_for_exec;
(void) pthread_mutex_destroy(&LOCK_log); (void) pthread_mutex_destroy(&LOCK_log);
(void) pthread_mutex_destroy(&LOCK_index); close(0);
(void) pthread_cond_destroy(&update_cond);
} }
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
/*
Reopen the log file
SYNOPSIS
reopen_file()
DESCRIPTION
Reopen the log file. The method is used during FLUSH LOGS
and locks LOCK_log mutex
*/
void MYSQL_LOG::reopen_file()
{
enum_log_type save_log_type;
char *save_name;
DBUG_ENTER("MYSQL_LOG::reopen_file");
if (!is_open())
{
DBUG_PRINT("info",("log is closed"));
DBUG_VOID_RETURN;
}
pthread_mutex_lock(&LOCK_log);
save_name= name;
save_log_type= log_type;
name= 0; // Don't free name
close(LOG_CLOSE_TO_BE_OPENED);
/*
Note that at this point, log_type != LOG_CLOSED (important for is_open()).
*/
open(save_name, save_log_type, 0, io_cache_type);
my_free(save_name, MYF(0));
pthread_mutex_unlock(&LOCK_log);
DBUG_VOID_RETURN;
}
int MYSQL_LOG::generate_new_name(char *new_name, const char *log_name) int MYSQL_LOG::generate_new_name(char *new_name, const char *log_name)
{ {
fn_format(new_name,log_name,mysql_data_home,"",4); fn_format(new_name,log_name,mysql_data_home,"",4);
...@@ -1437,33 +1634,245 @@ int MYSQL_LOG::generate_new_name(char *new_name, const char *log_name) ...@@ -1437,33 +1634,245 @@ int MYSQL_LOG::generate_new_name(char *new_name, const char *log_name)
} }
void MYSQL_LOG::init(enum_log_type log_type_arg, /*
enum cache_type io_cache_type_arg, Write a command to traditional general log file
bool no_auto_events_arg,
ulong max_size_arg) SYNOPSIS
write()
event_time command start timestamp
user_host the pointer to the string with user@host info
user_host_len length of the user_host string. this is computed once
and passed to all general log event handlers
thread_id Id of the thread, issued a query
command_type the type of the command being logged
command_type_len the length of the string above
sql_text the very text of the query being executed
sql_text_len the length of sql_text string
DESCRIPTION
Log given command to to normal (not rotable) log file
RETURN
FASE - OK
TRUE - error occured
*/
bool MYSQL_GENERAL_LOG::write(time_t event_time, const char *user_host,
uint user_host_len, int thread_id,
const char *command_type, uint command_type_len,
const char *sql_text, uint sql_text_len)
{ {
DBUG_ENTER("MYSQL_LOG::init"); char buff[32];
log_type = log_type_arg; uint length= 0;
io_cache_type = io_cache_type_arg; char time_buff[MAX_TIME_SIZE];
no_auto_events = no_auto_events_arg; struct tm start;
max_size=max_size_arg; uint time_buff_len= 0;
DBUG_PRINT("info",("log_type: %d max_size: %lu", log_type, max_size));
DBUG_VOID_RETURN; /* Test if someone closed between the is_open test and lock */
if (is_open())
{
/* Note that my_b_write() assumes it knows the length for this */
if (event_time != last_time)
{
last_time= event_time;
localtime_r(&event_time, &start);
time_buff_len= my_snprintf(time_buff, MAX_TIME_SIZE,
"%02d%02d%02d %2d:%02d:%02d",
start.tm_year % 100, start.tm_mon + 1,
start.tm_mday, start.tm_hour,
start.tm_min, start.tm_sec);
if (my_b_write(&log_file, (byte*) &time_buff, time_buff_len))
goto err;
}
else
if (my_b_write(&log_file, (byte*) "\t\t" ,2) < 0)
goto err;
/* command_type, thread_id */
length= my_snprintf(buff, 32, "%5ld ", thread_id);
if (my_b_write(&log_file, (byte*) buff, length))
goto err;
if (my_b_write(&log_file, (byte*) command_type, command_type_len))
goto err;
if (my_b_write(&log_file, (byte*) "\t", 1))
goto err;
/* sql_text */
if (my_b_write(&log_file, (byte*) sql_text, sql_text_len))
goto err;
if (my_b_write(&log_file, (byte*) "\n", 1) ||
flush_io_cache(&log_file))
goto err;
}
return FALSE;
err:
if (!write_error)
{
write_error= 1;
sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno);
}
return TRUE;
} }
void MYSQL_LOG::init_pthread_objects() /*
Log a query to the traditional slow log file
SYNOPSIS
write()
thd THD of the query
current_time current timestamp
query_start_arg command start timestamp
user_host the pointer to the string with user@host info
user_host_len length of the user_host string. this is computed once
and passed to all general log event handlers
query_time Amount of time the query took to execute (in seconds)
lock_time Amount of time the query was locked (in seconds)
is_command The flag, which determines, whether the sql_text is a
query or an administrator command.
sql_text the very text of the query or administrator command
processed
sql_text_len the length of sql_text string
DESCRIPTION
Log a query to the slow log file.
RETURN
FALSE - OK
TRUE - error occured
*/
bool MYSQL_SLOW_LOG::write(THD *thd, time_t current_time,
time_t query_start_arg, const char *user_host,
uint user_host_len, longlong query_time,
longlong lock_time, bool is_command,
const char *sql_text, uint sql_text_len)
{ {
DBUG_ASSERT(inited == 0); bool error= 0;
inited= 1; DBUG_ENTER("MYSQL_SLOW_LOG::write");
(void) pthread_mutex_init(&LOCK_log,MY_MUTEX_INIT_SLOW);
(void) pthread_mutex_init(&LOCK_index, MY_MUTEX_INIT_SLOW); if (!is_open())
(void) pthread_cond_init(&update_cond, 0); DBUG_RETURN(0);
if (is_open())
{ // Safety agains reopen
int tmp_errno= 0;
char buff[80], *end;
uint buff_len;
end= buff;
if (!(specialflag & SPECIAL_SHORT_LOG_FORMAT))
{
Security_context *sctx= thd->security_ctx;
if (current_time != last_time)
{
last_time= current_time;
struct tm start;
localtime_r(&current_time, &start);
buff_len= my_snprintf(buff, sizeof buff,
"# Time: %02d%02d%02d %2d:%02d:%02d\n",
start.tm_year % 100, start.tm_mon + 1,
start.tm_mday, start.tm_hour,
start.tm_min, start.tm_sec);
/* Note that my_b_write() assumes it knows the length for this */
if (my_b_write(&log_file, (byte*) buff, buff_len))
tmp_errno= errno;
}
if (my_b_printf(&log_file, "# User@Host: ", sizeof("# User@Host: ") - 1)
!= sizeof("# User@Host: ") - 1)
tmp_errno= errno;
if (my_b_printf(&log_file, user_host, user_host_len) != user_host_len)
tmp_errno= errno;
if (my_b_write(&log_file, (byte*) "\n", 1))
tmp_errno= errno;
}
/* For slow query log */
if (my_b_printf(&log_file,
"# Query_time: %lu Lock_time: %lu"
" Rows_sent: %lu Rows_examined: %lu\n",
(ulong) query_time, (ulong) lock_time,
(ulong) thd->sent_row_count,
(ulong) thd->examined_row_count) == (uint) -1)
tmp_errno= errno;
if (thd->db && strcmp(thd->db, db))
{ // Database changed
if (my_b_printf(&log_file,"use %s;\n",thd->db) == (uint) -1)
tmp_errno= errno;
strmov(db,thd->db);
}
if (thd->last_insert_id_used)
{
end=strmov(end, ",last_insert_id=");
end=longlong10_to_str((longlong) thd->current_insert_id, end, -10);
}
// Save value if we do an insert.
if (thd->insert_id_used)
{
if (!(specialflag & SPECIAL_SHORT_LOG_FORMAT))
{
end=strmov(end,",insert_id=");
end=longlong10_to_str((longlong) thd->last_insert_id, end, -10);
}
}
/*
This info used to show up randomly, depending on whether the query
checked the query start time or not. now we always write current
timestamp to the slow log
*/
end= strmov(end, ",timestamp=");
end= int10_to_str((long) current_time, end, 10);
if (end != buff)
{
*end++=';';
*end='\n';
if (my_b_write(&log_file, (byte*) "SET ", 4) ||
my_b_write(&log_file, (byte*) buff + 1, (uint) (end-buff)))
tmp_errno= errno;
}
if (is_command)
{
end= strxmov(buff, "# administrator command: ", NullS);
buff_len= (ulong) (end - buff);
my_b_write(&log_file, (byte*) buff, buff_len);
}
if (my_b_write(&log_file, (byte*) sql_text, sql_text_len) ||
my_b_write(&log_file, (byte*) ";\n",2) ||
flush_io_cache(&log_file))
tmp_errno= errno;
if (tmp_errno)
{
error= 1;
if (! write_error)
{
write_error= 1;
sql_print_error(ER(ER_ERROR_ON_WRITE), name, error);
}
}
}
DBUG_RETURN(error);
} }
const char *MYSQL_LOG::generate_name(const char *log_name, const char *MYSQL_LOG::generate_name(const char *log_name,
const char *suffix, const char *suffix,
bool strip_ext, char *buff) bool strip_ext, char *buff)
{ {
if (!log_name || !log_name[0]) if (!log_name || !log_name[0])
{ {
...@@ -1471,22 +1880,78 @@ const char *MYSQL_LOG::generate_name(const char *log_name, ...@@ -1471,22 +1880,78 @@ const char *MYSQL_LOG::generate_name(const char *log_name,
TODO: The following should be using fn_format(); We just need to TODO: The following should be using fn_format(); We just need to
first change fn_format() to cut the file name if it's too long. first change fn_format() to cut the file name if it's too long.
*/ */
strmake(buff,glob_hostname,FN_REFLEN-5); strmake(buff, glob_hostname, FN_REFLEN - 5);
strmov(fn_ext(buff),suffix); strmov(fn_ext(buff), suffix);
return (const char *)buff; return (const char *)buff;
} }
// get rid of extension if the log is binary to avoid problems // get rid of extension if the log is binary to avoid problems
if (strip_ext) if (strip_ext)
{ {
char *p = fn_ext(log_name); char *p= fn_ext(log_name);
uint length=(uint) (p-log_name); uint length= (uint) (p - log_name);
strmake(buff,log_name,min(length,FN_REFLEN)); strmake(buff, log_name, min(length, FN_REFLEN));
return (const char*)buff; return (const char*)buff;
} }
return log_name; return log_name;
} }
bool MYSQL_LOG::open_index_file(const char *index_file_name_arg,
MYSQL_BIN_LOG::MYSQL_BIN_LOG()
:bytes_written(0), prepared_xids(0), file_id(1), open_count(1),
need_start_event(TRUE), m_table_map_version(0),
description_event_for_exec(0), description_event_for_queue(0)
{
/*
We don't want to initialize locks here as such initialization depends on
safe_mutex (when using safe_mutex) which depends on MY_INIT(), which is
called only in main(). Doing initialization here would make it happen
before main().
*/
index_file_name[0] = 0;
bzero((char*) &index_file, sizeof(index_file));
}
/* this is called only once */
void MYSQL_BIN_LOG::cleanup()
{
DBUG_ENTER("cleanup");
if (inited)
{
inited= 0;
close(LOG_CLOSE_INDEX|LOG_CLOSE_STOP_EVENT);
delete description_event_for_queue;
delete description_event_for_exec;
(void) pthread_mutex_destroy(&LOCK_log);
(void) pthread_mutex_destroy(&LOCK_index);
(void) pthread_cond_destroy(&update_cond);
}
DBUG_VOID_RETURN;
}
/* Init binlog-specific vars */
void MYSQL_BIN_LOG::init(bool no_auto_events_arg, ulong max_size_arg)
{
DBUG_ENTER("MYSQL_BIN_LOG::init");
no_auto_events= no_auto_events_arg;
max_size= max_size_arg;
DBUG_PRINT("info",("max_size: %lu", max_size));
DBUG_VOID_RETURN;
}
void MYSQL_BIN_LOG::init_pthread_objects()
{
DBUG_ASSERT(inited == 0);
inited= 1;
(void) pthread_mutex_init(&LOCK_log, MY_MUTEX_INIT_SLOW);
(void) pthread_mutex_init(&LOCK_index, MY_MUTEX_INIT_SLOW);
(void) pthread_cond_init(&update_cond, 0);
}
bool MYSQL_BIN_LOG::open_index_file(const char *index_file_name_arg,
const char *log_name) const char *log_name)
{ {
File index_file_nr= -1; File index_file_nr= -1;
...@@ -1523,10 +1988,10 @@ bool MYSQL_LOG::open_index_file(const char *index_file_name_arg, ...@@ -1523,10 +1988,10 @@ bool MYSQL_LOG::open_index_file(const char *index_file_name_arg,
/* /*
Open a (new) log file. Open a (new) binlog file.
DESCRIPTION DESCRIPTION
- If binary logs, also open the index file and register the new - Open the log file and the index file. Register the new
file name in it file name in it
- When calling this when the file is in use, you must have a locks - When calling this when the file is in use, you must have a locks
on LOCK_log and LOCK_index. on LOCK_log and LOCK_index.
...@@ -1536,94 +2001,33 @@ bool MYSQL_LOG::open_index_file(const char *index_file_name_arg, ...@@ -1536,94 +2001,33 @@ bool MYSQL_LOG::open_index_file(const char *index_file_name_arg,
1 error 1 error
*/ */
bool MYSQL_LOG::open(const char *log_name, bool MYSQL_BIN_LOG::open(const char *log_name,
enum_log_type log_type_arg, enum_log_type log_type_arg,
const char *new_name, const char *new_name,
enum cache_type io_cache_type_arg, enum cache_type io_cache_type_arg,
bool no_auto_events_arg, bool no_auto_events_arg,
ulong max_size_arg, ulong max_size_arg,
bool null_created_arg) bool null_created_arg)
{ {
char buff[FN_REFLEN]; char buff[FN_REFLEN];
File file= -1; File file= -1;
int open_flags = O_CREAT | O_BINARY; int open_flags = O_CREAT | O_BINARY;
DBUG_ENTER("MYSQL_LOG::open"); DBUG_ENTER("MYSQL_BIN_LOG::open");
DBUG_PRINT("enter",("log_type: %d",(int) log_type_arg)); DBUG_PRINT("enter",("log_type: %d",(int) log_type_arg));
last_time=query_start=0; last_time= 0;
write_error=0; write_error=0;
init(log_type_arg,io_cache_type_arg,no_auto_events_arg,max_size_arg); /* open the main log file */
if (MYSQL_LOG::open(log_name, log_type_arg, new_name, io_cache_type_arg))
DBUG_RETURN(1); /* all warnings issued */
if (!(name=my_strdup(log_name,MYF(MY_WME)))) init(no_auto_events_arg, max_size_arg);
{
name= (char *)log_name; // for the error message
goto err;
}
if (new_name)
strmov(log_file_name,new_name);
else if (generate_new_name(log_file_name, name))
goto err;
if (io_cache_type == SEQ_READ_APPEND)
open_flags |= O_RDWR | O_APPEND;
else
open_flags |= O_WRONLY | (log_type == LOG_BIN ? 0 : O_APPEND);
db[0]=0;
open_count++; open_count++;
if ((file=my_open(log_file_name,open_flags,
MYF(MY_WME | ME_WAITTANG))) < 0 ||
init_io_cache(&log_file, file, IO_SIZE, io_cache_type,
my_tell(file,MYF(MY_WME)), 0,
MYF(MY_WME | MY_NABP |
((log_type == LOG_BIN) ? MY_WAIT_IF_FULL : 0))))
goto err;
switch (log_type) { DBUG_ASSERT(log_type == LOG_BIN);
case LOG_NORMAL:
{
char *end;
int len=my_snprintf(buff, sizeof(buff), "%s, Version: %s. "
#ifdef EMBEDDED_LIBRARY
"embedded library\n", my_progname, server_version
#elif __NT__
"started with:\nTCP Port: %d, Named Pipe: %s\n",
my_progname, server_version, mysqld_port, mysqld_unix_port
#else
"started with:\nTcp port: %d Unix socket: %s\n",
my_progname,server_version,mysqld_port,mysqld_unix_port
#endif
);
end=strnmov(buff+len,"Time Id Command Argument\n",
sizeof(buff)-len);
if (my_b_write(&log_file, (byte*) buff,(uint) (end-buff)) ||
flush_io_cache(&log_file))
goto err;
break;
}
case LOG_NEW:
{
uint len;
time_t skr=time(NULL);
struct tm tm_tmp;
localtime_r(&skr,&tm_tmp);
len= my_snprintf(buff,sizeof(buff),
"# %s, Version: %s at %02d%02d%02d %2d:%02d:%02d\n",
my_progname,server_version,
tm_tmp.tm_year % 100,
tm_tmp.tm_mon+1,
tm_tmp.tm_mday,
tm_tmp.tm_hour,
tm_tmp.tm_min,
tm_tmp.tm_sec);
if (my_b_write(&log_file, (byte*) buff, len) ||
flush_io_cache(&log_file))
goto err;
break;
}
case LOG_BIN:
{ {
bool write_file_name_to_index_file=0; bool write_file_name_to_index_file=0;
...@@ -1714,12 +2118,6 @@ bool MYSQL_LOG::open(const char *log_name, ...@@ -1714,12 +2118,6 @@ bool MYSQL_LOG::open(const char *log_name,
my_sync(index_file.file, MYF(MY_WME))) my_sync(index_file.file, MYF(MY_WME)))
goto err; goto err;
} }
break;
}
case LOG_CLOSED: // Impossible
case LOG_TO_BE_OPENED:
DBUG_ASSERT(1);
break;
} }
DBUG_RETURN(0); DBUG_RETURN(0);
...@@ -1738,7 +2136,7 @@ shutdown the MySQL server and restart it.", name, errno); ...@@ -1738,7 +2136,7 @@ shutdown the MySQL server and restart it.", name, errno);
} }
int MYSQL_LOG::get_current_log(LOG_INFO* linfo) int MYSQL_BIN_LOG::get_current_log(LOG_INFO* linfo)
{ {
pthread_mutex_lock(&LOCK_log); pthread_mutex_lock(&LOCK_log);
strmake(linfo->log_file_name, log_file_name, sizeof(linfo->log_file_name)-1); strmake(linfo->log_file_name, log_file_name, sizeof(linfo->log_file_name)-1);
...@@ -1825,7 +2223,7 @@ static bool copy_up_file_and_fill(IO_CACHE *index_file, my_off_t offset) ...@@ -1825,7 +2223,7 @@ static bool copy_up_file_and_fill(IO_CACHE *index_file, my_off_t offset)
LOG_INFO_IO Got IO error while reading file LOG_INFO_IO Got IO error while reading file
*/ */
int MYSQL_LOG::find_log_pos(LOG_INFO *linfo, const char *log_name, int MYSQL_BIN_LOG::find_log_pos(LOG_INFO *linfo, const char *log_name,
bool need_lock) bool need_lock)
{ {
int error= 0; int error= 0;
...@@ -1899,7 +2297,7 @@ int MYSQL_LOG::find_log_pos(LOG_INFO *linfo, const char *log_name, ...@@ -1899,7 +2297,7 @@ int MYSQL_LOG::find_log_pos(LOG_INFO *linfo, const char *log_name,
LOG_INFO_IO Got IO error while reading file LOG_INFO_IO Got IO error while reading file
*/ */
int MYSQL_LOG::find_next_log(LOG_INFO* linfo, bool need_lock) int MYSQL_BIN_LOG::find_next_log(LOG_INFO* linfo, bool need_lock)
{ {
int error= 0; int error= 0;
uint length; uint length;
...@@ -1947,7 +2345,7 @@ int MYSQL_LOG::find_next_log(LOG_INFO* linfo, bool need_lock) ...@@ -1947,7 +2345,7 @@ int MYSQL_LOG::find_next_log(LOG_INFO* linfo, bool need_lock)
1 error 1 error
*/ */
bool MYSQL_LOG::reset_logs(THD* thd) bool MYSQL_BIN_LOG::reset_logs(THD* thd)
{ {
LOG_INFO linfo; LOG_INFO linfo;
bool error=0; bool error=0;
...@@ -2047,7 +2445,7 @@ bool MYSQL_LOG::reset_logs(THD* thd) ...@@ -2047,7 +2445,7 @@ bool MYSQL_LOG::reset_logs(THD* thd)
#ifdef HAVE_REPLICATION #ifdef HAVE_REPLICATION
int MYSQL_LOG::purge_first_log(struct st_relay_log_info* rli, bool included) int MYSQL_BIN_LOG::purge_first_log(struct st_relay_log_info* rli, bool included)
{ {
int error; int error;
DBUG_ENTER("purge_first_log"); DBUG_ENTER("purge_first_log");
...@@ -2123,7 +2521,7 @@ int MYSQL_LOG::purge_first_log(struct st_relay_log_info* rli, bool included) ...@@ -2123,7 +2521,7 @@ int MYSQL_LOG::purge_first_log(struct st_relay_log_info* rli, bool included)
Update log index_file Update log index_file
*/ */
int MYSQL_LOG::update_log_index(LOG_INFO* log_info, bool need_update_threads) int MYSQL_BIN_LOG::update_log_index(LOG_INFO* log_info, bool need_update_threads)
{ {
if (copy_up_file_and_fill(&index_file, log_info->index_file_start_offset)) if (copy_up_file_and_fill(&index_file, log_info->index_file_start_offset))
return LOG_INFO_IO; return LOG_INFO_IO;
...@@ -2156,7 +2554,7 @@ int MYSQL_LOG::update_log_index(LOG_INFO* log_info, bool need_update_threads) ...@@ -2156,7 +2554,7 @@ int MYSQL_LOG::update_log_index(LOG_INFO* log_info, bool need_update_threads)
LOG_INFO_EOF to_log not found LOG_INFO_EOF to_log not found
*/ */
int MYSQL_LOG::purge_logs(const char *to_log, int MYSQL_BIN_LOG::purge_logs(const char *to_log,
bool included, bool included,
bool need_mutex, bool need_mutex,
bool need_update_threads, bool need_update_threads,
...@@ -2242,7 +2640,7 @@ int MYSQL_LOG::purge_logs(const char *to_log, ...@@ -2242,7 +2640,7 @@ int MYSQL_LOG::purge_logs(const char *to_log,
LOG_INFO_PURGE_NO_ROTATE Binary file that can't be rotated LOG_INFO_PURGE_NO_ROTATE Binary file that can't be rotated
*/ */
int MYSQL_LOG::purge_logs_before_date(time_t purge_time) int MYSQL_BIN_LOG::purge_logs_before_date(time_t purge_time)
{ {
int error; int error;
LOG_INFO log_info; LOG_INFO log_info;
...@@ -2301,7 +2699,7 @@ int MYSQL_LOG::purge_logs_before_date(time_t purge_time) ...@@ -2301,7 +2699,7 @@ int MYSQL_LOG::purge_logs_before_date(time_t purge_time)
If file name will be longer then FN_REFLEN it will be truncated If file name will be longer then FN_REFLEN it will be truncated
*/ */
void MYSQL_LOG::make_log_name(char* buf, const char* log_ident) void MYSQL_BIN_LOG::make_log_name(char* buf, const char* log_ident)
{ {
uint dir_len = dirname_length(log_file_name); uint dir_len = dirname_length(log_file_name);
if (dir_len > FN_REFLEN) if (dir_len > FN_REFLEN)
...@@ -2315,29 +2713,49 @@ void MYSQL_LOG::make_log_name(char* buf, const char* log_ident) ...@@ -2315,29 +2713,49 @@ void MYSQL_LOG::make_log_name(char* buf, const char* log_ident)
Check if we are writing/reading to the given log file Check if we are writing/reading to the given log file
*/ */
bool MYSQL_LOG::is_active(const char *log_file_name_arg) bool MYSQL_BIN_LOG::is_active(const char *log_file_name_arg)
{ {
return !strcmp(log_file_name, log_file_name_arg); return !strcmp(log_file_name, log_file_name_arg);
} }
/*
Wrappers around new_file_impl to avoid using argument
to control locking. The argument 1) less readable 2) breaks
incapsulation 3) allows external access to the class without
a lock (which is not possible with private new_file_without_locking
method).
*/
void MYSQL_BIN_LOG::new_file()
{
new_file_impl(1);
}
void MYSQL_BIN_LOG::new_file_without_locking()
{
new_file_impl(0);
}
/* /*
Start writing to a new log file or reopen the old file Start writing to a new log file or reopen the old file
SYNOPSIS SYNOPSIS
new_file() new_file_impl()
need_lock Set to 1 if caller has not locked LOCK_log need_lock Set to 1 if caller has not locked LOCK_log
NOTE NOTE
The new file name is stored last in the index file The new file name is stored last in the index file
*/ */
void MYSQL_LOG::new_file(bool need_lock) void MYSQL_BIN_LOG::new_file_impl(bool need_lock)
{ {
char new_name[FN_REFLEN], *new_name_ptr, *old_name; char new_name[FN_REFLEN], *new_name_ptr, *old_name;
enum_log_type save_log_type; enum_log_type save_log_type;
DBUG_ENTER("MYSQL_LOG::new_file"); DBUG_ENTER("MYSQL_BIN_LOG::new_file_impl");
if (!is_open()) if (!is_open())
{ {
DBUG_PRINT("info",("log is closed")); DBUG_PRINT("info",("log is closed"));
...@@ -2433,11 +2851,11 @@ void MYSQL_LOG::new_file(bool need_lock) ...@@ -2433,11 +2851,11 @@ void MYSQL_LOG::new_file(bool need_lock)
} }
bool MYSQL_LOG::append(Log_event* ev) bool MYSQL_BIN_LOG::append(Log_event* ev)
{ {
bool error = 0; bool error = 0;
pthread_mutex_lock(&LOCK_log); pthread_mutex_lock(&LOCK_log);
DBUG_ENTER("MYSQL_LOG::append"); DBUG_ENTER("MYSQL_BIN_LOG::append");
DBUG_ASSERT(log_file.type == SEQ_READ_APPEND); DBUG_ASSERT(log_file.type == SEQ_READ_APPEND);
/* /*
...@@ -2452,7 +2870,7 @@ bool MYSQL_LOG::append(Log_event* ev) ...@@ -2452,7 +2870,7 @@ bool MYSQL_LOG::append(Log_event* ev)
bytes_written+= ev->data_written; bytes_written+= ev->data_written;
DBUG_PRINT("info",("max_size: %lu",max_size)); DBUG_PRINT("info",("max_size: %lu",max_size));
if ((uint) my_b_append_tell(&log_file) > max_size) if ((uint) my_b_append_tell(&log_file) > max_size)
new_file(0); new_file_without_locking();
err: err:
pthread_mutex_unlock(&LOCK_log); pthread_mutex_unlock(&LOCK_log);
...@@ -2461,10 +2879,10 @@ bool MYSQL_LOG::append(Log_event* ev) ...@@ -2461,10 +2879,10 @@ bool MYSQL_LOG::append(Log_event* ev)
} }
bool MYSQL_LOG::appendv(const char* buf, uint len,...) bool MYSQL_BIN_LOG::appendv(const char* buf, uint len,...)
{ {
bool error= 0; bool error= 0;
DBUG_ENTER("MYSQL_LOG::appendv"); DBUG_ENTER("MYSQL_BIN_LOG::appendv");
va_list(args); va_list(args);
va_start(args,len); va_start(args,len);
...@@ -2482,7 +2900,7 @@ bool MYSQL_LOG::appendv(const char* buf, uint len,...) ...@@ -2482,7 +2900,7 @@ bool MYSQL_LOG::appendv(const char* buf, uint len,...)
} while ((buf=va_arg(args,const char*)) && (len=va_arg(args,uint))); } while ((buf=va_arg(args,const char*)) && (len=va_arg(args,uint)));
DBUG_PRINT("info",("max_size: %lu",max_size)); DBUG_PRINT("info",("max_size: %lu",max_size));
if ((uint) my_b_append_tell(&log_file) > max_size) if ((uint) my_b_append_tell(&log_file) > max_size)
new_file(0); new_file_without_locking();
err: err:
if (!error) if (!error)
...@@ -2491,99 +2909,7 @@ bool MYSQL_LOG::appendv(const char* buf, uint len,...) ...@@ -2491,99 +2909,7 @@ bool MYSQL_LOG::appendv(const char* buf, uint len,...)
} }
/* bool MYSQL_BIN_LOG::flush_and_sync()
Write a command to traditional general log file
SYNOPSIS
write()
event_time command start timestamp
user_host the pointer to the string with user@host info
user_host_len length of the user_host string. this is computed once
and passed to all general log event handlers
thread_id Id of the thread, issued a query
command_type the type of the command being logged
command_type_len the length of the string above
sql_text the very text of the query being executed
sql_text_len the length of sql_text string
DESCRIPTION
Log given command to to normal (not rotable) log file
RETURN
FASE - OK
TRUE - error occured
*/
bool MYSQL_LOG::write(time_t event_time, const char *user_host,
uint user_host_len, int thread_id,
const char *command_type, uint command_type_len,
const char *sql_text, uint sql_text_len)
{
char buff[32];
uint length= 0;
char time_buff[MAX_TIME_SIZE];
struct tm start;
uint time_buff_len= 0;
/* Test if someone closed between the is_open test and lock */
if (is_open())
{
/* Note that my_b_write() assumes it knows the length for this */
if (event_time != last_time)
{
last_time= event_time;
localtime_r(&event_time, &start);
time_buff_len= my_snprintf(time_buff, MAX_TIME_SIZE,
"%02d%02d%02d %2d:%02d:%02d",
start.tm_year % 100, start.tm_mon + 1,
start.tm_mday, start.tm_hour,
start.tm_min, start.tm_sec);
if (my_b_write(&log_file, (byte*) &time_buff, time_buff_len))
goto err;
}
else
if (my_b_write(&log_file, (byte*) "\t\t" ,2) < 0)
goto err;
/* command_type, thread_id */
length= my_snprintf(buff, 32, "%5ld ", thread_id);
if (my_b_write(&log_file, (byte*) buff, length))
goto err;
if (my_b_write(&log_file, (byte*) command_type, command_type_len))
goto err;
if (my_b_write(&log_file, (byte*) "\t", 1))
goto err;
/* sql_text */
if (my_b_write(&log_file, (byte*) sql_text, sql_text_len))
goto err;
if (my_b_write(&log_file, (byte*) "\n", 1) ||
flush_io_cache(&log_file))
goto err;
}
return FALSE;
err:
if (!write_error)
{
write_error= 1;
sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno);
}
return TRUE;
}
bool MYSQL_LOG::flush_and_sync()
{ {
int err=0, fd=log_file.file; int err=0, fd=log_file.file;
safe_mutex_assert_owner(&LOCK_log); safe_mutex_assert_owner(&LOCK_log);
...@@ -2597,7 +2923,7 @@ bool MYSQL_LOG::flush_and_sync() ...@@ -2597,7 +2923,7 @@ bool MYSQL_LOG::flush_and_sync()
return err; return err;
} }
void MYSQL_LOG::start_union_events(THD *thd) void MYSQL_BIN_LOG::start_union_events(THD *thd)
{ {
DBUG_ASSERT(!thd->binlog_evt_union.do_union); DBUG_ASSERT(!thd->binlog_evt_union.do_union);
thd->binlog_evt_union.do_union= TRUE; thd->binlog_evt_union.do_union= TRUE;
...@@ -2606,13 +2932,13 @@ void MYSQL_LOG::start_union_events(THD *thd) ...@@ -2606,13 +2932,13 @@ void MYSQL_LOG::start_union_events(THD *thd)
thd->binlog_evt_union.first_query_id= thd->query_id; thd->binlog_evt_union.first_query_id= thd->query_id;
} }
void MYSQL_LOG::stop_union_events(THD *thd) void MYSQL_BIN_LOG::stop_union_events(THD *thd)
{ {
DBUG_ASSERT(thd->binlog_evt_union.do_union); DBUG_ASSERT(thd->binlog_evt_union.do_union);
thd->binlog_evt_union.do_union= FALSE; thd->binlog_evt_union.do_union= FALSE;
} }
bool MYSQL_LOG::is_query_in_union(THD *thd, query_id_t query_id_param) bool MYSQL_BIN_LOG::is_query_in_union(THD *thd, query_id_t query_id_param)
{ {
return (thd->binlog_evt_union.do_union && return (thd->binlog_evt_union.do_union &&
query_id_param >= thd->binlog_evt_union.first_query_id); query_id_param >= thd->binlog_evt_union.first_query_id);
...@@ -2716,9 +3042,10 @@ THD::binlog_set_pending_rows_event(Rows_log_event* ev) ...@@ -2716,9 +3042,10 @@ THD::binlog_set_pending_rows_event(Rows_log_event* ev)
(either cached binlog if transaction, or disk binlog). Sets a new pending (either cached binlog if transaction, or disk binlog). Sets a new pending
event. event.
*/ */
int MYSQL_LOG::flush_and_set_pending_rows_event(THD *thd, Rows_log_event* event) int MYSQL_BIN_LOG::
flush_and_set_pending_rows_event(THD *thd, Rows_log_event* event)
{ {
DBUG_ENTER("MYSQL_LOG::flush_and_set_pending_rows_event(event)"); DBUG_ENTER("MYSQL_BIN_LOG::flush_and_set_pending_rows_event(event)");
DBUG_ASSERT(thd->current_stmt_binlog_row_based && mysql_bin_log.is_open()); DBUG_ASSERT(thd->current_stmt_binlog_row_based && mysql_bin_log.is_open());
DBUG_PRINT("enter", ("event=%p", event)); DBUG_PRINT("enter", ("event=%p", event));
...@@ -2801,11 +3128,11 @@ int MYSQL_LOG::flush_and_set_pending_rows_event(THD *thd, Rows_log_event* event) ...@@ -2801,11 +3128,11 @@ int MYSQL_LOG::flush_and_set_pending_rows_event(THD *thd, Rows_log_event* event)
Write an event to the binary log Write an event to the binary log
*/ */
bool MYSQL_LOG::write(Log_event *event_info) bool MYSQL_BIN_LOG::write(Log_event *event_info)
{ {
THD *thd= event_info->thd; THD *thd= event_info->thd;
bool error= 1; bool error= 1;
DBUG_ENTER("MYSQL_LOG::write(Log_event *)"); DBUG_ENTER("MYSQL_BIN_LOG::write(Log_event *)");
if (thd->binlog_evt_union.do_union) if (thd->binlog_evt_union.do_union)
{ {
...@@ -3014,14 +3341,14 @@ bool general_log_print(THD *thd, enum enum_server_command command, ...@@ -3014,14 +3341,14 @@ bool general_log_print(THD *thd, enum enum_server_command command,
return error; return error;
} }
void MYSQL_LOG::rotate_and_purge(uint flags) void MYSQL_BIN_LOG::rotate_and_purge(uint flags)
{ {
if (!(flags & RP_LOCK_LOG_IS_ALREADY_LOCKED)) if (!(flags & RP_LOCK_LOG_IS_ALREADY_LOCKED))
pthread_mutex_lock(&LOCK_log); pthread_mutex_lock(&LOCK_log);
if ((flags & RP_FORCE_ROTATE) || if ((flags & RP_FORCE_ROTATE) ||
(my_b_tell(&log_file) >= (my_off_t) max_size)) (my_b_tell(&log_file) >= (my_off_t) max_size))
{ {
new_file(0); new_file_without_locking();
#ifdef HAVE_REPLICATION #ifdef HAVE_REPLICATION
if (expire_logs_days) if (expire_logs_days)
{ {
...@@ -3035,7 +3362,7 @@ void MYSQL_LOG::rotate_and_purge(uint flags) ...@@ -3035,7 +3362,7 @@ void MYSQL_LOG::rotate_and_purge(uint flags)
pthread_mutex_unlock(&LOCK_log); pthread_mutex_unlock(&LOCK_log);
} }
uint MYSQL_LOG::next_file_id() uint MYSQL_BIN_LOG::next_file_id()
{ {
uint res; uint res;
pthread_mutex_lock(&LOCK_log); pthread_mutex_lock(&LOCK_log);
...@@ -3066,9 +3393,9 @@ uint MYSQL_LOG::next_file_id() ...@@ -3066,9 +3393,9 @@ uint MYSQL_LOG::next_file_id()
that the same updates are run on the slave. that the same updates are run on the slave.
*/ */
bool MYSQL_LOG::write(THD *thd, IO_CACHE *cache, Log_event *commit_event) bool MYSQL_BIN_LOG::write(THD *thd, IO_CACHE *cache, Log_event *commit_event)
{ {
DBUG_ENTER("MYSQL_LOG::write(THD *, IO_CACHE *, Log_event *)"); DBUG_ENTER("MYSQL_BIN_LOG::write(THD *, IO_CACHE *, Log_event *)");
VOID(pthread_mutex_lock(&LOCK_log)); VOID(pthread_mutex_lock(&LOCK_log));
if (likely(is_open())) // Should always be true if (likely(is_open())) // Should always be true
...@@ -3163,148 +3490,6 @@ bool MYSQL_LOG::write(THD *thd, IO_CACHE *cache, Log_event *commit_event) ...@@ -3163,148 +3490,6 @@ bool MYSQL_LOG::write(THD *thd, IO_CACHE *cache, Log_event *commit_event)
} }
/*
Log a query to the traditional slow log file
SYNOPSIS
write()
thd THD of the query
current_time current timestamp
query_start_arg command start timestamp
user_host the pointer to the string with user@host info
user_host_len length of the user_host string. this is computed once
and passed to all general log event handlers
query_time Amount of time the query took to execute (in seconds)
lock_time Amount of time the query was locked (in seconds)
is_command The flag, which determines, whether the sql_text is a
query or an administrator command.
sql_text the very text of the query or administrator command
processed
sql_text_len the length of sql_text string
DESCRIPTION
Log a query to the slow log file.
RETURN
FALSE - OK
TRUE - error occured
*/
bool MYSQL_LOG::write(THD *thd, time_t current_time, time_t query_start_arg,
const char *user_host, uint user_host_len,
longlong query_time, longlong lock_time, bool is_command,
const char *sql_text, uint sql_text_len)
{
bool error= 0;
DBUG_ENTER("MYSQL_LOG::write");
if (!is_open())
DBUG_RETURN(0);
if (is_open())
{ // Safety agains reopen
int tmp_errno= 0;
char buff[80], *end;
uint buff_len;
end= buff;
if (!(specialflag & SPECIAL_SHORT_LOG_FORMAT))
{
Security_context *sctx= thd->security_ctx;
if (current_time != last_time)
{
last_time= current_time;
struct tm start;
localtime_r(&current_time, &start);
buff_len= my_snprintf(buff, sizeof buff,
"# Time: %02d%02d%02d %2d:%02d:%02d\n",
start.tm_year % 100, start.tm_mon + 1,
start.tm_mday, start.tm_hour,
start.tm_min, start.tm_sec);
/* Note that my_b_write() assumes it knows the length for this */
if (my_b_write(&log_file, (byte*) buff, buff_len))
tmp_errno=errno;
}
if (my_b_printf(&log_file, "# User@Host: ", sizeof("# User@Host: ") - 1))
tmp_errno=errno;
if (my_b_printf(&log_file, user_host, user_host_len))
tmp_errno=errno;
if (my_b_write(&log_file, (byte*) "\n", 1))
tmp_errno=errno;
}
/* For slow query log */
if (my_b_printf(&log_file,
"# Query_time: %lu Lock_time: %lu"
" Rows_sent: %lu Rows_examined: %lu\n",
(ulong) query_time, (ulong) lock_time,
(ulong) thd->sent_row_count,
(ulong) thd->examined_row_count) == (uint) -1)
tmp_errno=errno;
if (thd->db && strcmp(thd->db,db))
{ // Database changed
if (my_b_printf(&log_file,"use %s;\n",thd->db) == (uint) -1)
tmp_errno=errno;
strmov(db,thd->db);
}
if (thd->last_insert_id_used)
{
end=strmov(end,",last_insert_id=");
end=longlong10_to_str((longlong) thd->current_insert_id,end,-10);
}
// Save value if we do an insert.
if (thd->insert_id_used)
{
if (!(specialflag & SPECIAL_SHORT_LOG_FORMAT))
{
end=strmov(end,",insert_id=");
end=longlong10_to_str((longlong) thd->last_insert_id,end,-10);
}
}
/*
This info used to show up randomly, depending on whether the query
checked the query start time or not. now we always write current
timestamp to the slow log
*/
end= strmov(end, ",timestamp=");
end= int10_to_str((long) current_time, end, 10);
if (end != buff)
{
*end++=';';
*end='\n';
if (my_b_write(&log_file, (byte*) "SET ",4) ||
my_b_write(&log_file, (byte*) buff+1,(uint) (end-buff)))
tmp_errno=errno;
}
if (is_command)
{
end= strxmov(buff, "# administrator command: ", NullS);
buff_len= (ulong) (end - buff);
my_b_write(&log_file, (byte*) buff, buff_len);
}
if (my_b_write(&log_file, (byte*) sql_text, sql_text_len) ||
my_b_write(&log_file, (byte*) ";\n",2) ||
flush_io_cache(&log_file))
tmp_errno=errno;
if (tmp_errno)
{
error=1;
if (! write_error)
{
write_error=1;
sql_print_error(ER(ER_ERROR_ON_WRITE),name,error);
}
}
}
DBUG_RETURN(error);
}
/* /*
Wait until we get a signal that the binary log has been updated Wait until we get a signal that the binary log has been updated
...@@ -3321,7 +3506,7 @@ bool MYSQL_LOG::write(THD *thd, time_t current_time, time_t query_start_arg, ...@@ -3321,7 +3506,7 @@ bool MYSQL_LOG::write(THD *thd, time_t current_time, time_t query_start_arg,
THD::enter_cond() (see NOTES in sql_class.h). THD::enter_cond() (see NOTES in sql_class.h).
*/ */
void MYSQL_LOG::wait_for_update(THD* thd, bool is_slave) void MYSQL_BIN_LOG::wait_for_update(THD* thd, bool is_slave)
{ {
const char *old_msg; const char *old_msg;
DBUG_ENTER("wait_for_update"); DBUG_ENTER("wait_for_update");
...@@ -3354,9 +3539,9 @@ void MYSQL_LOG::wait_for_update(THD* thd, bool is_slave) ...@@ -3354,9 +3539,9 @@ void MYSQL_LOG::wait_for_update(THD* thd, bool is_slave)
The internal structures are not freed until cleanup() is called The internal structures are not freed until cleanup() is called
*/ */
void MYSQL_LOG::close(uint exiting) void MYSQL_BIN_LOG::close(uint exiting)
{ // One can't set log_type here! { // One can't set log_type here!
DBUG_ENTER("MYSQL_LOG::close"); DBUG_ENTER("MYSQL_BIN_LOG::close");
DBUG_PRINT("enter",("exiting: %d", (int) exiting)); DBUG_PRINT("enter",("exiting: %d", (int) exiting));
if (log_type != LOG_CLOSED && log_type != LOG_TO_BE_OPENED) if (log_type != LOG_CLOSED && log_type != LOG_TO_BE_OPENED)
{ {
...@@ -3370,7 +3555,6 @@ void MYSQL_LOG::close(uint exiting) ...@@ -3370,7 +3555,6 @@ void MYSQL_LOG::close(uint exiting)
signal_update(); signal_update();
} }
#endif /* HAVE_REPLICATION */ #endif /* HAVE_REPLICATION */
end_io_cache(&log_file);
/* don't pwrite in a file opened with O_APPEND - it doesn't work */ /* don't pwrite in a file opened with O_APPEND - it doesn't work */
if (log_file.type == WRITE_CACHE && log_type == LOG_BIN) if (log_file.type == WRITE_CACHE && log_type == LOG_BIN)
...@@ -3380,16 +3564,8 @@ void MYSQL_LOG::close(uint exiting) ...@@ -3380,16 +3564,8 @@ void MYSQL_LOG::close(uint exiting)
my_pwrite(log_file.file, &flags, 1, offset, MYF(0)); my_pwrite(log_file.file, &flags, 1, offset, MYF(0));
} }
if (my_sync(log_file.file,MYF(MY_WME)) && ! write_error) /* this will cleanup IO_CACHE, sync and close the file */
{ MYSQL_LOG::close(exiting);
write_error=1;
sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno);
}
if (my_close(log_file.file,MYF(MY_WME)) && ! write_error)
{
write_error=1;
sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno);
}
} }
/* /*
...@@ -3412,7 +3588,7 @@ void MYSQL_LOG::close(uint exiting) ...@@ -3412,7 +3588,7 @@ void MYSQL_LOG::close(uint exiting)
} }
void MYSQL_LOG::set_max_size(ulong max_size_arg) void MYSQL_BIN_LOG::set_max_size(ulong max_size_arg)
{ {
/* /*
We need to take locks, otherwise this may happen: We need to take locks, otherwise this may happen:
...@@ -3421,7 +3597,7 @@ void MYSQL_LOG::set_max_size(ulong max_size_arg) ...@@ -3421,7 +3597,7 @@ void MYSQL_LOG::set_max_size(ulong max_size_arg)
uses the old_max_size argument, so max_size_arg has been overwritten and uses the old_max_size argument, so max_size_arg has been overwritten and
it's like if the SET command was never run. it's like if the SET command was never run.
*/ */
DBUG_ENTER("MYSQL_LOG::set_max_size"); DBUG_ENTER("MYSQL_BIN_LOG::set_max_size");
pthread_mutex_lock(&LOCK_log); pthread_mutex_lock(&LOCK_log);
if (is_open()) if (is_open())
max_size= max_size_arg; max_size= max_size_arg;
...@@ -3570,9 +3746,9 @@ bool flush_error_log() ...@@ -3570,9 +3746,9 @@ bool flush_error_log()
return result; return result;
} }
void MYSQL_LOG::signal_update() void MYSQL_BIN_LOG::signal_update()
{ {
DBUG_ENTER("MYSQL_LOG::signal_update"); DBUG_ENTER("MYSQL_BIN_LOG::signal_update");
pthread_cond_broadcast(&update_cond); pthread_cond_broadcast(&update_cond);
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
...@@ -4175,7 +4351,7 @@ int TC_LOG::using_heuristic_recover() ...@@ -4175,7 +4351,7 @@ int TC_LOG::using_heuristic_recover()
} }
/****** transaction coordinator log for 2pc - binlog() based solution ******/ /****** transaction coordinator log for 2pc - binlog() based solution ******/
#define TC_LOG_BINLOG MYSQL_LOG #define TC_LOG_BINLOG MYSQL_BIN_LOG
/* /*
TODO keep in-memory list of prepared transactions TODO keep in-memory list of prepared transactions
......
...@@ -147,33 +147,89 @@ typedef struct st_log_info ...@@ -147,33 +147,89 @@ typedef struct st_log_info
class Log_event; class Log_event;
class Rows_log_event; class Rows_log_event;
enum enum_log_type { LOG_CLOSED, LOG_TO_BE_OPENED, LOG_NORMAL, LOG_NEW, LOG_BIN}; enum enum_log_type { LOG_CLOSED, LOG_TO_BE_OPENED, LOG_NORMAL, LOG_BIN};
/* /*
TODO split MYSQL_LOG into base MYSQL_LOG and
MYSQL_QUERY_LOG, MYSQL_SLOW_LOG, MYSQL_BIN_LOG
most of the code from MYSQL_LOG should be in the MYSQL_BIN_LOG
only (TC_LOG included)
TODO use mmap instead of IO_CACHE for binlog TODO use mmap instead of IO_CACHE for binlog
(mmap+fsync is two times faster than write+fsync) (mmap+fsync is two times faster than write+fsync)
*/ */
class MYSQL_LOG: public TC_LOG class MYSQL_LOG
{
public:
MYSQL_LOG();
void init_pthread_objects();
void cleanup();
void reopen_file();
bool open(const char *log_name,
enum_log_type log_type,
const char *new_name,
enum cache_type io_cache_type_arg);
void init(enum_log_type log_type_arg,
enum cache_type io_cache_type_arg);
void close(uint exiting);
inline bool is_open() { return log_type != LOG_CLOSED; }
const char *generate_name(const char *log_name, const char *suffix,
bool strip_ext, char *buff);
int generate_new_name(char *new_name, const char *log_name);
protected:
/* LOCK_log is inited by init_pthread_objects() */
pthread_mutex_t LOCK_log;
char *name;
char log_file_name[FN_REFLEN];
char time_buff[20], db[NAME_LEN + 1];
bool write_error, inited;
IO_CACHE log_file;
volatile enum_log_type log_type;
enum cache_type io_cache_type;
time_t last_time;
friend class Log_event;
};
class MYSQL_GENERAL_LOG: public MYSQL_LOG
{
public:
MYSQL_GENERAL_LOG() {} /* get rid of gcc warning */
bool write(time_t event_time, const char *user_host,
uint user_host_len, int thread_id,
const char *command_type, uint command_type_len,
const char *sql_text, uint sql_text_len);
bool open_query_log(const char *log_name)
{
char buf[FN_REFLEN];
return open(generate_name(log_name, ".log", 0, buf), LOG_NORMAL, 0,
WRITE_CACHE);
}
};
class MYSQL_SLOW_LOG: public MYSQL_LOG
{
public:
MYSQL_SLOW_LOG() {} /* get rid of gcc warning */
bool write(THD *thd, time_t current_time, time_t query_start_arg,
const char *user_host, uint user_host_len,
longlong query_time, longlong lock_time, bool is_command,
const char *sql_text, uint sql_text_len);
bool open_slow_log(const char *log_name)
{
char buf[FN_REFLEN];
return open(generate_name(log_name, "-slow.log", 0, buf), LOG_NORMAL, 0,
WRITE_CACHE);
}
};
class MYSQL_BIN_LOG: public TC_LOG, private MYSQL_LOG
{ {
private: private:
/* LOCK_log and LOCK_index are inited by init_pthread_objects() */ /* LOCK_log and LOCK_index are inited by init_pthread_objects() */
pthread_mutex_t LOCK_log, LOCK_index; pthread_mutex_t LOCK_index;
pthread_mutex_t LOCK_prep_xids; pthread_mutex_t LOCK_prep_xids;
pthread_cond_t COND_prep_xids; pthread_cond_t COND_prep_xids;
pthread_cond_t update_cond; pthread_cond_t update_cond;
ulonglong bytes_written; ulonglong bytes_written;
time_t last_time,query_start;
IO_CACHE log_file;
IO_CACHE index_file; IO_CACHE index_file;
char *name; char index_file_name[FN_REFLEN];
char time_buff[20],db[NAME_LEN+1];
char log_file_name[FN_REFLEN],index_file_name[FN_REFLEN];
/* /*
The max size before rotation (usable only if log_type == LOG_BIN: binary The max size before rotation (usable only if log_type == LOG_BIN: binary
logs and relay logs). logs and relay logs).
...@@ -186,13 +242,10 @@ class MYSQL_LOG: public TC_LOG ...@@ -186,13 +242,10 @@ class MYSQL_LOG: public TC_LOG
*/ */
ulong max_size; ulong max_size;
ulong prepared_xids; /* for tc log - number of xids to remember */ ulong prepared_xids; /* for tc log - number of xids to remember */
volatile enum_log_type log_type;
enum cache_type io_cache_type;
// current file sequence number for load data infile binary logging // current file sequence number for load data infile binary logging
uint file_id; uint file_id;
uint open_count; // For replication uint open_count; // For replication
int readers_count; int readers_count;
bool write_error, inited;
bool need_start_event; bool need_start_event;
/* /*
no_auto_events means we don't want any of these automatic events : no_auto_events means we don't want any of these automatic events :
...@@ -202,13 +255,20 @@ class MYSQL_LOG: public TC_LOG ...@@ -202,13 +255,20 @@ class MYSQL_LOG: public TC_LOG
In 5.0 it's 0 for relay logs too! In 5.0 it's 0 for relay logs too!
*/ */
bool no_auto_events; bool no_auto_events;
friend class Log_event;
ulonglong m_table_map_version; ulonglong m_table_map_version;
int write_to_file(IO_CACHE *cache); int write_to_file(IO_CACHE *cache);
/*
This is used to start writing to a new log file. The difference from
new_file() is locking. new_file_without_locking() does not acquire
LOCK_log.
*/
void new_file_without_locking();
void new_file_impl(bool need_lock);
public: public:
MYSQL_LOG::generate_name;
/* /*
These describe the log's format. This is used only for relay logs. These describe the log's format. This is used only for relay logs.
_for_exec is used by the SQL thread, _for_queue by the I/O thread. It's _for_exec is used by the SQL thread, _for_queue by the I/O thread. It's
...@@ -220,9 +280,9 @@ class MYSQL_LOG: public TC_LOG ...@@ -220,9 +280,9 @@ class MYSQL_LOG: public TC_LOG
Format_description_log_event *description_event_for_exec, Format_description_log_event *description_event_for_exec,
*description_event_for_queue; *description_event_for_queue;
MYSQL_LOG(); MYSQL_BIN_LOG();
/* /*
note that there's no destructor ~MYSQL_LOG() ! note that there's no destructor ~MYSQL_BIN_LOG() !
The reason is that we don't want it to be automatically called The reason is that we don't want it to be automatically called
on exit() - but only during the correct shutdown process on exit() - but only during the correct shutdown process
*/ */
...@@ -264,9 +324,7 @@ class MYSQL_LOG: public TC_LOG ...@@ -264,9 +324,7 @@ class MYSQL_LOG: public TC_LOG
void signal_update(); void signal_update();
void wait_for_update(THD* thd, bool master_or_slave); void wait_for_update(THD* thd, bool master_or_slave);
void set_need_start_event() { need_start_event = 1; } void set_need_start_event() { need_start_event = 1; }
void init(enum_log_type log_type_arg, void init(bool no_auto_events_arg, ulong max_size);
enum cache_type io_cache_type_arg,
bool no_auto_events_arg, ulong max_size);
void init_pthread_objects(); void init_pthread_objects();
void cleanup(); void cleanup();
bool open(const char *log_name, bool open(const char *log_name,
...@@ -275,35 +333,10 @@ class MYSQL_LOG: public TC_LOG ...@@ -275,35 +333,10 @@ class MYSQL_LOG: public TC_LOG
enum cache_type io_cache_type_arg, enum cache_type io_cache_type_arg,
bool no_auto_events_arg, ulong max_size, bool no_auto_events_arg, ulong max_size,
bool null_created); bool null_created);
const char *generate_name(const char *log_name, const char *suffix,
bool strip_ext, char *buff);
/* simplified open_xxx wrappers for the gigantic open above */
bool open_query_log(const char *log_name)
{
char buf[FN_REFLEN];
return open(generate_name(log_name, ".log", 0, buf),
LOG_NORMAL, 0, WRITE_CACHE, 0, 0, 0);
}
bool open_slow_log(const char *log_name)
{
char buf[FN_REFLEN];
return open(generate_name(log_name, "-slow.log", 0, buf),
LOG_NORMAL, 0, WRITE_CACHE, 0, 0, 0);
}
bool open_index_file(const char *index_file_name_arg, bool open_index_file(const char *index_file_name_arg,
const char *log_name); const char *log_name);
void new_file(bool need_lock); /* Use this to start writing a new log file */
/* log a command to the old-fashioned general log */ void new_file();
bool write(time_t event_time, const char *user_host,
uint user_host_len, int thread_id,
const char *command_type, uint command_type_len,
const char *sql_text, uint sql_text_len);
/* log a query to the old-fashioned slow query log */
bool write(THD *thd, time_t current_time, time_t query_start_arg,
const char *user_host, uint user_host_len,
longlong query_time, longlong lock_time, bool is_command,
const char *sql_text, uint sql_text_len);
bool write(Log_event* event_info); // binary log write bool write(Log_event* event_info); // binary log write
bool write(THD *thd, IO_CACHE *cache, Log_event *commit_event); bool write(THD *thd, IO_CACHE *cache, Log_event *commit_event);
...@@ -319,7 +352,6 @@ class MYSQL_LOG: public TC_LOG ...@@ -319,7 +352,6 @@ class MYSQL_LOG: public TC_LOG
bool appendv(const char* buf,uint len,...); bool appendv(const char* buf,uint len,...);
bool append(Log_event* ev); bool append(Log_event* ev);
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 update_log_index(LOG_INFO* linfo, bool need_update_threads); int update_log_index(LOG_INFO* linfo, bool need_update_threads);
...@@ -416,7 +448,8 @@ class Log_to_csv_event_handler: public Log_event_handler ...@@ -416,7 +448,8 @@ class Log_to_csv_event_handler: public Log_event_handler
class Log_to_file_event_handler: public Log_event_handler class Log_to_file_event_handler: public Log_event_handler
{ {
MYSQL_LOG mysql_log, mysql_slow_log; MYSQL_GENERAL_LOG mysql_log;
MYSQL_SLOW_LOG mysql_slow_log;
bool is_initialized; bool is_initialized;
public: public:
Log_to_file_event_handler(): is_initialized(FALSE) Log_to_file_event_handler(): is_initialized(FALSE)
......
...@@ -470,7 +470,7 @@ enum Int_event_type ...@@ -470,7 +470,7 @@ enum Int_event_type
#ifndef MYSQL_CLIENT #ifndef MYSQL_CLIENT
class String; class String;
class MYSQL_LOG; class MYSQL_BIN_LOG;
class THD; class THD;
#endif #endif
......
...@@ -1525,7 +1525,7 @@ extern char *default_tz_name; ...@@ -1525,7 +1525,7 @@ extern char *default_tz_name;
extern my_bool opt_large_pages; extern my_bool opt_large_pages;
extern uint opt_large_page_size; extern uint opt_large_page_size;
extern MYSQL_LOG mysql_bin_log; extern MYSQL_BIN_LOG mysql_bin_log;
extern LOGGER logger; extern LOGGER logger;
extern TABLE_LIST general_log, slow_log; extern TABLE_LIST general_log, slow_log;
extern FILE *bootstrap_file; extern FILE *bootstrap_file;
......
...@@ -2610,10 +2610,10 @@ static int init_common_variables(const char *conf_file_name, int argc, ...@@ -2610,10 +2610,10 @@ static int init_common_variables(const char *conf_file_name, int argc,
global_system_variables.time_zone= my_tz_SYSTEM; global_system_variables.time_zone= my_tz_SYSTEM;
/* /*
Init mutexes for the global MYSQL_LOG objects. Init mutexes for the global MYSQL_BIN_LOG objects.
As safe_mutex depends on what MY_INIT() does, we can't init the mutexes of As safe_mutex depends on what MY_INIT() does, we can't init the mutexes of
global MYSQL_LOGs in their constructors, because then they would be inited global MYSQL_BIN_LOGs in their constructors, because then they would be
before MY_INIT(). So we do it here. inited before MY_INIT(). So we do it here.
*/ */
mysql_bin_log.init_pthread_objects(); mysql_bin_log.init_pthread_objects();
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
/* inline since it's called below */ /* inline since it's called below */
inline inline
injector::transaction::transaction(MYSQL_LOG *log, THD *thd) injector::transaction::transaction(MYSQL_BIN_LOG *log, THD *thd)
: m_state(START_STATE), m_thd(thd) : m_state(START_STATE), m_thd(thd)
{ {
/* /*
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
/* Forward declarations */ /* Forward declarations */
class handler; class handler;
class MYSQL_LOG; class MYSQL_BIN_LOG;
class st_table; class st_table;
typedef st_table TABLE; typedef st_table TABLE;
...@@ -219,7 +219,7 @@ class injector ...@@ -219,7 +219,7 @@ class injector
private: private:
/* Only the injector may construct these object */ /* Only the injector may construct these object */
transaction(MYSQL_LOG *, THD *); transaction(MYSQL_BIN_LOG *, THD *);
void swap(transaction& o) { void swap(transaction& o) {
/* std::swap(m_start_pos, o.m_start_pos); */ /* std::swap(m_start_pos, o.m_start_pos); */
......
...@@ -69,7 +69,7 @@ typedef struct st_relay_log_info ...@@ -69,7 +69,7 @@ typedef struct st_relay_log_info
Protected with internal locks. Protected with internal locks.
Must get data_lock when resetting the logs. Must get data_lock when resetting the logs.
*/ */
MYSQL_LOG relay_log; MYSQL_BIN_LOG relay_log;
LOG_INFO linfo; LOG_INFO linfo;
IO_CACHE cache_buf,*cur_log; IO_CACHE cache_buf,*cur_log;
......
...@@ -4570,7 +4570,7 @@ static Log_event* next_event(RELAY_LOG_INFO* rli) ...@@ -4570,7 +4570,7 @@ static Log_event* next_event(RELAY_LOG_INFO* rli)
When the relay log is created when the I/O thread starts, easy: the When the relay log is created when the I/O thread starts, easy: the
master will send the description event and we will queue it. master will send the description event and we will queue it.
But if the relay log is created by new_file(): then the solution is: But if the relay log is created by new_file(): then the solution is:
MYSQL_LOG::open() will write the buffered description event. MYSQL_BIN_LOG::open() will write the buffered description event.
*/ */
if ((ev=Log_event::read_log_event(cur_log,0, if ((ev=Log_event::read_log_event(cur_log,0,
rli->relay_log.description_event_for_exec))) rli->relay_log.description_event_for_exec)))
...@@ -4832,7 +4832,8 @@ event(errno: %d cur_log->error: %d)", ...@@ -4832,7 +4832,8 @@ event(errno: %d cur_log->error: %d)",
Rotate a relay log (this is used only by FLUSH LOGS; the automatic rotation Rotate a relay log (this is used only by FLUSH LOGS; the automatic rotation
because of size is simpler because when we do it we already have all relevant because of size is simpler because when we do it we already have all relevant
locks; here we don't, so this function is mainly taking locks). locks; here we don't, so this function is mainly taking locks).
Returns nothing as we cannot catch any error (MYSQL_LOG::new_file() is void). Returns nothing as we cannot catch any error (MYSQL_BIN_LOG::new_file()
is void).
*/ */
void rotate_relay_log(MASTER_INFO* mi) void rotate_relay_log(MASTER_INFO* mi)
...@@ -4854,7 +4855,7 @@ void rotate_relay_log(MASTER_INFO* mi) ...@@ -4854,7 +4855,7 @@ void rotate_relay_log(MASTER_INFO* mi)
} }
/* If the relay log is closed, new_file() will do nothing. */ /* If the relay log is closed, new_file() will do nothing. */
rli->relay_log.new_file(1); rli->relay_log.new_file();
/* /*
We harvest now, because otherwise BIN_LOG_HEADER_SIZE will not immediately We harvest now, because otherwise BIN_LOG_HEADER_SIZE will not immediately
......
...@@ -73,7 +73,7 @@ ...@@ -73,7 +73,7 @@
run_lock protects all information about the run state: slave_running, and the run_lock protects all information about the run state: slave_running, and the
existence of the I/O thread (to stop/start it, you need this mutex). existence of the I/O thread (to stop/start it, you need this mutex).
data_lock protects some moving members of the struct: counters (log name, data_lock protects some moving members of the struct: counters (log name,
position) and relay log (MYSQL_LOG object). position) and relay log (MYSQL_BIN_LOG object).
In RELAY_LOG_INFO: run_lock, data_lock In RELAY_LOG_INFO: run_lock, data_lock
see MASTER_INFO see MASTER_INFO
...@@ -81,7 +81,7 @@ ...@@ -81,7 +81,7 @@
Order of acquisition: if you want to have LOCK_active_mi and a run_lock, you Order of acquisition: if you want to have LOCK_active_mi and a run_lock, you
must acquire LOCK_active_mi first. must acquire LOCK_active_mi first.
In MYSQL_LOG: LOCK_log, LOCK_index of the binlog and the relay log In MYSQL_BIN_LOG: LOCK_log, LOCK_index of the binlog and the relay log
LOCK_log: when you write to it. LOCK_index: when you create/delete a binlog LOCK_log: when you write to it. LOCK_index: when you create/delete a binlog
(so that you have to update the .index file). (so that you have to update the .index file).
*/ */
......
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