Skip to content

Commit 2a4767f

Browse files
committed
Don't overwrite the global format description event when we encounter a FDE in innodb binlog
1 parent c07eafe commit 2a4767f

3 files changed

Lines changed: 50 additions & 21 deletions

File tree

client/mysqlbinlog.cc

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1940,13 +1940,15 @@ static void generate_output_legacy_binlog_name(char *out_name, size_t out_name_l
19401940
}
19411941

19421942
static bool init_output_legacy_binlog(FILE **out_file, char *out_name,
1943-
size_t out_name_len)
1943+
size_t out_name_len,
1944+
Format_description_log_event *fdev)
19441945
{
19451946
/* Reset the log_file_pos to 0 for the new output legacy binlog file */
19461947
log_file_pos= 0;
19471948
log_file_pos_overflow_warning_printed= false;
19481949

1949-
generate_output_legacy_binlog_name(out_name, out_name_len, ++convert_engine_output_index);
1950+
generate_output_legacy_binlog_name(out_name, out_name_len,
1951+
++convert_engine_output_index);
19501952

19511953
if (!(*out_file= my_fopen(out_name, O_WRONLY | O_BINARY, MYF(MY_WME))))
19521954
{
@@ -1966,8 +1968,7 @@ static bool init_output_legacy_binlog(FILE **out_file, char *out_name,
19661968
log_file_pos+= BIN_LOG_HEADER_SIZE;
19671969

19681970
// Write the FORMAT_DESCRIPTION_EVENT to the output legacy binlog file
1969-
if (write_format_description_event_to_legacy_binlog(*out_file,
1970-
glob_description_event))
1971+
if (write_format_description_event_to_legacy_binlog(*out_file, fdev))
19711972
{
19721973
error("Could not write FORMAT_DESCRIPTION_EVENT to output legacy binlog "
19731974
"file");
@@ -1999,7 +2000,8 @@ static bool init_output_legacy_binlog(FILE **out_file, char *out_name,
19992000
}
20002001

20012002
static bool rotate_output_legacy_binlog(FILE **out_file, char *out_name,
2002-
size_t out_name_len)
2003+
size_t out_name_len,
2004+
Format_description_log_event *fdev)
20032005
{
20042006
char next_out_file_name[FN_REFLEN + 1];
20052007
generate_output_legacy_binlog_name(next_out_file_name,
@@ -2019,7 +2021,7 @@ static bool rotate_output_legacy_binlog(FILE **out_file, char *out_name,
20192021
return true;
20202022
}
20212023

2022-
return init_output_legacy_binlog(out_file, out_name, out_name_len);
2024+
return init_output_legacy_binlog(out_file, out_name, out_name_len, fdev);
20232025
}
20242026

20252027
/*
@@ -2029,28 +2031,31 @@ static bool rotate_output_legacy_binlog(FILE **out_file, char *out_name,
20292031
*/
20302032
static Exit_status write_event_to_legacy_binlog(Log_event *ev)
20312033
{
2032-
/*
2034+
/*
20332035
Update the global server_id and timestamp variables
20342036
*/
20352037
generated_event_server_id= ev->server_id;
20362038
generated_event_timestamp= (uint32) ev->when;
20372039

2038-
// if event type is FORMAT_DESCRIPTION_EVENT, store the event in global
2039-
// variable glob_description_event
2040+
/*
2041+
A FORMAT_DESCRIPTION_EVENT in an engine binlog indicates a server restart.
2042+
Use this FDE only for the restart-triggered rotation. Do not store it in
2043+
glob_description_event, as reusing it for normal rotations would
2044+
incorrectly clear the temporary tables.
2045+
*/
20402046
if (ev->get_type_code() == FORMAT_DESCRIPTION_EVENT)
20412047
{
20422048

2043-
delete glob_description_event;
2044-
glob_description_event= (Format_description_log_event *) ev;
2045-
20462049
// close the output legacy binlog file if it is open
20472050
if (output_legacy_binlog_file)
20482051
{
20492052
if (rotate_output_legacy_binlog(&output_legacy_binlog_file,
2050-
out_file_name, sizeof(out_file_name)))
2053+
out_file_name, sizeof(out_file_name),
2054+
(Format_description_log_event *) ev))
20512055
goto err;
20522056
}
20532057

2058+
delete ev;
20542059
return OK_CONTINUE;
20552060
}
20562061

@@ -2062,18 +2067,19 @@ static Exit_status write_event_to_legacy_binlog(Log_event *ev)
20622067
if (!output_legacy_binlog_file)
20632068
{
20642069
if (init_output_legacy_binlog(&output_legacy_binlog_file, out_file_name,
2065-
sizeof(out_file_name)))
2070+
sizeof(out_file_name),
2071+
glob_description_event))
20662072
goto err;
20672073
}
20682074

20692075
/*
20702076
Rotate the output legacy binlog file once the max binlog size is reached.
20712077
*/
2072-
if (ev->get_type_code() == GTID_EVENT &&
2073-
log_file_pos >= opt_max_binlog_size)
2078+
if (ev->get_type_code() == GTID_EVENT && log_file_pos >= opt_max_binlog_size)
20742079
{
20752080
if (rotate_output_legacy_binlog(&output_legacy_binlog_file, out_file_name,
2076-
sizeof(out_file_name)))
2081+
sizeof(out_file_name),
2082+
glob_description_event))
20772083
goto err;
20782084
}
20792085

