Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions mysql-test/suite/rpl/r/mdev38829_semisync_write_fail.result
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
call mtr.add_suppression("Write to binary log failed*");
SET GLOBAL rpl_semi_sync_master_enabled = 1;
SET GLOBAL rpl_semi_sync_master_wait_point = 'AFTER_SYNC';
set @saved_dbug = @@global.debug_dbug;
SET GLOBAL debug_dbug='d,injecting_fault_writing';
CREATE TABLE t1 (i INT);
CREATE TABLE t1 (i INT);
ERROR HY000: Error writing file 'master-bin' ((errno: #)
set @@global.debug_dbug = @saved_dbug;
SELECT 1;
1
1
SHOW STATUS LIKE 'Rpl_semi_sync_master_status';
Variable_name Value
Rpl_semi_sync_master_status ON
SET GLOBAL rpl_semi_sync_master_enabled = 0;
SET GLOBAL rpl_semi_sync_master_wait_point = DEFAULT;
DROP TABLE IF EXISTS t1;
36 changes: 36 additions & 0 deletions mysql-test/suite/rpl/t/mdev38829_semisync_write_fail.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#
# MDEV-38829: Assertion `rpl_semi_sync_master_off_times >
# thd->expected_semi_sync_offs' failed in Repl_semi_sync_master::commit_trx()
#
# A failed direct binlog write (write_gtid_event()/write_event() returning an
# error) left semisync registration skipped, but the semisync wait
# (wait_after_sync() -> commit_trx()) still ran unconditionally. commit_trx()
# then found no entry for the transaction and asserted that the only
# possible cause was a concurrent switch_off()/switch_on(), which is false
# here -- the entry was simply never registered.
#
# Verify that a failed direct binlog write no longer triggers a semisync
# wait for a transaction that was never registered: the query should just
# return a clean write error, and the server must remain fully responsive
# (in particular, no assertion failure / crash).
#
--source include/have_debug.inc
--source include/have_binlog_format_mixed_or_statement.inc

call mtr.add_suppression("Write to binary log failed*");

SET GLOBAL rpl_semi_sync_master_enabled = 1;
SET GLOBAL rpl_semi_sync_master_wait_point = 'AFTER_SYNC';

--let $query= CREATE TABLE t1 (i INT)
--source include/binlog_inject_error.inc

# The server must still be fully alive and responsive here -- this is the
# actual regression check: pre-fix, the statement above aborts the
# (debug-build) server via DBUG_ASSERT instead of returning cleanly.
SELECT 1;
SHOW STATUS LIKE 'Rpl_semi_sync_master_status';

SET GLOBAL rpl_semi_sync_master_enabled = 0;
SET GLOBAL rpl_semi_sync_master_wait_point = DEFAULT;
DROP TABLE IF EXISTS t1;
3 changes: 2 additions & 1 deletion sql/log.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7259,7 +7259,8 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info, my_bool *with_annotate)
mysql_mutex_assert_owner(&LOCK_after_binlog_sync);
mysql_mutex_assert_not_owner(&LOCK_commit_ordered);
#ifdef HAVE_REPLICATION
if (repl_semisync_master.wait_after_sync(log_file_name, offset))
if (likely(!error) &&
repl_semisync_master.wait_after_sync(log_file_name, offset))
{
error=1;
/* error is already printed inside hook */
Expand Down