Commit aaefb52d authored by Luis Soares's avatar Luis Soares

BUG#46166: MYSQL_BIN_LOG::new_file_impl is not propagating error

           when generating new name.
      
If find_uniq_filename returns an error, then this error is not
being propagated upwards, and execution does not report error to
the user (although a entry in the error log is generated).
                  
Additionally, some more errors were ignored in new_file_impl:
- when writing the rotate event
- when reopening the index and binary log file
                  
This patch addresses this by propagating the error up in the
execution stack. Furthermore, when rotation of the binary log
fails, an incident event is written, because there may be a
chance that some changes for a given statement, were not properly
logged. For example, in SBR, LOAD DATA INFILE statement requires
more than one event to be logged, should rotation fail while
logging part of the LOAD DATA events, then the logged data would
become inconsistent with the data in the storage engine.
parent 2419cec9
#
# Takes the flag as an argument:
# -- let $io_thd_injection_fault_flag=+d,fault_injection_new_file_rotate_event
# -- source include/io_thd_fault_injection.inc
#
SET @old_debug=@@global.debug;
-- disable_warnings
-- source include/stop_slave.inc
-- enable_warnings
-- eval SET GLOBAL debug="+d,$io_thd_injection_fault_flag"
START SLAVE io_thread;
-- source include/wait_for_slave_io_to_stop.inc
-- source include/wait_for_slave_io_error.inc
-- eval SET GLOBAL debug="-d,$io_thd_injection_fault_flag"
SET GLOBAL debug=@old_debug;
# restart because slave is in bad shape
-- source include/restart_mysqld.inc
# Write file to make mysql-test-run.pl expect the "crash", but don't start # Write file to make mysql-test-run.pl expect the "crash", but don't start
# it until it's told to # it until it's told to
--exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect --let $_server_id= `SELECT @@server_id`
--let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/mysqld.$_server_id.expect
--exec echo "wait" > $_expect_file_name
# Send shutdown to the connected server and give # Send shutdown to the connected server and give
# it 10 seconds to die before zapping it # it 10 seconds to die before zapping it
shutdown_server 10; shutdown_server 10;
# Write file to make mysql-test-run.pl start up the server again # Write file to make mysql-test-run.pl start up the server again
--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect --exec echo "restart" > $_expect_file_name
# Turn on reconnect # Turn on reconnect
--enable_reconnect --enable_reconnect
......
...@@ -2,7 +2,9 @@ call mtr.add_suppression('Attempting backtrace'); ...@@ -2,7 +2,9 @@ call mtr.add_suppression('Attempting backtrace');
call mtr.add_suppression('MSYQL_BIN_LOG::purge_logs failed to process registered files that would be purged.'); call mtr.add_suppression('MSYQL_BIN_LOG::purge_logs failed to process registered files that would be purged.');
call mtr.add_suppression('MSYQL_BIN_LOG::open failed to sync the index file'); call mtr.add_suppression('MSYQL_BIN_LOG::open failed to sync the index file');
call mtr.add_suppression('Turning logging off for the whole duration of the MySQL server process.'); call mtr.add_suppression('Turning logging off for the whole duration of the MySQL server process.');
call mtr.add_suppression('Could not open .*');
call mtr.add_suppression('MSYQL_BIN_LOG::purge_logs failed to clean registers before purging logs.'); call mtr.add_suppression('MSYQL_BIN_LOG::purge_logs failed to clean registers before purging logs.');
RESET MASTER;
flush logs; flush logs;
flush logs; flush logs;
flush logs; flush logs;
...@@ -116,11 +118,31 @@ master-bin.000011 ...@@ -116,11 +118,31 @@ master-bin.000011
# This should put the server in unsafe state and stop # This should put the server in unsafe state and stop
# accepting any command. If we inject a fault at this # accepting any command. If we inject a fault at this
# point and continue the execution the server crashes. # point and continue the execution the server crashes.
# Besides the flush command does not report an error.
# #
SET @index=LOAD_FILE('MYSQLTEST_VARDIR/mysqld.1/data//master-bin.index');
SELECT @index;
@index
master-bin.000006
master-bin.000007
master-bin.000008
master-bin.000009
master-bin.000010
master-bin.000011
# fault_injection_registering_index # fault_injection_registering_index
SET SESSION debug="+d,fault_injection_registering_index"; SET SESSION debug="+d,fault_injection_registering_index";
flush logs; flush logs;
ERROR HY000: Can't open file: './master-bin.000012' (errno: 1)
SET @index=LOAD_FILE('MYSQLTEST_VARDIR/mysqld.1/data//master-bin.index');
SELECT @index;
@index
master-bin.000006
master-bin.000007
master-bin.000008
master-bin.000009
master-bin.000010
master-bin.000011
SET @index=LOAD_FILE('MYSQLTEST_VARDIR/mysqld.1/data//master-bin.index'); SET @index=LOAD_FILE('MYSQLTEST_VARDIR/mysqld.1/data//master-bin.index');
SELECT @index; SELECT @index;
@index @index
...@@ -135,6 +157,18 @@ master-bin.000012 ...@@ -135,6 +157,18 @@ master-bin.000012
# fault_injection_updating_index # fault_injection_updating_index
SET SESSION debug="+d,fault_injection_updating_index"; SET SESSION debug="+d,fault_injection_updating_index";
flush logs; flush logs;
ERROR HY000: Can't open file: './master-bin.000013' (errno: 1)
SET @index=LOAD_FILE('MYSQLTEST_VARDIR/mysqld.1/data//master-bin.index');
SELECT @index;
@index
master-bin.000006
master-bin.000007
master-bin.000008
master-bin.000009
master-bin.000010
master-bin.000011
master-bin.000012
SET @index=LOAD_FILE('MYSQLTEST_VARDIR/mysqld.1/data//master-bin.index'); SET @index=LOAD_FILE('MYSQLTEST_VARDIR/mysqld.1/data//master-bin.index');
SELECT @index; SELECT @index;
@index @index
......
...@@ -10,9 +10,12 @@ call mtr.add_suppression('Attempting backtrace'); ...@@ -10,9 +10,12 @@ call mtr.add_suppression('Attempting backtrace');
call mtr.add_suppression('MSYQL_BIN_LOG::purge_logs failed to process registered files that would be purged.'); call mtr.add_suppression('MSYQL_BIN_LOG::purge_logs failed to process registered files that would be purged.');
call mtr.add_suppression('MSYQL_BIN_LOG::open failed to sync the index file'); call mtr.add_suppression('MSYQL_BIN_LOG::open failed to sync the index file');
call mtr.add_suppression('Turning logging off for the whole duration of the MySQL server process.'); call mtr.add_suppression('Turning logging off for the whole duration of the MySQL server process.');
call mtr.add_suppression('Could not open .*');
call mtr.add_suppression('MSYQL_BIN_LOG::purge_logs failed to clean registers before purging logs.'); call mtr.add_suppression('MSYQL_BIN_LOG::purge_logs failed to clean registers before purging logs.');
let $old=`select @@debug`; let $old=`select @@debug`;
RESET MASTER;
let $MYSQLD_DATADIR= `select @@datadir`; let $MYSQLD_DATADIR= `select @@datadir`;
let $INDEX=$MYSQLD_DATADIR/master-bin.index; let $INDEX=$MYSQLD_DATADIR/master-bin.index;
...@@ -205,12 +208,25 @@ SELECT @index; ...@@ -205,12 +208,25 @@ SELECT @index;
--echo # This should put the server in unsafe state and stop --echo # This should put the server in unsafe state and stop
--echo # accepting any command. If we inject a fault at this --echo # accepting any command. If we inject a fault at this
--echo # point and continue the execution the server crashes. --echo # point and continue the execution the server crashes.
--echo # Besides the flush command does not report an error.
--echo # --echo #
--chmod 0644 $INDEX
-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
-- eval SET @index=LOAD_FILE('$index')
-- replace_regex /\.[\\\/]master/master/
SELECT @index;
--echo # fault_injection_registering_index --echo # fault_injection_registering_index
SET SESSION debug="+d,fault_injection_registering_index"; SET SESSION debug="+d,fault_injection_registering_index";
-- error ER_CANT_OPEN_FILE
flush logs; flush logs;
--chmod 0644 $INDEX
-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
-- eval SET @index=LOAD_FILE('$index')
-- replace_regex /\.[\\\/]master/master/
SELECT @index;
--source include/restart_mysqld.inc --source include/restart_mysqld.inc
--chmod 0644 $INDEX --chmod 0644 $INDEX
...@@ -221,7 +237,15 @@ SELECT @index; ...@@ -221,7 +237,15 @@ SELECT @index;
--echo # fault_injection_updating_index --echo # fault_injection_updating_index
SET SESSION debug="+d,fault_injection_updating_index"; SET SESSION debug="+d,fault_injection_updating_index";
-- error ER_CANT_OPEN_FILE
flush logs; flush logs;
--chmod 0644 $INDEX
-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
-- eval SET @index=LOAD_FILE('$index')
-- replace_regex /\.[\\\/]master/master/
SELECT @index;
--source include/restart_mysqld.inc --source include/restart_mysqld.inc
--chmod 0644 $INDEX --chmod 0644 $INDEX
......
stop slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
start slave;
#######################################################################
####################### PART 1: MASTER TESTS ##########################
#######################################################################
include/stop_slave.inc
call mtr.add_suppression("Can't generate a unique log-filename");
call mtr.add_suppression("Writing one row to the row-based binary log failed.*");
call mtr.add_suppression("Error writing file .*");
SET @old_debug= @@global.debug;
SELECT repeat('x',8192) INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/bug_46166.data';
SELECT repeat('x',10) INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/bug_46166-2.data';
RESET MASTER;
###################### TEST #1
FLUSH LOGS;
# assert: must show two binlogs
show binary logs;
Log_name File_size
master-bin.000001 #
master-bin.000002 #
###################### TEST #2
RESET MASTER;
SET GLOBAL debug="+d,error_unique_log_filename";
FLUSH LOGS;
ERROR HY000: Can't generate a unique log-filename master-bin.(1-999)
# assert: must show one binlog
show binary logs;
Log_name File_size
master-bin.000001 #
SET GLOBAL debug="";
RESET MASTER;
###################### TEST #3
CREATE TABLE t1 (a int);
CREATE TABLE t2 (a TEXT) Engine=InnoDB;
CREATE TABLE t4 (a TEXT);
INSERT INTO t1 VALUES (1);
RESET MASTER;
LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/bug_46166.data' INTO TABLE t2;
# assert: must show two binlog
show binary logs;
Log_name File_size
master-bin.000001 #
master-bin.000002 #
SET GLOBAL debug="-d,error_unique_log_filename";
DELETE FROM t2;
RESET MASTER;
###################### TEST #4
SET GLOBAL debug="+d,error_unique_log_filename";
LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/bug_46166.data' INTO TABLE t2;
ERROR HY000: Can't generate a unique log-filename master-bin.(1-999)
# assert: must show one entry
SELECT count(*) FROM t2;
count(*)
1
SET GLOBAL debug="-d,error_unique_log_filename";
DELETE FROM t2;
RESET MASTER;
###################### TEST #5
SET GLOBAL debug="+d,error_unique_log_filename";
LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/bug_46166-2.data' INTO TABLE t2;
# assert: must show one entry
SELECT count(*) FROM t2;
count(*)
1
SET GLOBAL debug="-d,error_unique_log_filename";
DELETE FROM t2;
RESET MASTER;
###################### TEST #6
SET GLOBAL debug="+d,error_unique_log_filename";
SET AUTOCOMMIT=0;
INSERT INTO t2 VALUES ('muse');
LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/bug_46166.data' INTO TABLE t2;
INSERT INTO t2 VALUES ('muse');
COMMIT;
ERROR HY000: Can't generate a unique log-filename master-bin.(1-999)
# assert: must show three entries
SELECT count(*) FROM t2;
count(*)
3
SET AUTOCOMMIT= 1;
SET GLOBAL debug="-d,error_unique_log_filename";
DELETE FROM t2;
RESET MASTER;
###################### TEST #7
SET GLOBAL debug="+d,error_unique_log_filename";
SELECT count(*) FROM t4;
count(*)
0
LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/bug_46166.data' INTO TABLE t4;
ERROR HY000: Can't generate a unique log-filename master-bin.(1-999)
# assert: must show 1 entry
SELECT count(*) FROM t4;
count(*)
1
### check that the incident event is written to the current log
SET GLOBAL debug="-d,error_unique_log_filename";
FLUSH LOGS;
SHOW BINLOG EVENTS IN 'BINLOG_FILE' FROM <binlog_start> LIMIT 1;
Log_name Pos Event_type Server_id End_log_pos Info
BINLOG_FILE # Incident # # #1 (LOST_EVENTS)
DELETE FROM t4;
RESET MASTER;
###################### TEST #8
SET GLOBAL debug="+d,error_unique_log_filename";
# must show 0 entries
SELECT count(*) FROM t4;
count(*)
0
SELECT count(*) FROM t2;
count(*)
0
LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/bug_46166.data' INTO TABLE t4;
ERROR HY000: Can't generate a unique log-filename master-bin.(1-999)
LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/bug_46166.data' INTO TABLE t2;
ERROR HY000: Can't generate a unique log-filename master-bin.(1-999)
INSERT INTO t2 VALUES ('aaa'), ('bbb'), ('ccc');
ERROR HY000: Can't generate a unique log-filename master-bin.(1-999)
# INFO: Count(*) Before Offending DELETEs
# assert: must show 1 entry
SELECT count(*) FROM t4;
count(*)
1
# assert: must show 4 entries
SELECT count(*) FROM t2;
count(*)
4
DELETE FROM t4;
ERROR HY000: Can't generate a unique log-filename master-bin.(1-999)
DELETE FROM t2;
ERROR HY000: Can't generate a unique log-filename master-bin.(1-999)
# INFO: Count(*) After Offending DELETEs
# assert: must show zero entries
SELECT count(*) FROM t4;
count(*)
0
SELECT count(*) FROM t2;
count(*)
0
SET GLOBAL debug="-d,error_unique_log_filename";
###################### TEST #9
SET GLOBAL debug="+d,error_unique_log_filename";
SET SQL_LOG_BIN=0;
INSERT INTO t2 VALUES ('aaa'), ('bbb'), ('ccc'), ('ddd');
INSERT INTO t4 VALUES ('eee'), ('fff'), ('ggg'), ('hhh');
# assert: must show four entries
SELECT count(*) FROM t2;
count(*)
4
SELECT count(*) FROM t4;
count(*)
4
DELETE FROM t2;
DELETE FROM t4;
# assert: must show zero entries
SELECT count(*) FROM t2;
count(*)
0
SELECT count(*) FROM t4;
count(*)
0
SET SQL_LOG_BIN=1;
SET GLOBAL debug="-d,error_unique_log_filename";
###################### TEST #10
call mtr.add_suppression("MSYQL_BIN_LOG::open failed to sync the index file.");
call mtr.add_suppression("Could not open .*");
RESET MASTER;
SHOW WARNINGS;
Level Code Message
SET GLOBAL debug="+d,fault_injection_registering_index";
FLUSH LOGS;
ERROR HY000: Can't open file: './master-bin.000002' (errno: 1)
SET GLOBAL debug="-d,fault_injection_registering_index";
SHOW BINARY LOGS;
ERROR HY000: You are not using binary logging
CREATE TABLE t5 (a INT);
INSERT INTO t4 VALUES ('bbbbb');
INSERT INTO t2 VALUES ('aaaaa');
DELETE FROM t4;
DELETE FROM t2;
DROP TABLE t5;
###################### TEST #11
SET GLOBAL debug="+d,fault_injection_openning_index";
FLUSH LOGS;
ERROR HY000: Can't open file: './master-bin.index' (errno: 1)
SET GLOBAL debug="-d,fault_injection_openning_index";
RESET MASTER;
ERROR HY000: Binlog closed, cannot RESET MASTER
CREATE TABLE t5 (a INT);
INSERT INTO t4 VALUES ('bbbbb');
INSERT INTO t2 VALUES ('aaaaa');
DELETE FROM t4;
DELETE FROM t2;
DROP TABLE t5;
###################### TEST #12
SET GLOBAL debug="+d,fault_injection_new_file_rotate_event";
FLUSH LOGS;
ERROR HY000: Can't open file: 'master-bin' (errno: 0)
SET GLOBAL debug="-d,fault_injection_new_file_rotate_event";
RESET MASTER;
ERROR HY000: Binlog closed, cannot RESET MASTER
CREATE TABLE t5 (a INT);
INSERT INTO t4 VALUES ('bbbbb');
INSERT INTO t2 VALUES ('aaaaa');
DELETE FROM t4;
DELETE FROM t2;
DROP TABLE t5;
SET GLOBAL debug= @old_debug;
DROP TABLE t1, t2, t4;
RESET MASTER;
include/start_slave.inc
#######################################################################
####################### PART 2: SLAVE TESTS ###########################
#######################################################################
stop slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
start slave;
call mtr.add_suppression("Slave I/O: Relay log write failure: could not queue event from master.*");
call mtr.add_suppression("Error writing file .*");
call mtr.add_suppression("Could not open .*");
call mtr.add_suppression("MSYQL_BIN_LOG::open failed to sync the index file.");
call mtr.add_suppression("Can't generate a unique log-filename .*");
###################### TEST #13
SET @old_debug=@@global.debug;
include/stop_slave.inc
SET GLOBAL debug="+d,error_unique_log_filename";
START SLAVE io_thread;
Last_IO_Error = Relay log write failure: could not queue event from master
SET GLOBAL debug="-d,error_unique_log_filename";
SET GLOBAL debug=@old_debug;
###################### TEST #14
SET @old_debug=@@global.debug;
include/stop_slave.inc
SET GLOBAL debug="+d,fault_injection_new_file_rotate_event";
START SLAVE io_thread;
Last_IO_Error = Relay log write failure: could not queue event from master
SET GLOBAL debug="-d,fault_injection_new_file_rotate_event";
SET GLOBAL debug=@old_debug;
###################### TEST #15
SET @old_debug=@@global.debug;
include/stop_slave.inc
SET GLOBAL debug="+d,fault_injection_registering_index";
START SLAVE io_thread;
Last_IO_Error = Relay log write failure: could not queue event from master
SET GLOBAL debug="-d,fault_injection_registering_index";
SET GLOBAL debug=@old_debug;
###################### TEST #16
SET @old_debug=@@global.debug;
include/stop_slave.inc
SET GLOBAL debug="+d,fault_injection_openning_index";
START SLAVE io_thread;
Last_IO_Error = Relay log write failure: could not queue event from master
SET GLOBAL debug="-d,fault_injection_openning_index";
SET GLOBAL debug=@old_debug;
include/stop_slave.inc
SET GLOBAL debug=@old_debug;
RESET SLAVE;
RESET MASTER;
include/start_slave.inc
This diff is collapsed.
...@@ -1192,7 +1192,11 @@ int ha_commit_trans(THD *thd, bool all) ...@@ -1192,7 +1192,11 @@ int ha_commit_trans(THD *thd, bool all)
error=ha_commit_one_phase(thd, all) ? (cookie ? 2 : 1) : 0; error=ha_commit_one_phase(thd, all) ? (cookie ? 2 : 1) : 0;
DBUG_EXECUTE_IF("crash_commit_before_unlog", DBUG_SUICIDE();); DBUG_EXECUTE_IF("crash_commit_before_unlog", DBUG_SUICIDE(););
if (cookie) if (cookie)
tc_log->unlog(cookie, xid); if(tc_log->unlog(cookie, xid))
{
error= 2;
goto end;
}
DBUG_EXECUTE_IF("crash_commit_after", DBUG_SUICIDE();); DBUG_EXECUTE_IF("crash_commit_after", DBUG_SUICIDE(););
end: end:
if (rw_trans) if (rw_trans)
......
This diff is collapsed.
...@@ -39,7 +39,7 @@ class TC_LOG ...@@ -39,7 +39,7 @@ class TC_LOG
virtual int open(const char *opt_name)=0; virtual int open(const char *opt_name)=0;
virtual void close()=0; virtual void close()=0;
virtual int log_xid(THD *thd, my_xid xid)=0; virtual int log_xid(THD *thd, my_xid xid)=0;
virtual void unlog(ulong cookie, my_xid xid)=0; virtual int unlog(ulong cookie, my_xid xid)=0;
}; };
class TC_LOG_DUMMY: public TC_LOG // use it to disable the logging class TC_LOG_DUMMY: public TC_LOG // use it to disable the logging
...@@ -49,7 +49,7 @@ class TC_LOG_DUMMY: public TC_LOG // use it to disable the logging ...@@ -49,7 +49,7 @@ class TC_LOG_DUMMY: public TC_LOG // use it to disable the logging
int open(const char *opt_name) { return 0; } int open(const char *opt_name) { return 0; }
void close() { } void close() { }
int log_xid(THD *thd, my_xid xid) { return 1; } int log_xid(THD *thd, my_xid xid) { return 1; }
void unlog(ulong cookie, my_xid xid) { } int unlog(ulong cookie, my_xid xid) { return 0; }
}; };
#ifdef HAVE_MMAP #ifdef HAVE_MMAP
...@@ -94,7 +94,7 @@ class TC_LOG_MMAP: public TC_LOG ...@@ -94,7 +94,7 @@ class TC_LOG_MMAP: public TC_LOG
int open(const char *opt_name); int open(const char *opt_name);
void close(); void close();
int log_xid(THD *thd, my_xid xid); int log_xid(THD *thd, my_xid xid);
void unlog(ulong cookie, my_xid xid); int unlog(ulong cookie, my_xid xid);
int recover(); int recover();
private: private:
...@@ -283,8 +283,8 @@ class MYSQL_BIN_LOG: public TC_LOG, private MYSQL_LOG ...@@ -283,8 +283,8 @@ class MYSQL_BIN_LOG: public TC_LOG, private MYSQL_LOG
new_file() is locking. new_file_without_locking() does not acquire new_file() is locking. new_file_without_locking() does not acquire
LOCK_log. LOCK_log.
*/ */
void new_file_without_locking(); int new_file_without_locking();
void new_file_impl(bool need_lock); int new_file_impl(bool need_lock);
public: public:
MYSQL_LOG::generate_name; MYSQL_LOG::generate_name;
...@@ -314,7 +314,7 @@ class MYSQL_BIN_LOG: public TC_LOG, private MYSQL_LOG ...@@ -314,7 +314,7 @@ class MYSQL_BIN_LOG: public TC_LOG, private MYSQL_LOG
int open(const char *opt_name); int open(const char *opt_name);
void close(); void close();
int log_xid(THD *thd, my_xid xid); int log_xid(THD *thd, my_xid xid);
void unlog(ulong cookie, my_xid xid); int unlog(ulong cookie, my_xid xid);
int recover(IO_CACHE *log, Format_description_log_event *fdle); int recover(IO_CACHE *log, Format_description_log_event *fdle);
#if !defined(MYSQL_CLIENT) #if !defined(MYSQL_CLIENT)
int flush_and_set_pending_rows_event(THD *thd, Rows_log_event* event); int flush_and_set_pending_rows_event(THD *thd, Rows_log_event* event);
...@@ -354,7 +354,7 @@ class MYSQL_BIN_LOG: public TC_LOG, private MYSQL_LOG ...@@ -354,7 +354,7 @@ class MYSQL_BIN_LOG: public TC_LOG, private MYSQL_LOG
bool open_index_file(const char *index_file_name_arg, bool open_index_file(const char *index_file_name_arg,
const char *log_name, bool need_mutex); const char *log_name, bool need_mutex);
/* Use this to start writing a new log file */ /* Use this to start writing a new log file */
void new_file(); int new_file();
void reset_gathered_updates(THD *thd); void reset_gathered_updates(THD *thd);
bool write(Log_event* event_info); // binary log write bool write(Log_event* event_info); // binary log write
...@@ -379,7 +379,7 @@ class MYSQL_BIN_LOG: public TC_LOG, private MYSQL_LOG ...@@ -379,7 +379,7 @@ class MYSQL_BIN_LOG: public TC_LOG, private MYSQL_LOG
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);
void rotate_and_purge(uint flags); int rotate_and_purge(uint flags);
bool flush_and_sync(); bool flush_and_sync();
int purge_logs(const char *to_log, bool included, int purge_logs(const char *to_log, bool included,
bool need_mutex, bool need_update_threads, bool need_mutex, bool need_update_threads,
......
...@@ -1063,7 +1063,7 @@ uint cached_table_definitions(void); ...@@ -1063,7 +1063,7 @@ uint cached_table_definitions(void);
void kill_mysql(void); void kill_mysql(void);
void close_connection(THD *thd, uint errcode, bool lock); void close_connection(THD *thd, uint errcode, bool lock);
bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables, bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
bool *write_to_binlog); int *write_to_binlog);
#ifndef NO_EMBEDDED_ACCESS_CHECKS #ifndef NO_EMBEDDED_ACCESS_CHECKS
bool check_access(THD *thd, ulong access, const char *db, ulong *save_priv, bool check_access(THD *thd, ulong access, const char *db, ulong *save_priv,
bool no_grant, bool no_errors, bool schema_db); bool no_grant, bool no_errors, bool schema_db);
......
...@@ -2839,7 +2839,7 @@ pthread_handler_t signal_hand(void *arg __attribute__((unused))) ...@@ -2839,7 +2839,7 @@ pthread_handler_t signal_hand(void *arg __attribute__((unused)))
case SIGHUP: case SIGHUP:
if (!abort_loop) if (!abort_loop)
{ {
bool not_used; int not_used;
mysql_print_status(); // Print some debug info mysql_print_status(); // Print some debug info
reload_acl_and_cache((THD*) 0, reload_acl_and_cache((THD*) 0,
(REFRESH_LOG | REFRESH_TABLES | REFRESH_FAST | (REFRESH_LOG | REFRESH_TABLES | REFRESH_FAST |
......
...@@ -229,8 +229,7 @@ int injector::record_incident(THD *thd, Incident incident) ...@@ -229,8 +229,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;
mysql_bin_log.rotate_and_purge(RP_FORCE_ROTATE); return mysql_bin_log.rotate_and_purge(RP_FORCE_ROTATE);
return 0;
} }
int injector::record_incident(THD *thd, Incident incident, LEX_STRING const message) int injector::record_incident(THD *thd, Incident incident, LEX_STRING const message)
...@@ -238,6 +237,5 @@ int injector::record_incident(THD *thd, Incident incident, LEX_STRING const mess ...@@ -238,6 +237,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;
mysql_bin_log.rotate_and_purge(RP_FORCE_ROTATE); return mysql_bin_log.rotate_and_purge(RP_FORCE_ROTATE);
return 0;
} }
...@@ -3398,8 +3398,7 @@ static int process_io_rotate(Master_info *mi, Rotate_log_event *rev) ...@@ -3398,8 +3398,7 @@ static int process_io_rotate(Master_info *mi, Rotate_log_event *rev)
Rotate the relay log makes binlog format detection easier (at next slave Rotate the relay log makes binlog format detection easier (at next slave
start or mysqlbinlog) start or mysqlbinlog)
*/ */
rotate_relay_log(mi); /* will take the right mutexes */ DBUG_RETURN(rotate_relay_log(mi) /* will take the right mutexes */);
DBUG_RETURN(0);
} }
/* /*
...@@ -4482,10 +4481,11 @@ event(errno: %d cur_log->error: %d)", ...@@ -4482,10 +4481,11 @@ event(errno: %d cur_log->error: %d)",
is void). is void).
*/ */
void rotate_relay_log(Master_info* mi) int rotate_relay_log(Master_info* mi)
{ {
DBUG_ENTER("rotate_relay_log"); DBUG_ENTER("rotate_relay_log");
Relay_log_info* rli= &mi->rli; Relay_log_info* rli= &mi->rli;
int error= 0;
/* We don't lock rli->run_lock. This would lead to deadlocks. */ /* We don't lock rli->run_lock. This would lead to deadlocks. */
pthread_mutex_lock(&mi->run_lock); pthread_mutex_lock(&mi->run_lock);
...@@ -4501,7 +4501,8 @@ void rotate_relay_log(Master_info* mi) ...@@ -4501,7 +4501,8 @@ 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(); if ((error= rli->relay_log.new_file()))
goto end;
/* /*
We harvest now, because otherwise BIN_LOG_HEADER_SIZE will not immediately We harvest now, because otherwise BIN_LOG_HEADER_SIZE will not immediately
...@@ -4519,7 +4520,7 @@ void rotate_relay_log(Master_info* mi) ...@@ -4519,7 +4520,7 @@ void rotate_relay_log(Master_info* mi)
rli->relay_log.harvest_bytes_written(&rli->log_space_total); rli->relay_log.harvest_bytes_written(&rli->log_space_total);
end: end:
pthread_mutex_unlock(&mi->run_lock); pthread_mutex_unlock(&mi->run_lock);
DBUG_VOID_RETURN; DBUG_RETURN(error);
} }
......
...@@ -189,7 +189,7 @@ int purge_relay_logs(Relay_log_info* rli, THD *thd, bool just_reset, ...@@ -189,7 +189,7 @@ int purge_relay_logs(Relay_log_info* rli, THD *thd, bool just_reset,
const char** errmsg); const char** errmsg);
void set_slave_thread_options(THD* thd); void set_slave_thread_options(THD* thd);
void set_slave_thread_default_charset(THD *thd, Relay_log_info const *rli); void set_slave_thread_default_charset(THD *thd, Relay_log_info const *rli);
void rotate_relay_log(Master_info* mi); int rotate_relay_log(Master_info* mi);
int apply_event_and_update_pos(Log_event* ev, THD* thd, Relay_log_info* rli); int apply_event_and_update_pos(Log_event* ev, THD* thd, Relay_log_info* rli);
pthread_handler_t handle_slave_io(void *arg); pthread_handler_t handle_slave_io(void *arg);
......
...@@ -567,6 +567,13 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, ...@@ -567,6 +567,13 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
transactional_table, transactional_table,
errcode); errcode);
} }
/*
Flushing the IO CACHE while writing the execute load query log event
may result in error (for instance, because the max_binlog_size has been
reached, and rotation of the binary log failed).
*/
error= error || mysql_bin_log.get_log_file()->error;
} }
if (error) if (error)
goto err; goto err;
......
...@@ -1474,7 +1474,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, ...@@ -1474,7 +1474,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
#endif #endif
case COM_REFRESH: case COM_REFRESH:
{ {
bool not_used; int not_used;
status_var_increment(thd->status_var.com_stat[SQLCOM_FLUSH]); status_var_increment(thd->status_var.com_stat[SQLCOM_FLUSH]);
ulong options= (ulong) (uchar) packet[0]; ulong options= (ulong) (uchar) packet[0];
if (check_global_access(thd,RELOAD_ACL)) if (check_global_access(thd,RELOAD_ACL))
...@@ -3227,7 +3227,11 @@ mysql_execute_command(THD *thd) ...@@ -3227,7 +3227,11 @@ mysql_execute_command(THD *thd)
{ {
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 */
mysql_bin_log.rotate_and_purge(RP_FORCE_ROTATE); if (mysql_bin_log.rotate_and_purge(RP_FORCE_ROTATE))
{
res= 1;
break;
}
} }
DBUG_PRINT("debug", ("Just after generate_incident()")); DBUG_PRINT("debug", ("Just after generate_incident()"));
} }
...@@ -4051,7 +4055,7 @@ mysql_execute_command(THD *thd) ...@@ -4051,7 +4055,7 @@ mysql_execute_command(THD *thd)
lex->no_write_to_binlog= 1; lex->no_write_to_binlog= 1;
case SQLCOM_FLUSH: case SQLCOM_FLUSH:
{ {
bool write_to_binlog; int write_to_binlog;
if (check_global_access(thd,RELOAD_ACL)) if (check_global_access(thd,RELOAD_ACL))
goto error; goto error;
...@@ -4068,12 +4072,22 @@ mysql_execute_command(THD *thd) ...@@ -4068,12 +4072,22 @@ mysql_execute_command(THD *thd)
/* /*
Presumably, RESET and binlog writing doesn't require synchronization Presumably, RESET and binlog writing doesn't require synchronization
*/ */
if (!lex->no_write_to_binlog && write_to_binlog)
if (write_to_binlog > 0) // we should write
{
if (!lex->no_write_to_binlog)
res= write_bin_log(thd, FALSE, thd->query(), thd->query_length());
} else if (write_to_binlog < 0)
{ {
if ((res= write_bin_log(thd, FALSE, thd->query(), thd->query_length()))) /*
break; We should not write, but rather report error because
} reload_acl_and_cache binlog interactions failed
my_ok(thd); */
res= 1;
}
if (!res)
my_ok(thd);
} }
break; break;
...@@ -6862,7 +6876,10 @@ void add_join_natural(TABLE_LIST *a, TABLE_LIST *b, List<String> *using_fields, ...@@ -6862,7 +6876,10 @@ void add_join_natural(TABLE_LIST *a, TABLE_LIST *b, List<String> *using_fields,
@param thd Thread handler (can be NULL!) @param thd Thread handler (can be NULL!)
@param options What should be reset/reloaded (tables, privileges, slave...) @param options What should be reset/reloaded (tables, privileges, slave...)
@param tables Tables to flush (if any) @param tables Tables to flush (if any)
@param write_to_binlog True if we can write to the binlog. @param write_to_binlog < 0 if there was an error while interacting with the binary log inside
reload_acl_and_cache,
0 if we should not write to the binary log,
> 0 if we can write to the binlog.
@note Depending on 'options', it may be very bad to write the @note Depending on 'options', it may be very bad to write the
query to the binlog (e.g. FLUSH SLAVE); this is a query to the binlog (e.g. FLUSH SLAVE); this is a
...@@ -6876,11 +6893,11 @@ void add_join_natural(TABLE_LIST *a, TABLE_LIST *b, List<String> *using_fields, ...@@ -6876,11 +6893,11 @@ void add_join_natural(TABLE_LIST *a, TABLE_LIST *b, List<String> *using_fields,
*/ */
bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables, bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
bool *write_to_binlog) int *write_to_binlog)
{ {
bool result=0; bool result=0;
select_errors=0; /* Write if more errors */ select_errors=0; /* Write if more errors */
bool tmp_write_to_binlog= 1; int tmp_write_to_binlog= *write_to_binlog= 1;
DBUG_ASSERT(!thd || !thd->in_sub_stmt); DBUG_ASSERT(!thd || !thd->in_sub_stmt);
...@@ -6943,12 +6960,16 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables, ...@@ -6943,12 +6960,16 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
tmp_write_to_binlog= 0; tmp_write_to_binlog= 0;
if( mysql_bin_log.is_open() ) if( mysql_bin_log.is_open() )
{ {
mysql_bin_log.rotate_and_purge(RP_FORCE_ROTATE); if (mysql_bin_log.rotate_and_purge(RP_FORCE_ROTATE))
*write_to_binlog= -1;
} }
#ifdef HAVE_REPLICATION #ifdef HAVE_REPLICATION
int rotate_error= 0;
pthread_mutex_lock(&LOCK_active_mi); pthread_mutex_lock(&LOCK_active_mi);
rotate_relay_log(active_mi); rotate_error= rotate_relay_log(active_mi);
pthread_mutex_unlock(&LOCK_active_mi); pthread_mutex_unlock(&LOCK_active_mi);
if (rotate_error)
*write_to_binlog= -1;
#endif #endif
/* flush slow and general logs */ /* flush slow and general logs */
...@@ -7059,7 +7080,8 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables, ...@@ -7059,7 +7080,8 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
#endif #endif
if (options & REFRESH_USER_RESOURCES) if (options & REFRESH_USER_RESOURCES)
reset_mqh((LEX_USER *) NULL, 0); /* purecov: inspected */ reset_mqh((LEX_USER *) NULL, 0); /* purecov: inspected */
*write_to_binlog= tmp_write_to_binlog; if (*write_to_binlog != -1)
*write_to_binlog= tmp_write_to_binlog;
/* /*
If the query was killed then this function must fail. If the query was killed then this function must fail.
*/ */
......
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