Skip to content

Commit 00ccff4

Browse files
andrelkinvuvova
authored andcommitted
MDEV-14014 Multi-Slave Replication Fail: bogus data in log event
MDEV-7257 made a dump thread to read from binlog concurrently with writers as long as the read bytes are below a water-mark (MYSQL_BIN_LOG::binlog_end_pos). However it appeared to be possible a dump thread reader reach out for bytes past the water mark through a feature of IO_CACHE that fills in the internal buffer and while doing so it could read what the reader is not supposed to see (the bytes above MYSQL_BIN_LOG::binlog_end_pos). The issue is fixed with constraining the IO_CACHE buffer fill to respect the watermark. An added unit test proves reading from file is bound to an external parameter passed to {IO_CACHE::end_of_file} cache member.
1 parent 52a25d7 commit 00ccff4

File tree

2 files changed

+37
-1
lines changed

2 files changed

+37
-1
lines changed

sql/sql_repl.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2538,6 +2538,7 @@ static int send_events(binlog_send_info *info, IO_CACHE* log, LOG_INFO* linfo,
25382538
linfo->pos= my_b_tell(log);
25392539
info->last_pos= my_b_tell(log);
25402540

2541+
log->end_of_file= end_pos;
25412542
while (linfo->pos < end_pos)
25422543
{
25432544
if (should_stop(info))

unittest/sql/mf_iocache-t.cc

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,10 +253,43 @@ void mdev10259()
253253

254254
}
255255

256+
void mdev14014()
257+
{
258+
int res;
259+
uchar buf_o[200];
260+
uchar buf_i[200];
261+
memset(buf_i, 0, sizeof( buf_i));
262+
memset(buf_o, FILL, sizeof(buf_o));
263+
264+
diag("MDEV-14014 Dump thread reads past last 'officially' written byte");
265+
266+
init_io_cache_encryption();
267+
268+
res= open_cached_file(&info, 0, 0, CACHE_SIZE, 0);
269+
ok(res == 0, "open_cached_file" INFO_TAIL);
270+
271+
res= my_b_write(&info, buf_o, sizeof(buf_o));
272+
ok(res == 0, "buffer is written" INFO_TAIL);
273+
274+
res= my_b_flush_io_cache(&info, 1);
275+
ok(res == 0, "flush" INFO_TAIL);
276+
277+
res= reinit_io_cache(&info, READ_CACHE, 0, 0, 0);
278+
ok(res == 0, "reinit READ_CACHE" INFO_TAIL);
279+
280+
info.end_of_file= 100;
281+
res= my_b_read(&info, buf_i, sizeof(buf_i));
282+
ok(res == 1 && buf_i[100] == 0 && buf_i[200-1] == 0,
283+
"short read leaves buf_i[100..200-1] == 0");
284+
285+
close_cached_file(&info);
286+
}
287+
288+
256289
int main(int argc __attribute__((unused)),char *argv[])
257290
{
258291
MY_INIT(argv[0]);
259-
plan(46);
292+
plan(51);
260293

261294
/* temp files with and without encryption */
262295
encrypt_tmp_files= 1;
@@ -272,6 +305,8 @@ int main(int argc __attribute__((unused)),char *argv[])
272305
mdev10259();
273306
encrypt_tmp_files= 0;
274307

308+
mdev14014();
309+
275310
my_end(0);
276311
return exit_status();
277312
}

0 commit comments

Comments
 (0)