mirror of
https://github.com/MariaDB/server.git
synced 2026-10-23 18:49:29 +03:00
MDEV-41442: Too large InnoDB mtr with large binlog_cache_size
The binlog-in-engine code limits the maximum size of engine binlog writes by forcing OOB-spill, eg. to avoid exceeding InnoDB max mtr size. However there was a case missed: When the transaction is larger than binlog_max_spill_size but smaller than the binlog_cache_size, there was no check to force OOB-spilling, and the code would do a too large binlog write that asserts or fails inside InnoDB. Signed-off-by: Kristian Nielsen <knielsen@knielsen-hq.org>
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
11
sql/log.cc
11
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);
|
||||
|
||||
Reference in New Issue
Block a user