mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
merge: 5.1 -> 5.1-rpl
conflicts: Text conflict in client/mysqltest.cc Text conflict in mysql-test/include/wait_until_connected_again.inc Text conflict in mysql-test/lib/mtr_report.pm Text conflict in mysql-test/mysql-test-run.pl Text conflict in mysql-test/r/events_bugs.result Text conflict in mysql-test/r/log_state.result Text conflict in mysql-test/r/myisam_data_pointer_size_func.result Text conflict in mysql-test/r/mysqlcheck.result Text conflict in mysql-test/r/query_cache.result Text conflict in mysql-test/r/status.result Text conflict in mysql-test/suite/binlog/r/binlog_index.result Text conflict in mysql-test/suite/binlog/r/binlog_innodb.result Text conflict in mysql-test/suite/rpl/r/rpl_packet.result Text conflict in mysql-test/suite/rpl/t/rpl_packet.test Text conflict in mysql-test/t/disabled.def Text conflict in mysql-test/t/events_bugs.test Text conflict in mysql-test/t/log_state.test Text conflict in mysql-test/t/myisam_data_pointer_size_func.test Text conflict in mysql-test/t/mysqlcheck.test Text conflict in mysql-test/t/query_cache.test Text conflict in mysql-test/t/rpl_init_slave_func.test Text conflict in mysql-test/t/status.test
This commit is contained in:
301
sql/log.cc
301
sql/log.cc
@ -207,6 +207,7 @@ public:
|
||||
truncate(0);
|
||||
before_stmt_pos= MY_OFF_T_UNDEF;
|
||||
trans_log.end_of_file= max_binlog_cache_size;
|
||||
DBUG_ASSERT(empty());
|
||||
}
|
||||
|
||||
Rows_log_event *pending() const
|
||||
@ -1377,8 +1378,6 @@ binlog_end_trans(THD *thd, binlog_trx_data *trx_data,
|
||||
FLAGSTR(thd->options, OPTION_NOT_AUTOCOMMIT),
|
||||
FLAGSTR(thd->options, OPTION_BEGIN)));
|
||||
|
||||
thd->binlog_flush_pending_rows_event(TRUE);
|
||||
|
||||
/*
|
||||
NULL denotes ROLLBACK with nothing to replicate: i.e., rollback of
|
||||
only transactional tables. If the transaction contain changes to
|
||||
@ -1387,6 +1386,7 @@ binlog_end_trans(THD *thd, binlog_trx_data *trx_data,
|
||||
*/
|
||||
if (end_ev != NULL)
|
||||
{
|
||||
thd->binlog_flush_pending_rows_event(TRUE);
|
||||
/*
|
||||
Doing a commit or a rollback including non-transactional tables,
|
||||
i.e., ending a transaction where we might write the transaction
|
||||
@ -1435,6 +1435,7 @@ binlog_end_trans(THD *thd, binlog_trx_data *trx_data,
|
||||
mysql_bin_log.update_table_map_version();
|
||||
}
|
||||
|
||||
DBUG_ASSERT(thd->binlog_get_pending_rows_event() == NULL);
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
@ -1464,6 +1465,7 @@ static int binlog_prepare(handlerton *hton, THD *thd, bool all)
|
||||
*/
|
||||
static int binlog_commit(handlerton *hton, THD *thd, bool all)
|
||||
{
|
||||
int error= 0;
|
||||
DBUG_ENTER("binlog_commit");
|
||||
binlog_trx_data *const trx_data=
|
||||
(binlog_trx_data*) thd_get_ha_data(thd, binlog_hton);
|
||||
@ -1476,60 +1478,11 @@ static int binlog_commit(handlerton *hton, THD *thd, bool all)
|
||||
}
|
||||
|
||||
/*
|
||||
Decision table for committing a transaction. The top part, the
|
||||
*conditions* represent different cases that can occur, and hte
|
||||
bottom part, the *actions*, represent what should be done in that
|
||||
particular case.
|
||||
We commit the transaction if:
|
||||
|
||||
Real transaction 'all' was true
|
||||
- We are not in a transaction and committing a statement, or
|
||||
|
||||
Statement in cache There were at least one statement in the
|
||||
transaction cache
|
||||
|
||||
In transaction We are inside a transaction
|
||||
|
||||
Stmt modified non-trans The statement being committed modified a
|
||||
non-transactional table
|
||||
|
||||
All modified non-trans Some statement before this one in the
|
||||
transaction modified a non-transactional
|
||||
table
|
||||
|
||||
|
||||
============================= = = = = = = = = = = = = = = = =
|
||||
Real transaction N N N N N N N N N N N N N N N N
|
||||
Statement in cache N N N N N N N N Y Y Y Y Y Y Y Y
|
||||
In transaction N N N N Y Y Y Y N N N N Y Y Y Y
|
||||
Stmt modified non-trans N N Y Y N N Y Y N N Y Y N N Y Y
|
||||
All modified non-trans N Y N Y N Y N Y N Y N Y N Y N Y
|
||||
|
||||
Action: (C)ommit/(A)ccumulate C C - C A C - C - - - - A A - A
|
||||
============================= = = = = = = = = = = = = = = = =
|
||||
|
||||
|
||||
============================= = = = = = = = = = = = = = = = =
|
||||
Real transaction Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y
|
||||
Statement in cache N N N N N N N N Y Y Y Y Y Y Y Y
|
||||
In transaction N N N N Y Y Y Y N N N N Y Y Y Y
|
||||
Stmt modified non-trans N N Y Y N N Y Y N N Y Y N N Y Y
|
||||
All modified non-trans N Y N Y N Y N Y N Y N Y N Y N Y
|
||||
|
||||
(C)ommit/(A)ccumulate/(-) - - - - C C - C - - - - C C - C
|
||||
============================= = = = = = = = = = = = = = = = =
|
||||
|
||||
In other words, we commit the transaction if and only if both of
|
||||
the following are true:
|
||||
- We are not in a transaction and committing a statement
|
||||
|
||||
- We are in a transaction and one (or more) of the following are
|
||||
true:
|
||||
|
||||
- A full transaction is committed
|
||||
|
||||
OR
|
||||
|
||||
- A non-transactional statement is committed and there is
|
||||
no statement cached
|
||||
- We are in a transaction and a full transaction is committed
|
||||
|
||||
Otherwise, we accumulate the statement
|
||||
*/
|
||||
@ -1542,18 +1495,18 @@ static int binlog_commit(handlerton *hton, THD *thd, bool all)
|
||||
YESNO(in_transaction),
|
||||
YESNO(thd->transaction.all.modified_non_trans_table),
|
||||
YESNO(thd->transaction.stmt.modified_non_trans_table)));
|
||||
if (in_transaction &&
|
||||
(all ||
|
||||
(!trx_data->at_least_one_stmt &&
|
||||
thd->transaction.stmt.modified_non_trans_table)) ||
|
||||
!in_transaction && !all)
|
||||
if (!in_transaction || all)
|
||||
{
|
||||
Query_log_event qev(thd, STRING_WITH_LEN("COMMIT"), TRUE, FALSE);
|
||||
qev.error_code= 0; // see comment in MYSQL_LOG::write(THD, IO_CACHE)
|
||||
int error= binlog_end_trans(thd, trx_data, &qev, all);
|
||||
DBUG_RETURN(error);
|
||||
error= binlog_end_trans(thd, trx_data, &qev, all);
|
||||
goto end;
|
||||
}
|
||||
DBUG_RETURN(0);
|
||||
|
||||
end:
|
||||
if (!all)
|
||||
trx_data->before_stmt_pos = MY_OFF_T_UNDEF; // part of the stmt commit
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1613,6 +1566,8 @@ static int binlog_rollback(handlerton *hton, THD *thd, bool all)
|
||||
*/
|
||||
error= binlog_end_trans(thd, trx_data, 0, all);
|
||||
}
|
||||
if (!all)
|
||||
trx_data->before_stmt_pos = MY_OFF_T_UNDEF; // part of the stmt rollback
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
@ -2358,6 +2313,7 @@ MYSQL_BIN_LOG::MYSQL_BIN_LOG()
|
||||
*/
|
||||
index_file_name[0] = 0;
|
||||
bzero((char*) &index_file, sizeof(index_file));
|
||||
bzero((char*) &purge_temp, sizeof(purge_temp));
|
||||
}
|
||||
|
||||
/* this is called only once */
|
||||
@ -2952,6 +2908,7 @@ err:
|
||||
int MYSQL_BIN_LOG::purge_first_log(Relay_log_info* rli, bool included)
|
||||
{
|
||||
int error;
|
||||
char *to_purge_if_included= NULL;
|
||||
DBUG_ENTER("purge_first_log");
|
||||
|
||||
DBUG_ASSERT(is_open());
|
||||
@ -2959,36 +2916,20 @@ int MYSQL_BIN_LOG::purge_first_log(Relay_log_info* rli, bool included)
|
||||
DBUG_ASSERT(!strcmp(rli->linfo.log_file_name,rli->event_relay_log_name));
|
||||
|
||||
pthread_mutex_lock(&LOCK_index);
|
||||
pthread_mutex_lock(&rli->log_space_lock);
|
||||
rli->relay_log.purge_logs(rli->group_relay_log_name, included,
|
||||
0, 0, &rli->log_space_total);
|
||||
// Tell the I/O thread to take the relay_log_space_limit into account
|
||||
rli->ignore_log_space_limit= 0;
|
||||
pthread_mutex_unlock(&rli->log_space_lock);
|
||||
to_purge_if_included= my_strdup(rli->group_relay_log_name, MYF(0));
|
||||
|
||||
/*
|
||||
Ok to broadcast after the critical region as there is no risk of
|
||||
the mutex being destroyed by this thread later - this helps save
|
||||
context switches
|
||||
*/
|
||||
pthread_cond_broadcast(&rli->log_space_cond);
|
||||
|
||||
/*
|
||||
Read the next log file name from the index file and pass it back to
|
||||
the caller
|
||||
If included is true, we want the first relay log;
|
||||
otherwise we want the one after event_relay_log_name.
|
||||
the caller.
|
||||
*/
|
||||
if ((included && (error=find_log_pos(&rli->linfo, NullS, 0))) ||
|
||||
(!included &&
|
||||
((error=find_log_pos(&rli->linfo, rli->event_relay_log_name, 0)) ||
|
||||
(error=find_next_log(&rli->linfo, 0)))))
|
||||
if((error=find_log_pos(&rli->linfo, rli->event_relay_log_name, 0)) ||
|
||||
(error=find_next_log(&rli->linfo, 0)))
|
||||
{
|
||||
char buff[22];
|
||||
sql_print_error("next log error: %d offset: %s log: %s included: %d",
|
||||
error,
|
||||
llstr(rli->linfo.index_file_offset,buff),
|
||||
rli->group_relay_log_name,
|
||||
rli->event_relay_log_name,
|
||||
included);
|
||||
goto err;
|
||||
}
|
||||
@ -3016,7 +2957,42 @@ int MYSQL_BIN_LOG::purge_first_log(Relay_log_info* rli, bool included)
|
||||
/* Store where we are in the new file for the execution thread */
|
||||
flush_relay_log_info(rli);
|
||||
|
||||
DBUG_EXECUTE_IF("crash_before_purge_logs", abort(););
|
||||
|
||||
pthread_mutex_lock(&rli->log_space_lock);
|
||||
rli->relay_log.purge_logs(to_purge_if_included, included,
|
||||
0, 0, &rli->log_space_total);
|
||||
// Tell the I/O thread to take the relay_log_space_limit into account
|
||||
rli->ignore_log_space_limit= 0;
|
||||
pthread_mutex_unlock(&rli->log_space_lock);
|
||||
|
||||
/*
|
||||
Ok to broadcast after the critical region as there is no risk of
|
||||
the mutex being destroyed by this thread later - this helps save
|
||||
context switches
|
||||
*/
|
||||
pthread_cond_broadcast(&rli->log_space_cond);
|
||||
|
||||
/*
|
||||
* Need to update the log pos because purge logs has been called
|
||||
* after fetching initially the log pos at the begining of the method.
|
||||
*/
|
||||
if((error=find_log_pos(&rli->linfo, rli->event_relay_log_name, 0)))
|
||||
{
|
||||
char buff[22];
|
||||
sql_print_error("next log error: %d offset: %s log: %s included: %d",
|
||||
error,
|
||||
llstr(rli->linfo.index_file_offset,buff),
|
||||
rli->group_relay_log_name,
|
||||
included);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* If included was passed, rli->linfo should be the first entry. */
|
||||
DBUG_ASSERT(!included || rli->linfo.index_file_start_offset == 0);
|
||||
|
||||
err:
|
||||
my_free(to_purge_if_included, MYF(0));
|
||||
pthread_mutex_unlock(&LOCK_index);
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
@ -3067,7 +3043,6 @@ int MYSQL_BIN_LOG::purge_logs(const char *to_log,
|
||||
ulonglong *decrease_log_space)
|
||||
{
|
||||
int error;
|
||||
int ret = 0;
|
||||
bool exit_loop= 0;
|
||||
LOG_INFO log_info;
|
||||
THD *thd= current_thd;
|
||||
@ -3076,8 +3051,36 @@ int MYSQL_BIN_LOG::purge_logs(const char *to_log,
|
||||
|
||||
if (need_mutex)
|
||||
pthread_mutex_lock(&LOCK_index);
|
||||
if ((error=find_log_pos(&log_info, to_log, 0 /*no mutex*/)))
|
||||
if ((error=find_log_pos(&log_info, to_log, 0 /*no mutex*/)))
|
||||
{
|
||||
sql_print_error("MYSQL_LOG::purge_logs was called with file %s not "
|
||||
"listed in the index.", to_log);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
For crash recovery reasons the index needs to be updated before
|
||||
any files are deleted. Move files to be deleted into a temp file
|
||||
to be processed after the index is updated.
|
||||
*/
|
||||
if (!my_b_inited(&purge_temp))
|
||||
{
|
||||
if ((error=open_cached_file(&purge_temp, mysql_tmpdir, TEMP_PREFIX,
|
||||
DISK_BUFFER_SIZE, MYF(MY_WME))))
|
||||
{
|
||||
sql_print_error("MYSQL_LOG::purge_logs failed to open purge_temp");
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((error=reinit_io_cache(&purge_temp, WRITE_CACHE, 0, 0, 1)))
|
||||
{
|
||||
sql_print_error("MYSQL_LOG::purge_logs failed to reinit purge_temp "
|
||||
"for write");
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
File name exists in index file; delete until we find this file
|
||||
@ -3088,6 +3091,61 @@ int MYSQL_BIN_LOG::purge_logs(const char *to_log,
|
||||
while ((strcmp(to_log,log_info.log_file_name) || (exit_loop=included)) &&
|
||||
!log_in_use(log_info.log_file_name))
|
||||
{
|
||||
if ((error=my_b_write(&purge_temp, (const uchar*)log_info.log_file_name,
|
||||
strlen(log_info.log_file_name))) ||
|
||||
(error=my_b_write(&purge_temp, (const uchar*)"\n", 1)))
|
||||
{
|
||||
sql_print_error("MYSQL_LOG::purge_logs failed to copy %s to purge_temp",
|
||||
log_info.log_file_name);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (find_next_log(&log_info, 0) || exit_loop)
|
||||
break;
|
||||
}
|
||||
|
||||
/* We know how many files to delete. Update index file. */
|
||||
if ((error=update_log_index(&log_info, need_update_threads)))
|
||||
{
|
||||
sql_print_error("MSYQL_LOG::purge_logs failed to update the index file");
|
||||
goto err;
|
||||
}
|
||||
|
||||
DBUG_EXECUTE_IF("crash_after_update_index", abort(););
|
||||
|
||||
/* Switch purge_temp for read. */
|
||||
if ((error=reinit_io_cache(&purge_temp, READ_CACHE, 0, 0, 0)))
|
||||
{
|
||||
sql_print_error("MSYQL_LOG::purge_logs failed to reinit purge_temp "
|
||||
"for read");
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Read each entry from purge_temp and delete the file. */
|
||||
for (;;)
|
||||
{
|
||||
uint length;
|
||||
|
||||
if ((length=my_b_gets(&purge_temp, log_info.log_file_name,
|
||||
FN_REFLEN)) <= 1)
|
||||
{
|
||||
if (purge_temp.error)
|
||||
{
|
||||
error= purge_temp.error;
|
||||
sql_print_error("MSYQL_LOG::purge_logs error %d reading from "
|
||||
"purge_temp", error);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Reached EOF */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Get rid of the trailing '\n' */
|
||||
log_info.log_file_name[length-1]= 0;
|
||||
|
||||
ha_binlog_index_purge_file(current_thd, log_info.log_file_name);
|
||||
|
||||
MY_STAT s;
|
||||
if (!my_stat(log_info.log_file_name, &s, MYF(0)))
|
||||
{
|
||||
@ -3188,23 +3246,10 @@ int MYSQL_BIN_LOG::purge_logs(const char *to_log,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ha_binlog_index_purge_file(current_thd, log_info.log_file_name);
|
||||
|
||||
if (find_next_log(&log_info, 0) || exit_loop)
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
If we get killed -9 here, the sysadmin would have to edit
|
||||
the log index file after restart - otherwise, this should be safe
|
||||
*/
|
||||
error= update_log_index(&log_info, need_update_threads);
|
||||
if (error == 0) {
|
||||
error = ret;
|
||||
}
|
||||
|
||||
err:
|
||||
close_cached_file(&purge_temp);
|
||||
if (need_mutex)
|
||||
pthread_mutex_unlock(&LOCK_index);
|
||||
DBUG_RETURN(error);
|
||||
@ -3215,7 +3260,7 @@ err:
|
||||
index file.
|
||||
|
||||
@param thd Thread pointer
|
||||
@param before_date Delete all log files before given date.
|
||||
@param purge_time Delete all log files before given date.
|
||||
|
||||
@note
|
||||
If any of the logs before the deleted one is in use,
|
||||
@ -3232,6 +3277,7 @@ err:
|
||||
int MYSQL_BIN_LOG::purge_logs_before_date(time_t purge_time)
|
||||
{
|
||||
int error;
|
||||
char to_log[FN_REFLEN];
|
||||
LOG_INFO log_info;
|
||||
MY_STAT stat_area;
|
||||
THD *thd= current_thd;
|
||||
@ -3239,12 +3285,8 @@ int MYSQL_BIN_LOG::purge_logs_before_date(time_t purge_time)
|
||||
DBUG_ENTER("purge_logs_before_date");
|
||||
|
||||
pthread_mutex_lock(&LOCK_index);
|
||||
to_log[0]= 0;
|
||||
|
||||
/*
|
||||
Delete until we find curren file
|
||||
or a file that is used or a file
|
||||
that is older than purge_time.
|
||||
*/
|
||||
if ((error=find_log_pos(&log_info, NullS, 0 /*no mutex*/)))
|
||||
goto err;
|
||||
|
||||
@ -3294,55 +3336,18 @@ int MYSQL_BIN_LOG::purge_logs_before_date(time_t purge_time)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (stat_area.st_mtime >= purge_time)
|
||||
if (stat_area.st_mtime < purge_time)
|
||||
strmake(to_log,
|
||||
log_info.log_file_name,
|
||||
sizeof(log_info.log_file_name));
|
||||
else
|
||||
break;
|
||||
if (my_delete(log_info.log_file_name, MYF(0)))
|
||||
{
|
||||
if (my_errno == ENOENT)
|
||||
{
|
||||
/* It's not fatal even if we can't delete a log file */
|
||||
if (thd)
|
||||
{
|
||||
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
|
||||
ER_LOG_PURGE_NO_FILE, ER(ER_LOG_PURGE_NO_FILE),
|
||||
log_info.log_file_name);
|
||||
}
|
||||
sql_print_information("Failed to delete file '%s'",
|
||||
log_info.log_file_name);
|
||||
my_errno= 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (thd)
|
||||
{
|
||||
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
|
||||
ER_BINLOG_PURGE_FATAL_ERR,
|
||||
"a problem with deleting %s; "
|
||||
"consider examining correspondence "
|
||||
"of your binlog index file "
|
||||
"to the actual binlog files",
|
||||
log_info.log_file_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
sql_print_information("Failed to delete log file '%s'",
|
||||
log_info.log_file_name);
|
||||
}
|
||||
error= LOG_INFO_FATAL;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
ha_binlog_index_purge_file(current_thd, log_info.log_file_name);
|
||||
}
|
||||
if (find_next_log(&log_info, 0))
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
If we get killed -9 here, the sysadmin would have to edit
|
||||
the log index file after restart - otherwise, this should be safe
|
||||
*/
|
||||
error= update_log_index(&log_info, 1);
|
||||
error= (to_log[0] ? purge_logs(to_log, 1, 0, 1, (ulonglong *) 0) : 0);
|
||||
|
||||
err:
|
||||
pthread_mutex_unlock(&LOCK_index);
|
||||
|
Reference in New Issue
Block a user