diff --git a/mysql-test/suite/binlog_in_engine/rpl_oob.result b/mysql-test/suite/binlog_in_engine/rpl_oob.result index a63d3412251..d3706aa854e 100644 --- a/mysql-test/suite/binlog_in_engine/rpl_oob.result +++ b/mysql-test/suite/binlog_in_engine/rpl_oob.result @@ -57,6 +57,8 @@ UPDATE t3 SET b = 'tmp' WHERE id = 1; UPDATE t3 SET a = REPEAT('y', 65535); UPDATE t3 SET b = 'wic'; COMMIT; +SET binlog_row_image=MINIMAL; +UPDATE t3 SET a = REPEAT('y', 15000); disconnect my_con1; connection master; SET GLOBAL binlog_cache_size= @old_cache_size; diff --git a/mysql-test/suite/binlog_in_engine/rpl_oob.test b/mysql-test/suite/binlog_in_engine/rpl_oob.test index 20086647350..cb69f99aae2 100644 --- a/mysql-test/suite/binlog_in_engine/rpl_oob.test +++ b/mysql-test/suite/binlog_in_engine/rpl_oob.test @@ -125,6 +125,16 @@ UPDATE t3 SET b = 'tmp' WHERE id = 1; UPDATE t3 SET a = REPEAT('y', 65535); UPDATE t3 SET b = 'wic'; COMMIT; + +# MDEV-41442: Too large mtr when trx is larger than InnoDB max mtr size but +# smaller than binlog_cache_size. + +# Use MINIMAL just to make the trx size not depend on old table data. +# We want > ~1MB but smaller than binlog_cache_size to trigger the +# bug condition. +SET binlog_row_image=MINIMAL; +UPDATE t3 SET a = REPEAT('y', 15000); + --disconnect my_con1 --connection master SET GLOBAL binlog_cache_size= @old_cache_size; diff --git a/sql/log.cc b/sql/log.cc index 4292a7a1236..05a8503dcab 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -8400,13 +8400,18 @@ MYSQL_BIN_LOG::write_gtid_event(THD *thd, binlog_cache_data *cache_data, if (opt_binlog_engine_hton) { DBUG_ASSERT(cache_data != nullptr); - uint32_t avail= (uint32_t)(dest->write_end - dest->write_pos); + uint64_t total= my_b_tell(dest); + uint32_t avail= + unlikely(total >= binlog_max_spill_size) ? 0 : + MY_MIN((uint32_t)(dest->write_end - dest->write_pos), + (uint32_t)(binlog_max_spill_size - total)); if (unlikely(avail < Gtid_log_event::max_size) && avail < gtid_event.get_size()) { /* - The GTID event doesn't fit in the cache, so we have to spill the - contents as oob event data. + The GTID event doesn't fit in the cache (or within + binlog_max_spill_size), so we have to spill the contents as oob event + data. */ if (my_b_flush_io_cache(dest, 0)) DBUG_RETURN(true);