Bug#11763573 - 56299: MUTEX DEADLOCK WITH COM_BINLOG_DUMP, BINLOG PURGE, AND PROCESSLIST/KILL
The bug case is similar to one fixed earlier bug_49536. Deadlock involving LOCK_log appears to be possible because the purge running thread is holding LOCK_log whereas there is no sense of doing that and which fact was exploited by the earlier bug fixes. Fixed with small reengineering of rotate_and_purge(), adding two new methods and setting up a policy to execute those instead of the former rotate_and_purge(RP_LOCK_LOG_IS_ALREADY_LOCKED). The policy for using rotate(), purge() is that if the caller acquires LOCK_log itself, it should call rotate(), release the mutex and run purge(). Side effect of this patch is refining error message of bug@11747416 to print the whole path. mysql-test/suite/rpl/r/rpl_cant_read_event_incident.result: the file name printing is changed to a relative path instead of just the file name. mysql-test/suite/rpl/r/rpl_log_pos.result: the file name printing is changed to a relative path instead of just the file name. mysql-test/suite/rpl/r/rpl_manual_change_index_file.result: the file name printing is changed to a relative path instead of just the file name. mysql-test/suite/rpl/r/rpl_packet.result: the file name printing is changed to a relative path instead of just the file name. mysql-test/suite/rpl/r/rpl_rotate_purge_deadlock.result: new result file is added. mysql-test/suite/rpl/t/rpl_cant_read_event_incident.test: The test of that bug can't satisfy windows and unix backslash interpretation so windows execution is chosen to bypass. mysql-test/suite/rpl/t/rpl_rotate_purge_deadlock-master.opt: new opt file is added. mysql-test/suite/rpl/t/rpl_rotate_purge_deadlock.test: regression test is added as well as verification of a possible side effect of the fixes is tried. sql/log.cc: LOCK_log is never taken during execution of log purging routine. The former MYSQL_BIN_LOG::rotate_and_purge is made to necessarily acquiring and releasing LOCK_log. If caller takes the mutex itself it has to use a new rotate(), purge() methods combination and to never let purge() be run with LOCK_log grabbed. split apart to allow the caller to chose either it Simulation of concurrently rotating/purging threads is added. sql/log.h: new rotate(), purge() methods are added to be used instead of the former rotate_and_purge(RP_LOCK_LOG_IS_ALREADY_LOCKED). rotate_and_purge() signature is changed. Caller should not call rotate_and_purge() but rather {rotate(), purge()} if LOCK_log is acquired by it. sql/rpl_injector.cc: changes to reflect the new rotate_and_purge() signature. sql/sql_class.h: unnecessary constants are removed. sql/sql_parse.cc: changes to reflect the new rotate_and_purge() signature. sql/sql_reload.cc: changes to reflect the new rotate_and_purge() signature. sql/sql_repl.cc: followup for bug@11747416: the file name printing is changed to a relative path instead of just the file name.
This commit is contained in:
parent
bf456a8772
commit
95fdeb89c2
@ -11,7 +11,7 @@ reset slave;
|
|||||||
start slave;
|
start slave;
|
||||||
include/wait_for_slave_param.inc [Last_IO_Errno]
|
include/wait_for_slave_param.inc [Last_IO_Errno]
|
||||||
Last_IO_Errno = '1236'
|
Last_IO_Errno = '1236'
|
||||||
Last_IO_Error = 'Got fatal error 1236 from master when reading data from binary log: 'binlog truncated in the middle of event; consider out of disk space on master; the last event was read from 'master-bin.000001' at 316, the last byte read was read from 'master-bin.000001' at 335.''
|
Last_IO_Error = 'Got fatal error 1236 from master when reading data from binary log: 'binlog truncated in the middle of event; consider out of disk space on master; the last event was read from './master-bin.000001' at 316, the last byte read was read from './master-bin.000001' at 335.''
|
||||||
reset master;
|
reset master;
|
||||||
stop slave;
|
stop slave;
|
||||||
reset slave;
|
reset slave;
|
||||||
|
@ -9,7 +9,7 @@ change master to master_log_pos=MASTER_LOG_POS;
|
|||||||
Read_Master_Log_Pos = '75'
|
Read_Master_Log_Pos = '75'
|
||||||
start slave;
|
start slave;
|
||||||
include/wait_for_slave_io_error.inc [errno=1236]
|
include/wait_for_slave_io_error.inc [errno=1236]
|
||||||
Last_IO_Error = 'Got fatal error 1236 from master when reading data from binary log: 'log event entry exceeded max_allowed_packet; Increase max_allowed_packet on master; the last event was read from 'master-bin.000001' at 75, the last byte read was read from 'master-bin.000001' at 94.''
|
Last_IO_Error = 'Got fatal error 1236 from master when reading data from binary log: 'log event entry exceeded max_allowed_packet; Increase max_allowed_packet on master; the last event was read from './master-bin.000001' at 75, the last byte read was read from './master-bin.000001' at 94.''
|
||||||
include/stop_slave_sql.inc
|
include/stop_slave_sql.inc
|
||||||
show master status;
|
show master status;
|
||||||
File Position Binlog_Do_DB Binlog_Ignore_DB
|
File Position Binlog_Do_DB Binlog_Ignore_DB
|
||||||
|
@ -5,7 +5,7 @@ CREATE TABLE t1(c1 INT);
|
|||||||
FLUSH LOGS;
|
FLUSH LOGS;
|
||||||
call mtr.add_suppression('Got fatal error 1236 from master when reading data from binary log: .*could not find next log');
|
call mtr.add_suppression('Got fatal error 1236 from master when reading data from binary log: .*could not find next log');
|
||||||
include/wait_for_slave_io_error.inc [errno=1236]
|
include/wait_for_slave_io_error.inc [errno=1236]
|
||||||
Last_IO_Error = 'Got fatal error 1236 from master when reading data from binary log: 'could not find next log; the last event was read from 'master-bin.000002' at 237, the last byte read was read from 'master-bin.000002' at 237.''
|
Last_IO_Error = 'Got fatal error 1236 from master when reading data from binary log: 'could not find next log; the last event was read from './master-bin.000002' at 237, the last byte read was read from './master-bin.000002' at 237.''
|
||||||
CREATE TABLE t2(c1 INT);
|
CREATE TABLE t2(c1 INT);
|
||||||
FLUSH LOGS;
|
FLUSH LOGS;
|
||||||
CREATE TABLE t3(c1 INT);
|
CREATE TABLE t3(c1 INT);
|
||||||
|
@ -37,7 +37,7 @@ DROP TABLE t1;
|
|||||||
CREATE TABLE t1 (f1 int PRIMARY KEY, f2 LONGTEXT, f3 LONGTEXT) ENGINE=MyISAM;
|
CREATE TABLE t1 (f1 int PRIMARY KEY, f2 LONGTEXT, f3 LONGTEXT) ENGINE=MyISAM;
|
||||||
INSERT INTO t1(f1, f2, f3) VALUES(1, REPEAT('a', @@global.max_allowed_packet), REPEAT('b', @@global.max_allowed_packet));
|
INSERT INTO t1(f1, f2, f3) VALUES(1, REPEAT('a', @@global.max_allowed_packet), REPEAT('b', @@global.max_allowed_packet));
|
||||||
include/wait_for_slave_io_error.inc [errno=1236]
|
include/wait_for_slave_io_error.inc [errno=1236]
|
||||||
Last_IO_Error = 'Got fatal error 1236 from master when reading data from binary log: 'log event entry exceeded max_allowed_packet; Increase max_allowed_packet on master; the last event was read from 'master-bin.000001' at 463, the last byte read was read from 'master-bin.000001' at 482.''
|
Last_IO_Error = 'Got fatal error 1236 from master when reading data from binary log: 'log event entry exceeded max_allowed_packet; Increase max_allowed_packet on master; the last event was read from './master-bin.000001' at 463, the last byte read was read from './master-bin.000001' at 482.''
|
||||||
STOP SLAVE;
|
STOP SLAVE;
|
||||||
RESET SLAVE;
|
RESET SLAVE;
|
||||||
RESET MASTER;
|
RESET MASTER;
|
||||||
|
30
mysql-test/suite/rpl/r/rpl_rotate_purge_deadlock.result
Normal file
30
mysql-test/suite/rpl/r/rpl_rotate_purge_deadlock.result
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
include/master-slave.inc
|
||||||
|
[connection master]
|
||||||
|
show binary logs;
|
||||||
|
Log_name File_size
|
||||||
|
master-bin.000001 #
|
||||||
|
create table t1 (f text) engine=innodb;
|
||||||
|
SET DEBUG_SYNC = 'at_purge_logs_before_date WAIT_FOR rotated';
|
||||||
|
insert into t1 set f=repeat('a', 4096);
|
||||||
|
*** there must be two logs in the list ***
|
||||||
|
show binary logs;
|
||||||
|
Log_name File_size
|
||||||
|
master-bin.000001 #
|
||||||
|
master-bin.000002 #
|
||||||
|
insert into t1 set f=repeat('b', 4096);
|
||||||
|
*** there must be three logs in the list ***
|
||||||
|
show binary logs;
|
||||||
|
Log_name File_size
|
||||||
|
master-bin.000001 #
|
||||||
|
master-bin.000002 #
|
||||||
|
master-bin.000003 #
|
||||||
|
SET DEBUG_SYNC = 'now SIGNAL rotated';
|
||||||
|
SET DEBUG_SYNC = 'RESET';
|
||||||
|
SET DEBUG_SYNC = 'RESET';
|
||||||
|
SET DEBUG_SYNC = 'at_purge_logs_before_date WAIT_FOR rotated';
|
||||||
|
insert into t1 set f=repeat('b', 4096);
|
||||||
|
SET DEBUG_SYNC = 'now SIGNAL rotated';
|
||||||
|
SET DEBUG_SYNC = 'RESET';
|
||||||
|
SET DEBUG_SYNC = 'RESET';
|
||||||
|
drop table t1;
|
||||||
|
include/rpl_end.inc
|
@ -14,6 +14,11 @@
|
|||||||
|
|
||||||
--source include/master-slave.inc
|
--source include/master-slave.inc
|
||||||
--source include/have_binlog_format_mixed.inc
|
--source include/have_binlog_format_mixed.inc
|
||||||
|
#
|
||||||
|
# Bug#13050593 swallows `\' from Last_IO_Error
|
||||||
|
# todo: uncomment the filter once the bug is fixed.
|
||||||
|
#
|
||||||
|
--source include/not_windows.inc
|
||||||
|
|
||||||
call mtr.add_suppression("Error in Log_event::read_log_event()");
|
call mtr.add_suppression("Error in Log_event::read_log_event()");
|
||||||
|
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
--max-binlog-size=4k --expire-logs-days=1
|
92
mysql-test/suite/rpl/t/rpl_rotate_purge_deadlock.test
Normal file
92
mysql-test/suite/rpl/t/rpl_rotate_purge_deadlock.test
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
#
|
||||||
|
# Bug#11763573 - 56299: MUTEX DEADLOCK WITH COM_BINLOG_DUMP, BINLOG PURGE, AND PROCESSLIST/KILL
|
||||||
|
#
|
||||||
|
source include/master-slave.inc;
|
||||||
|
source include/have_debug_sync.inc;
|
||||||
|
source include/have_binlog_format_row.inc;
|
||||||
|
source include/have_innodb.inc;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Testing that execution of two concurrent INSERTing connections both
|
||||||
|
# triggering the binlog rotation is correct even though their execution
|
||||||
|
# is interleaved.
|
||||||
|
# The test makes the first connection to complete the rotation part
|
||||||
|
# and yields control to the second connection that rotates as well and
|
||||||
|
# gets first on purging. And the fact of interleaving does not create
|
||||||
|
# any issue.
|
||||||
|
#
|
||||||
|
|
||||||
|
connection master;
|
||||||
|
source include/show_binary_logs.inc;
|
||||||
|
create table t1 (f text) engine=innodb;
|
||||||
|
SET DEBUG_SYNC = 'at_purge_logs_before_date WAIT_FOR rotated';
|
||||||
|
send insert into t1 set f=repeat('a', 4096);
|
||||||
|
|
||||||
|
connection master1;
|
||||||
|
|
||||||
|
let $wait_condition=
|
||||||
|
SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST
|
||||||
|
WHERE STATE like "debug sync point: at_purge_logs_before_date%";
|
||||||
|
--source include/wait_condition.inc
|
||||||
|
|
||||||
|
--echo *** there must be two logs in the list ***
|
||||||
|
source include/show_binary_logs.inc;
|
||||||
|
|
||||||
|
insert into t1 set f=repeat('b', 4096);
|
||||||
|
|
||||||
|
--echo *** there must be three logs in the list ***
|
||||||
|
source include/show_binary_logs.inc;
|
||||||
|
|
||||||
|
SET DEBUG_SYNC = 'now SIGNAL rotated';
|
||||||
|
SET DEBUG_SYNC = 'RESET';
|
||||||
|
|
||||||
|
# the first connection finally completes its INSERT
|
||||||
|
connection master;
|
||||||
|
reap;
|
||||||
|
SET DEBUG_SYNC = 'RESET';
|
||||||
|
|
||||||
|
sync_slave_with_master;
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Testing the reported deadlock involving DUMP, KILL and INSERT threads
|
||||||
|
#
|
||||||
|
|
||||||
|
connection master;
|
||||||
|
SET DEBUG_SYNC = 'at_purge_logs_before_date WAIT_FOR rotated';
|
||||||
|
send insert into t1 set f=repeat('b', 4096);
|
||||||
|
|
||||||
|
connection master1;
|
||||||
|
|
||||||
|
# make sure INSERT reaches waiting point
|
||||||
|
let $wait_condition=
|
||||||
|
SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST
|
||||||
|
WHERE STATE like "debug sync point: at_purge_logs_before_date%";
|
||||||
|
--source include/wait_condition.inc
|
||||||
|
|
||||||
|
# find and kill DUMP thread
|
||||||
|
let $_tid= `select id from information_schema.processlist where command = 'Binlog Dump' limit 1`;
|
||||||
|
--disable_query_log
|
||||||
|
eval kill query $_tid;
|
||||||
|
--enable_query_log
|
||||||
|
|
||||||
|
#
|
||||||
|
# Now the proof is that the new DUMP thread has executed
|
||||||
|
# a critical section of the deadlock without any regression and is UP
|
||||||
|
#
|
||||||
|
let $wait_condition=
|
||||||
|
SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST
|
||||||
|
WHERE command = 'Binlog Dump' and STATE like "Master has sent all binlog to slave%";
|
||||||
|
--source include/wait_condition.inc
|
||||||
|
|
||||||
|
SET DEBUG_SYNC = 'now SIGNAL rotated';
|
||||||
|
SET DEBUG_SYNC = 'RESET';
|
||||||
|
|
||||||
|
connection master;
|
||||||
|
reap;
|
||||||
|
SET DEBUG_SYNC = 'RESET';
|
||||||
|
drop table t1;
|
||||||
|
|
||||||
|
sync_slave_with_master;
|
||||||
|
|
||||||
|
--source include/rpl_end.inc
|
131
sql/log.cc
131
sql/log.cc
@ -49,7 +49,7 @@
|
|||||||
|
|
||||||
#include "sql_plugin.h"
|
#include "sql_plugin.h"
|
||||||
#include "rpl_handler.h"
|
#include "rpl_handler.h"
|
||||||
|
#include "debug_sync.h"
|
||||||
/* max size of the log message */
|
/* max size of the log message */
|
||||||
#define MAX_LOG_BUFFER_SIZE 1024
|
#define MAX_LOG_BUFFER_SIZE 1024
|
||||||
#define MAX_TIME_SIZE 32
|
#define MAX_TIME_SIZE 32
|
||||||
@ -5002,19 +5002,29 @@ err:
|
|||||||
{
|
{
|
||||||
bool synced;
|
bool synced;
|
||||||
if ((error= flush_and_sync(&synced)))
|
if ((error= flush_and_sync(&synced)))
|
||||||
goto unlock;
|
{
|
||||||
|
mysql_mutex_unlock(&LOCK_log);
|
||||||
if ((error= RUN_HOOK(binlog_storage, after_flush,
|
}
|
||||||
|
else if ((error= RUN_HOOK(binlog_storage, after_flush,
|
||||||
(thd, log_file_name, file->pos_in_file, synced))))
|
(thd, log_file_name, file->pos_in_file, synced))))
|
||||||
{
|
{
|
||||||
sql_print_error("Failed to run 'after_flush' hooks");
|
sql_print_error("Failed to run 'after_flush' hooks");
|
||||||
goto unlock;
|
mysql_mutex_unlock(&LOCK_log);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bool check_purge;
|
||||||
|
signal_update();
|
||||||
|
error= rotate(false, &check_purge);
|
||||||
|
mysql_mutex_unlock(&LOCK_log);
|
||||||
|
if (!error && check_purge)
|
||||||
|
purge();
|
||||||
}
|
}
|
||||||
signal_update();
|
|
||||||
rotate_and_purge(RP_LOCK_LOG_IS_ALREADY_LOCKED);
|
|
||||||
}
|
}
|
||||||
unlock:
|
else
|
||||||
mysql_mutex_unlock(&LOCK_log);
|
{
|
||||||
|
mysql_mutex_unlock(&LOCK_log);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
@ -5100,25 +5110,29 @@ bool general_log_write(THD *thd, enum enum_server_command command,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
The method executes rotation when LOCK_log is already acquired
|
||||||
|
by the caller.
|
||||||
|
|
||||||
|
@param force_rotate caller can request the log rotation
|
||||||
|
@param check_purge is set to true if rotation took place
|
||||||
|
|
||||||
@note
|
@note
|
||||||
If rotation fails, for instance the server was unable
|
If rotation fails, for instance the server was unable
|
||||||
to create a new log file, we still try to write an
|
to create a new log file, we still try to write an
|
||||||
incident event to the current log.
|
incident event to the current log.
|
||||||
|
|
||||||
@retval
|
@retval
|
||||||
nonzero - error
|
nonzero - error in rotating routine.
|
||||||
*/
|
*/
|
||||||
int MYSQL_BIN_LOG::rotate_and_purge(uint flags)
|
int MYSQL_BIN_LOG::rotate(bool force_rotate, bool* check_purge)
|
||||||
{
|
{
|
||||||
int error= 0;
|
int error= 0;
|
||||||
DBUG_ENTER("MYSQL_BIN_LOG::rotate_and_purge");
|
DBUG_ENTER("MYSQL_BIN_LOG::rotate");
|
||||||
#ifdef HAVE_REPLICATION
|
|
||||||
bool check_purge= false;
|
//todo: fix the macro def and restore safe_mutex_assert_owner(&LOCK_log);
|
||||||
#endif
|
*check_purge= false;
|
||||||
if (!(flags & RP_LOCK_LOG_IS_ALREADY_LOCKED))
|
|
||||||
mysql_mutex_lock(&LOCK_log);
|
if (force_rotate || (my_b_tell(&log_file) >= (my_off_t) max_size))
|
||||||
if ((flags & RP_FORCE_ROTATE) ||
|
|
||||||
(my_b_tell(&log_file) >= (my_off_t) max_size))
|
|
||||||
{
|
{
|
||||||
if ((error= new_file_without_locking()))
|
if ((error= new_file_without_locking()))
|
||||||
/**
|
/**
|
||||||
@ -5133,24 +5147,59 @@ int MYSQL_BIN_LOG::rotate_and_purge(uint flags)
|
|||||||
if (!write_incident(current_thd, FALSE))
|
if (!write_incident(current_thd, FALSE))
|
||||||
flush_and_sync(0);
|
flush_and_sync(0);
|
||||||
|
|
||||||
#ifdef HAVE_REPLICATION
|
*check_purge= true;
|
||||||
check_purge= true;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
if (!(flags & RP_LOCK_LOG_IS_ALREADY_LOCKED))
|
DBUG_RETURN(error);
|
||||||
mysql_mutex_unlock(&LOCK_log);
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
The method executes logs purging routine.
|
||||||
|
|
||||||
|
@retval
|
||||||
|
nonzero - error in rotating routine.
|
||||||
|
*/
|
||||||
|
void MYSQL_BIN_LOG::purge()
|
||||||
|
{
|
||||||
#ifdef HAVE_REPLICATION
|
#ifdef HAVE_REPLICATION
|
||||||
/*
|
if (expire_logs_days)
|
||||||
NOTE: Run purge_logs wo/ holding LOCK_log
|
|
||||||
as it otherwise will deadlock in ndbcluster_binlog_index_purge_file
|
|
||||||
*/
|
|
||||||
if (!error && check_purge && expire_logs_days)
|
|
||||||
{
|
{
|
||||||
|
DEBUG_SYNC(current_thd, "at_purge_logs_before_date");
|
||||||
time_t purge_time= my_time(0) - expire_logs_days*24*60*60;
|
time_t purge_time= my_time(0) - expire_logs_days*24*60*60;
|
||||||
if (purge_time >= 0)
|
if (purge_time >= 0)
|
||||||
|
{
|
||||||
purge_logs_before_date(purge_time);
|
purge_logs_before_date(purge_time);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
The method is a shortcut of @c rotate() and @c purge().
|
||||||
|
LOCK_log is acquired prior to rotate and is released after it.
|
||||||
|
|
||||||
|
@param force_rotate caller can request the log rotation
|
||||||
|
|
||||||
|
@retval
|
||||||
|
nonzero - error in rotating routine.
|
||||||
|
*/
|
||||||
|
int MYSQL_BIN_LOG::rotate_and_purge(bool force_rotate)
|
||||||
|
{
|
||||||
|
int error= 0;
|
||||||
|
DBUG_ENTER("MYSQL_BIN_LOG::rotate_and_purge");
|
||||||
|
bool check_purge= false;
|
||||||
|
|
||||||
|
//todo: fix the macro def and restore safe_mutex_assert_not_owner(&LOCK_log);
|
||||||
|
mysql_mutex_lock(&LOCK_log);
|
||||||
|
error= rotate(force_rotate, &check_purge);
|
||||||
|
/*
|
||||||
|
NOTE: Run purge_logs wo/ holding LOCK_log because it does not need
|
||||||
|
the mutex. Otherwise causes various deadlocks.
|
||||||
|
*/
|
||||||
|
mysql_mutex_unlock(&LOCK_log);
|
||||||
|
|
||||||
|
if (!error && check_purge)
|
||||||
|
purge();
|
||||||
|
|
||||||
DBUG_RETURN(error);
|
DBUG_RETURN(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5352,10 +5401,17 @@ bool MYSQL_BIN_LOG::write_incident(THD *thd, bool lock)
|
|||||||
{
|
{
|
||||||
if (!error && !(error= flush_and_sync(0)))
|
if (!error && !(error= flush_and_sync(0)))
|
||||||
{
|
{
|
||||||
|
bool check_purge= false;
|
||||||
signal_update();
|
signal_update();
|
||||||
error= rotate_and_purge(RP_LOCK_LOG_IS_ALREADY_LOCKED);
|
error= rotate(false, &check_purge);
|
||||||
|
mysql_mutex_unlock(&LOCK_log);
|
||||||
|
if (!error && check_purge)
|
||||||
|
purge();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mysql_mutex_unlock(&LOCK_log);
|
||||||
}
|
}
|
||||||
mysql_mutex_unlock(&LOCK_log);
|
|
||||||
}
|
}
|
||||||
DBUG_RETURN(error);
|
DBUG_RETURN(error);
|
||||||
}
|
}
|
||||||
@ -5388,11 +5444,13 @@ bool MYSQL_BIN_LOG::write(THD *thd, IO_CACHE *cache, Log_event *commit_event,
|
|||||||
bool incident)
|
bool incident)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("MYSQL_BIN_LOG::write(THD *, IO_CACHE *, Log_event *)");
|
DBUG_ENTER("MYSQL_BIN_LOG::write(THD *, IO_CACHE *, Log_event *)");
|
||||||
mysql_mutex_lock(&LOCK_log);
|
|
||||||
|
|
||||||
DBUG_ASSERT(is_open());
|
DBUG_ASSERT(is_open());
|
||||||
if (likely(is_open())) // Should always be true
|
if (likely(is_open())) // Should always be true
|
||||||
{
|
{
|
||||||
|
bool check_purge;
|
||||||
|
|
||||||
|
mysql_mutex_lock(&LOCK_log);
|
||||||
/*
|
/*
|
||||||
We only bother to write to the binary log if there is anything
|
We only bother to write to the binary log if there is anything
|
||||||
to write.
|
to write.
|
||||||
@ -5460,12 +5518,17 @@ bool MYSQL_BIN_LOG::write(THD *thd, IO_CACHE *cache, Log_event *commit_event,
|
|||||||
mysql_mutex_lock(&LOCK_prep_xids);
|
mysql_mutex_lock(&LOCK_prep_xids);
|
||||||
prepared_xids++;
|
prepared_xids++;
|
||||||
mysql_mutex_unlock(&LOCK_prep_xids);
|
mysql_mutex_unlock(&LOCK_prep_xids);
|
||||||
|
mysql_mutex_unlock(&LOCK_log);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if (rotate_and_purge(RP_LOCK_LOG_IS_ALREADY_LOCKED))
|
{
|
||||||
|
if (rotate(false, &check_purge))
|
||||||
goto err;
|
goto err;
|
||||||
|
mysql_mutex_unlock(&LOCK_log);
|
||||||
|
if (check_purge)
|
||||||
|
purge();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
mysql_mutex_unlock(&LOCK_log);
|
|
||||||
|
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
|
|
||||||
|
@ -455,7 +455,9 @@ public:
|
|||||||
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);
|
||||||
int rotate_and_purge(uint flags);
|
int rotate(bool force_rotate, bool* check_purge);
|
||||||
|
void purge();
|
||||||
|
int rotate_and_purge(bool force_rotate);
|
||||||
/**
|
/**
|
||||||
Flush binlog cache and synchronize to disk.
|
Flush binlog cache and synchronize to disk.
|
||||||
|
|
||||||
|
@ -237,7 +237,7 @@ int injector::record_incident(THD *thd, Incident incident)
|
|||||||
Incident_log_event ev(thd, incident);
|
Incident_log_event ev(thd, incident);
|
||||||
if (int error= mysql_bin_log.write(&ev))
|
if (int error= mysql_bin_log.write(&ev))
|
||||||
return error;
|
return error;
|
||||||
return mysql_bin_log.rotate_and_purge(RP_FORCE_ROTATE);
|
return mysql_bin_log.rotate_and_purge(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
int injector::record_incident(THD *thd, Incident incident, LEX_STRING const message)
|
int injector::record_incident(THD *thd, Incident incident, LEX_STRING const message)
|
||||||
@ -245,5 +245,5 @@ int injector::record_incident(THD *thd, Incident incident, LEX_STRING const mess
|
|||||||
Incident_log_event ev(thd, incident, message);
|
Incident_log_event ev(thd, incident, message);
|
||||||
if (int error= mysql_bin_log.write(&ev))
|
if (int error= mysql_bin_log.write(&ev))
|
||||||
return error;
|
return error;
|
||||||
return mysql_bin_log.rotate_and_purge(RP_FORCE_ROTATE);
|
return mysql_bin_log.rotate_and_purge(true);
|
||||||
}
|
}
|
||||||
|
@ -161,9 +161,6 @@ typedef struct st_user_var_events
|
|||||||
bool unsigned_flag;
|
bool unsigned_flag;
|
||||||
} BINLOG_USER_VAR_EVENT;
|
} BINLOG_USER_VAR_EVENT;
|
||||||
|
|
||||||
#define RP_LOCK_LOG_IS_ALREADY_LOCKED 1
|
|
||||||
#define RP_FORCE_ROTATE 2
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The COPY_INFO structure is used by INSERT/REPLACE code.
|
The COPY_INFO structure is used by INSERT/REPLACE code.
|
||||||
The schema of the row counting by the INSERT/INSERT ... ON DUPLICATE KEY
|
The schema of the row counting by the INSERT/INSERT ... ON DUPLICATE KEY
|
||||||
|
@ -2861,7 +2861,7 @@ end_with_restore_list:
|
|||||||
{
|
{
|
||||||
Incident_log_event ev(thd, incident);
|
Incident_log_event ev(thd, incident);
|
||||||
(void) mysql_bin_log.write(&ev); /* error is ignored */
|
(void) mysql_bin_log.write(&ev); /* error is ignored */
|
||||||
if (mysql_bin_log.rotate_and_purge(RP_FORCE_ROTATE))
|
if (mysql_bin_log.rotate_and_purge(true))
|
||||||
{
|
{
|
||||||
res= 1;
|
res= 1;
|
||||||
break;
|
break;
|
||||||
|
@ -141,7 +141,7 @@ bool reload_acl_and_cache(THD *thd, unsigned long options,
|
|||||||
tmp_write_to_binlog= 0;
|
tmp_write_to_binlog= 0;
|
||||||
if (mysql_bin_log.is_open())
|
if (mysql_bin_log.is_open())
|
||||||
{
|
{
|
||||||
if (mysql_bin_log.rotate_and_purge(RP_FORCE_ROTATE))
|
if (mysql_bin_log.rotate_and_purge(true))
|
||||||
*write_to_binlog= -1;
|
*write_to_binlog= -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1030,12 +1030,9 @@ err:
|
|||||||
detailing the fatal error message with coordinates
|
detailing the fatal error message with coordinates
|
||||||
of the last position read.
|
of the last position read.
|
||||||
*/
|
*/
|
||||||
char b_start[FN_REFLEN], b_end[FN_REFLEN];
|
|
||||||
fn_format(b_start, coord->file_name, "", "", MY_REPLACE_DIR);
|
|
||||||
fn_format(b_end, log_file_name, "", "", MY_REPLACE_DIR);
|
|
||||||
my_snprintf(error_text, sizeof(error_text), fmt, errmsg,
|
my_snprintf(error_text, sizeof(error_text), fmt, errmsg,
|
||||||
b_start, (llstr(coord->pos, llbuff1), llbuff1),
|
coord->file_name, (llstr(coord->pos, llbuff1), llbuff1),
|
||||||
b_end, (llstr(my_b_tell(&log), llbuff2), llbuff2));
|
log_file_name, (llstr(my_b_tell(&log), llbuff2), llbuff2));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
strcpy(error_text, errmsg);
|
strcpy(error_text, errmsg);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user