Description:
When binlog_row_event_max_size is set to a large value (e.g., its maximum ULONG_MAX), an unsigned integer wraparound occurs in Binlog_sender::run() (sql/rpl_binlog_sender.cc), causing the dump thread to reject legitimate
binlog events with the error: "log event entry exceeded max_allowed_packet; Increase max_allowed_packet on source"
Root Cause:
In Binlog_sender::run():
unsigned int max_event_size =
std::max(m_thd->variables.max_allowed_packet,
binlog_row_event_max_size + MAX_LOG_EVENT_HEADER);
When binlog_row_event_max_size is near ULONG_MAX (after BLOCK_SIZE(256) alignment, it becomes 0xFFFFFFFFFFFFFF00),
adding MAX_LOG_EVENT_HEADER (~300 bytes) causes an unsigned wraparound:
0xFFFFFFFFFFFFFF00 + 300 = 0x10000000000000024 mod 2^64 = 44
Then std::max(1GB, 44) returns 1GB, so max_event_size becomes 1073741824 (1GB) instead of the expected large
value.
This 1GB limit is then passed to Binlog_event_data_istream as m_max_event_size and checked in check_event_header()
(sql/binlog_reader.cc):
if (m_event_length > m_max_event_size)
return m_error->set_type(Binlog_read_error::EVENT_TOO_LARGE);
Any binlog event larger than 1GB (but within the valid 4-byte event_length range) is incorrectly rejected.
How to repeat:
1. On the source, set binlog_row_event_max_size to its maximum value:
mysqld --binlog-row-event-max-size=18446744073709551615
2. Use row-based replication (binlog_format=ROW).
3. Execute a transaction that produces a single row event larger than 1GB (e.g., a bulk INSERT with many rows that
are not split because binlog_row_event_max_size is effectively unlimited).
4. Connect a replica. The dump thread reads the binlog and fails at check_event_header() with:
Got fatal error 1236 from source when reading data from binary log:
'log event entry exceeded max_allowed_packet; Increase max_allowed_packet on source'
Suggested fix:
The upper bound of binlog_row_event_max_size should be limited to binary_log::max_log_event_size (1GB), consistent
with replica_max_allowed_packet. Because even if the source allows writing arbitrarily large row events, the
replica cannot receive events exceeding replica_max_allowed_packet (max 1GB). Allowing binlog_row_event_max_size
to exceed this limit is meaningless and leads to the wraparound bug.
Description: When binlog_row_event_max_size is set to a large value (e.g., its maximum ULONG_MAX), an unsigned integer wraparound occurs in Binlog_sender::run() (sql/rpl_binlog_sender.cc), causing the dump thread to reject legitimate binlog events with the error: "log event entry exceeded max_allowed_packet; Increase max_allowed_packet on source" Root Cause: In Binlog_sender::run(): unsigned int max_event_size = std::max(m_thd->variables.max_allowed_packet, binlog_row_event_max_size + MAX_LOG_EVENT_HEADER); When binlog_row_event_max_size is near ULONG_MAX (after BLOCK_SIZE(256) alignment, it becomes 0xFFFFFFFFFFFFFF00), adding MAX_LOG_EVENT_HEADER (~300 bytes) causes an unsigned wraparound: 0xFFFFFFFFFFFFFF00 + 300 = 0x10000000000000024 mod 2^64 = 44 Then std::max(1GB, 44) returns 1GB, so max_event_size becomes 1073741824 (1GB) instead of the expected large value. This 1GB limit is then passed to Binlog_event_data_istream as m_max_event_size and checked in check_event_header() (sql/binlog_reader.cc): if (m_event_length > m_max_event_size) return m_error->set_type(Binlog_read_error::EVENT_TOO_LARGE); Any binlog event larger than 1GB (but within the valid 4-byte event_length range) is incorrectly rejected. How to repeat: 1. On the source, set binlog_row_event_max_size to its maximum value: mysqld --binlog-row-event-max-size=18446744073709551615 2. Use row-based replication (binlog_format=ROW). 3. Execute a transaction that produces a single row event larger than 1GB (e.g., a bulk INSERT with many rows that are not split because binlog_row_event_max_size is effectively unlimited). 4. Connect a replica. The dump thread reads the binlog and fails at check_event_header() with: Got fatal error 1236 from source when reading data from binary log: 'log event entry exceeded max_allowed_packet; Increase max_allowed_packet on source' Suggested fix: The upper bound of binlog_row_event_max_size should be limited to binary_log::max_log_event_size (1GB), consistent with replica_max_allowed_packet. Because even if the source allows writing arbitrarily large row events, the replica cannot receive events exceeding replica_max_allowed_packet (max 1GB). Allowing binlog_row_event_max_size to exceed this limit is meaningless and leads to the wraparound bug.