mysql-test/suite/binlog_in_engine/mysqlbinlog_convert_engine_binlog_max_size.result

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
include/reset_master.inc
22
CREATE TABLE t1 (a INT PRIMARY KEY, b LONGTEXT) ENGINE=InnoDB;
3+
# restart
34
INSERT INTO t1 VALUES (1, REPEAT('a', 48 * 1024));
45
INSERT INTO t1 VALUES (2, REPEAT('b', 48 * 1024));
56
INSERT INTO t1 VALUES (3, REPEAT('c', 48 * 1024));
67
FLUSH BINARY LOGS;
78
*** Convert with a 32K maximum output binlog size
9+
*** Only the restart FDE is marked as created at startup
10+
FOUND 1 /Start: binlog v 4.*at startup/ in max_size_restart_fde.txt
11+
NOT FOUND /Start: binlog v 4.*at startup/ in max_size_normal_fdes.txt
812
*** Rotated files form a replayable binlog sequence
913
DROP TABLE t1;
1014
SELECT a, LENGTH(b) FROM t1 ORDER BY a;

mysql-test/suite/binlog_in_engine/mysqlbinlog_convert_engine_binlog_max_size.test

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,11 @@
55

66
--source include/reset_master.inc
77

8-
98
CREATE TABLE t1 (a INT PRIMARY KEY, b LONGTEXT) ENGINE=InnoDB;
9+
10+
# Generate a FORMAT_DESCRIPTION_EVENT that marks a server restart.
11+
--source include/restart_mysqld.inc
12+
1013
INSERT INTO t1 VALUES (1, REPEAT('a', 48 * 1024));
1114
INSERT INTO t1 VALUES (2, REPEAT('b', 48 * 1024));
1215
INSERT INTO t1 VALUES (3, REPEAT('c', 48 * 1024));
@@ -20,21 +23,37 @@ FLUSH BINARY LOGS;
2023
--echo *** Convert with a 32K maximum output binlog size
2124
--exec $MYSQL_BINLOG --convert-engine-binlog --max-binlog-size=32768 --result-file=$MYSQL_TMP_DIR/max_size_conv $datadir/binlog-000000.ibb
2225

23-
# Rotation is checked at transaction boundaries. The first large INSERT stays
24-
# in the initial file; each following INSERT starts a new output file.
26+
# The restart rotates the initial file after CREATE TABLE. Size is checked at
27+
# transaction boundaries, so each large INSERT after the first causes the next
28+
# INSERT to start a new output file.
2529
--file_exists $MYSQL_TMP_DIR/max_size_conv.000001
2630
--file_exists $MYSQL_TMP_DIR/max_size_conv.000002
2731
--file_exists $MYSQL_TMP_DIR/max_size_conv.000003
32+
--file_exists $MYSQL_TMP_DIR/max_size_conv.000004
33+
34+
--echo *** Only the restart FDE is marked as created at startup
35+
--exec $MYSQL_BINLOG --verbose $MYSQL_TMP_DIR/max_size_conv.000002 > $MYSQL_TMP_DIR/max_size_restart_fde.txt
36+
--let SEARCH_FILE= $MYSQL_TMP_DIR/max_size_restart_fde.txt
37+
--let SEARCH_PATTERN= Start: binlog v 4.*at startup
38+
--source include/search_pattern_in_file.inc
39+
40+
--exec $MYSQL_BINLOG --verbose $MYSQL_TMP_DIR/max_size_conv.000001 $MYSQL_TMP_DIR/max_size_conv.000003 $MYSQL_TMP_DIR/max_size_conv.000004 > $MYSQL_TMP_DIR/max_size_normal_fdes.txt
41+
--let SEARCH_FILE= $MYSQL_TMP_DIR/max_size_normal_fdes.txt
42+
--let SEARCH_PATTERN= Start: binlog v 4.*at startup
43+
--source include/search_pattern_in_file.inc
2844

2945
--echo *** Rotated files form a replayable binlog sequence
30-
--exec $MYSQL_BINLOG --gtid-strict-mode=0 $MYSQL_TMP_DIR/max_size_conv.000001 $MYSQL_TMP_DIR/max_size_conv.000002 $MYSQL_TMP_DIR/max_size_conv.000003 > $MYSQLTEST_VARDIR/tmp/max_size_replay.sql
46+
--exec $MYSQL_BINLOG --gtid-strict-mode=0 $MYSQL_TMP_DIR/max_size_conv.000001 $MYSQL_TMP_DIR/max_size_conv.000002 $MYSQL_TMP_DIR/max_size_conv.000003 $MYSQL_TMP_DIR/max_size_conv.000004 > $MYSQLTEST_VARDIR/tmp/max_size_replay.sql
3147
DROP TABLE t1;
3248
--exec $MYSQL --abort-source-on-error -e "source $MYSQLTEST_VARDIR/tmp/max_size_replay.sql;" test
3349
--remove_file $MYSQLTEST_VARDIR/tmp/max_size_replay.sql
3450

3551
SELECT a, LENGTH(b) FROM t1 ORDER BY a;
3652

53+
--remove_file $MYSQL_TMP_DIR/max_size_restart_fde.txt
54+
--remove_file $MYSQL_TMP_DIR/max_size_normal_fdes.txt
3755
--remove_file $MYSQL_TMP_DIR/max_size_conv.000001
3856
--remove_file $MYSQL_TMP_DIR/max_size_conv.000002
3957
--remove_file $MYSQL_TMP_DIR/max_size_conv.000003
58+
--remove_file $MYSQL_TMP_DIR/max_size_conv.000004
4059
DROP TABLE t1;

0 commit comments

Comments
 (0)