diff options
Diffstat (limited to 'sql/log.cc')
-rw-r--r-- | sql/log.cc | 121 |
1 files changed, 91 insertions, 30 deletions
diff --git a/sql/log.cc b/sql/log.cc index 0fac27989f2..22af63c025c 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -209,9 +209,9 @@ bool MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg, #ifdef EMBEDDED_LIBRARY sprintf(buff, "%s, Version: %s, embedded library\n", my_progname, server_version); #elif __NT__ - sprintf(buff, "%s, Version: %s, started with:\nTCP Port: %d, Named Pipe: %s\n", my_progname, server_version, mysql_port, mysql_unix_port); + sprintf(buff, "%s, Version: %s, started with:\nTCP Port: %d, Named Pipe: %s\n", my_progname, server_version, mysqld_port, mysqld_unix_port); #else - sprintf(buff, "%s, Version: %s, started with:\nTcp port: %d Unix socket: %s\n", my_progname,server_version,mysql_port,mysql_unix_port); + sprintf(buff, "%s, Version: %s, started with:\nTcp port: %d Unix socket: %s\n", my_progname,server_version,mysqld_port,mysqld_unix_port); #endif end=strmov(strend(buff),"Time Id Command Argument\n"); if (my_b_write(&log_file, (byte*) buff,(uint) (end-buff)) || @@ -317,7 +317,10 @@ bool MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg, DBUG_RETURN(0); err: - sql_print_error("Could not use %s for logging (error %d)", log_name, errno); + 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.", log_name, errno); if (file >= 0) my_close(file,MYF(0)); if (index_file_nr >= 0) @@ -767,6 +770,7 @@ int MYSQL_LOG::purge_logs(const char *to_log, !log_in_use(log_info.log_file_name)) { ulong tmp; + LINT_INIT(tmp); if (decrease_log_space) //stat the file we want to delete { MY_STAT s; @@ -962,14 +966,6 @@ void MYSQL_LOG::new_file(bool need_lock) THD* thd = current_thd; Rotate_log_event r(thd,new_name+dirname_length(new_name)); r.set_log_pos(this); - - /* - Because this log rotation could have been initiated by a master of - the slave running with log-bin, we set the flag on rotate - event to prevent infinite log rotation loop - */ - if (thd->slave_thread) - r.flags|= LOG_EVENT_FORCED_ROTATE_F; r.write(&log_file); bytes_written += r.get_event_len(); } @@ -1156,6 +1152,8 @@ bool MYSQL_LOG::write(THD *thd,enum enum_server_command command, bool MYSQL_LOG::write(Log_event* event_info) { + THD *thd=event_info->thd; + bool called_handler_commit=0; bool error=0; bool should_rotate = 0; DBUG_ENTER("MYSQL_LOG::write(event)"); @@ -1170,7 +1168,6 @@ bool MYSQL_LOG::write(Log_event* event_info) /* In most cases this is only called if 'is_open()' is true */ if (is_open()) { - THD *thd=event_info->thd; const char *local_db = event_info->get_db(); #ifdef USING_TRANSACTIONS IO_CACHE *file = ((event_info->get_cache_stmt()) ? @@ -1195,6 +1192,12 @@ bool MYSQL_LOG::write(Log_event* event_info) No check for auto events flag here - this write method should never be called if auto-events are enabled */ + + /* + 1. Write first log events which describe the 'run environment' + of the SQL command + */ + if (thd) { if (thd->last_insert_id_used) @@ -1240,7 +1243,7 @@ bool MYSQL_LOG::write(Log_event* event_info) goto err; } } -#if 0 +#ifdef TO_BE_REMOVED if (thd->variables.convert_set) { char buf[256], *p; @@ -1252,12 +1255,39 @@ bool MYSQL_LOG::write(Log_event* event_info) goto err; } #endif + + /* + If the user has set FOREIGN_KEY_CHECKS=0 we wrap every SQL + command in the binlog inside: + SET FOREIGN_KEY_CHECKS=0; + <command>; + SET FOREIGN_KEY_CHECKS=1; + */ + + if (thd->options & OPTION_NO_FOREIGN_KEY_CHECKS) + { + Query_log_event e(thd, "SET FOREIGN_KEY_CHECKS=0", 24, 0); + e.set_log_pos(this); + if (e.write(file)) + goto err; + } } + + /* Write the SQL command */ + event_info->set_log_pos(this); - if (event_info->write(file) || - file == &log_file && flush_io_cache(file)) + if (event_info->write(file)) goto err; - error=0; + + /* Write log events to reset the 'run environment' of the SQL command */ + + if (thd && thd->options & OPTION_NO_FOREIGN_KEY_CHECKS) + { + Query_log_event e(thd, "SET FOREIGN_KEY_CHECKS=1", 24, 0); + e.set_log_pos(this); + if (e.write(file)) + goto err; + } /* Tell for transactional table handlers up to which position in the @@ -1267,26 +1297,41 @@ bool MYSQL_LOG::write(Log_event* event_info) the table handler commit here, protected by the LOCK_log mutex, because otherwise the transactions may end up in a different order in the table handler log! + + Note that we will NOT call ha_report_binlog_offset_and_commit() if + there are binlog events cached in the transaction cache. That is + because then the log event which we write to the binlog here is + not a transactional event. In versions < 4.0.13 before this fix this + caused an InnoDB transaction to be committed if in the middle there + was a MyISAM event! */ - if (file == &log_file) + if (file == &log_file) // we are writing to the real log (disk) { - /* - LOAD DATA INFILE in AUTOCOMMIT=1 mode writes to the binlog - chunks also before it is successfully completed. We only report - the binlog write and do the commit inside the transactional table - handler if the log event type is appropriate. - */ - - if (event_info->get_type_code() == QUERY_EVENT - || event_info->get_type_code() == EXEC_LOAD_EVENT) + if (flush_io_cache(file)) + goto err; + + if (opt_using_transactions && !my_b_tell(&thd->transaction.trans_log)) { - error = ha_report_binlog_offset_and_commit(thd, log_file_name, - file->pos_in_file); + /* + LOAD DATA INFILE in AUTOCOMMIT=1 mode writes to the binlog + chunks also before it is successfully completed. We only report + the binlog write and do the commit inside the transactional table + handler if the log event type is appropriate. + */ + + if (event_info->get_type_code() == QUERY_EVENT || + event_info->get_type_code() == EXEC_LOAD_EVENT) + { + error = ha_report_binlog_offset_and_commit(thd, log_file_name, + file->pos_in_file); + called_handler_commit=1; + } } - + /* we wrote to the real log, check automatic rotation */ should_rotate= (my_b_tell(file) >= (my_off_t) max_binlog_size); } + error=0; err: if (error) @@ -1308,6 +1353,16 @@ err: } pthread_mutex_unlock(&LOCK_log); + + /* + Flush the transactional handler log file now that we have released + LOCK_log; the flush is placed here to eliminate the bottleneck on the + group commit + */ + + if (called_handler_commit) + ha_commit_complete(thd); + #ifdef HAVE_REPLICATION if (should_rotate && expire_logs_days) { @@ -1315,7 +1370,6 @@ err: if (purge_time >= 0) error= purge_logs_before_date(purge_time); } - #endif DBUG_RETURN(error); } @@ -1422,6 +1476,13 @@ bool MYSQL_LOG::write(THD *thd, IO_CACHE *cache) } VOID(pthread_mutex_unlock(&LOCK_log)); + + /* Flush the transactional handler log file now that we have released + LOCK_log; the flush is placed here to eliminate the bottleneck on the + group commit */ + + ha_commit_complete(thd); + DBUG_RETURN(0); err: |