Description:
When specify the --start-position=N to the the events that begin at position N and after, the output doesn't give the right Format_description_log_event start postion. See the difference in `How to repeat section`
The reason for this lay in read_fdle function. Since this function going to work for both binlog and relay-log, after read the first FDE, it continue to read some events(PREVIOUS_GTIDS_LOG_EVENT or ROTATE_EVENT) until it see another FDE or some other event. So if this is a binlog, problem occurs, the code will forward the
field `m_event_start_pos` that bigger than 4.
How to repeat:
without --start-position
[root@localhost data]# mysqlbinlog --hexdump binlog.000001 | head -n20
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
DELIMITER /*!*/;
# at 4
#201103 7:15:08 server id 1 end_log_pos 125 CRC32 0xfc7e724a
# Position Timestamp Type Master ID Size Master Pos Flags
# 00000004 cc 49 a1 5f 0f 01 00 00 00 79 00 00 00 7d 00 00 00 01 00
# 00000017 04 00 38 2e 30 2e 32 32 2d 64 65 62 75 67 00 00 |..8.0.22.debug..|
# 00000027 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
# 00000037 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
# 00000047 00 00 00 00 cc 49 a1 5f 13 00 0d 00 08 00 00 00 |.....I..........|
# 00000057 00 04 00 04 00 00 00 61 00 04 1a 08 00 00 00 08 |.......a........|
# 00000067 08 08 02 00 00 00 0a 0a 0a 2a 2a 00 12 34 00 0a |.............4..|
# 00000077 28 01 4a 72 7e fc |..Jr..|
# Start: binlog v 4, server v 8.0.22-debug created 201103 7:15:08 at startup
# Warning: this binlog is either in use or was not closed properly.
ROLLBACK/*!*/;
BINLOG '
zEmhXw8BAAAAeQAAAH0AAAABAAQAOC4wLjIyLWRlYnVnAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAADMSaFfEwANAAgAAAAABAAEAAAAYQAEGggAAAAICAgCAAAACgoKKioAEjQA
[root@localhost data]#
with --start-position
[root@localhost data]# mysqlbinlog --start-position=523 binlog.000001 | head -n20
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
DELIMITER /*!*/;
# at 156
#201103 7:15:08 server id 1 end_log_pos 125 CRC32 0xfc7e724a Start: binlog v 4, server v 8.0.22-debug created 201103 7:15:08 at startup
# Warning: this binlog is either in use or was not closed properly.
ROLLBACK/*!*/;
BINLOG '
zEmhXw8BAAAAeQAAAH0AAAABAAQAOC4wLjIyLWRlYnVnAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAADMSaFfEwANAAgAAAAABAAEAAAAYQAEGggAAAAICAgCAAAACgoKKioAEjQA
CigBSnJ+/A==
'/*!*/;
# at 523
#201103 7:22:30 server id 1 end_log_pos 640 CRC32 0x048ab7b8 Query thread_id=11 exec_time=0 error_code=0 Xid = 10
SET TIMESTAMP=1604406150/*!*/;
SET @@session.pseudo_thread_id=11/*!*/;
SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
SET @@session.sql_mode=1168113696/*!*/;
SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
/*!\C utf8mb4 *//*!*/;
[root@localhost data]#
Suggested fix:
--- a/sql/binlog_reader.h
+++ b/sql/binlog_reader.h
@@ -377,6 +377,8 @@ class Basic_binlog_file_reader {
[Rotate_event] : In the case rotating relaylog, no Rotate here
Format_description_event : master's Format_description_event
*/
+ int fdl_cnt = 0;
+ my_off_t first_fde_pos = position();
while (position() < offset) {
m_event_start_pos = position();
@@ -385,6 +387,7 @@ class Basic_binlog_file_reader {
if (ev == nullptr) break;
if (ev->get_type_code() == binary_log::FORMAT_DESCRIPTION_EVENT) {
+ fdl_cnt++;
delete fdle;
fdle = dynamic_cast<Format_description_log_event *>(ev);
m_fde = *fdle;
@@ -400,6 +403,9 @@ class Basic_binlog_file_reader {
delete fdle;
return nullptr;
}
+ if (fdl_cnt == 1 && first_fde_pos != m_event_start_pos) {
+ m_event_start_pos = first_fde_pos;
+ }
return fdle;
}
};