Binlog-in-engine: Fix binary search for GTID position

When finding the midpoint for each step in the binary search, that
midpoint was not correctly rounded to the nearest page containing a
GTID state record (when the range from the low to the high point is an
odd multiple of number of innodb_binlog_state_interval bytes). This
caused the search to look at the wrong page (and assert in debug
build).

Signed-off-by: Kristian Nielsen <knielsen@knielsen-hq.org>
This commit is contained in:
Kristian Nielsen 2025-10-06 14:07:29 +02:00
commit 649851f52b
6 changed files with 18 additions and 12 deletions

View file

@ -19828,9 +19828,9 @@ static MYSQL_SYSVAR_ULONGLONG(binlog_state_interval,
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
"Interval (in bytes) at which to write the GTID binlog state to binlog "
"files to speed up GTID lookups. Must be a multiple of the binlog page "
"size (4096 bytes)",
"size (16384 bytes)",
NULL, NULL, 2*1024*1024,
8192, ULONGLONG_MAX, 0);
32768, ULONGLONG_MAX, 0);
static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(autoextend_increment),

View file

@ -3259,7 +3259,10 @@ gtid_search::find_gtid_pos(slave_connection_state *pos,
((chunk_reader.cur_end_offset - 1) >> ibb_page_size_shift));
/* Round to the next diff_state_page_interval after file end. */
page2-= page2 % (uint32_t)diff_state_page_interval;
uint32_t page1= (page0 + page2) / 2;
uint32_t page1= page0 +
((page2 - page0) /
(2*(uint32_t)diff_state_page_interval) *
(uint32_t)diff_state_page_interval);
page0_diff_state.init();
page0_diff_state.load_nolock(&base_state);
tmp_diff_state.init();
@ -3290,7 +3293,10 @@ gtid_search::find_gtid_pos(slave_connection_state *pos,
}
else
page2= page1;
page1= (page0 + page2) / 2;
page1= page0 +
((page2 - page0) /
(2*(uint32_t)diff_state_page_interval) *
(uint32_t)diff_state_page_interval);
}
ut_ad(page1 >= page0);
out_state->load_nolock(&page0_diff_state);