What is happening here? 1) When binlog_rows_query_log_events is enabled Rows_query_log_event is created, written to binary log on master prior . 2) Slave is reading read this event from relay log and applying it, see Rows_query_log_event::do_apply_event(). When the event is applied the event itself is stored in Relay_log_info::rows_query_ev: int Rows_query_log_event::do_apply_event(Relay_log_info const *rli) { DBUG_ENTER("Rows_query_log_event::do_apply_event"); DBUG_ASSERT(rli->info_thd == thd); /* Set query for writing Rows_query log event into binlog later.*/ thd->set_query(m_rows_query, strlen(m_rows_query)); DBUG_ASSERT(rli->rows_query_ev == NULL); const_cast(rli)->rows_query_ev= this; /* Tell worker not to free the event */ worker= NULL; DBUG_RETURN(0); } 3) Usually Relay_log_info::rows_query_ev is removed with the following stack trace: #0 Rows_query_log_event::~Rows_query_log_event (this=0x7fff9401df00, __in_chrg=, __vtt_parm=) at ./sql/log_event.h:3795 #1 0x0000000001958d1e in Relay_log_info::cleanup_context (this=0x7fffa40413d0, thd=0x7fff94000950, error=false) at ./sql/rpl_rli.cc:1777 #2 0x00000000018d984b in rows_event_stmt_cleanup (rli=0x7fffa40413d0, thd=0x7fff94000950) at ./sql/log_event.cc:11297 #3 0x00000000018d9500 in Rows_log_event::do_apply_event (this=0x7fff94012fc0, rli=0x7fffa40413d0) at ./sql/log_event.cc:11175 #4 0x00000000018c00c7 in Log_event::apply_event (this=0x7fff94012fc0, rli=0x7fffa40413d0) at ./sql/log_event.cc:3371 #5 0x0000000001938e0f in apply_event_and_update_pos (ptr_ev=0x7ffff139e8a0, thd=0x7fff94000950, rli=0x7fffa40413d0) at ./sql/rpl_slave.cc:4750 #6 0x000000000193a5d7 in exec_relay_log_event (thd=0x7fff94000950, rli=0x7fffa40413d0) at ./sql/rpl_slave.cc:5265 #7 0x00000000019418eb in handle_slave_sql (arg=0x7fffa4139800) at ./sql/rpl_slave.cc:7461 #8 0x0000000001e6a679 in pfs_spawn_thread (arg=0x7fffa413d640) at ./storage/perfschema/pfs.cc:2188 #9 0x00007ffff71616ba in start_thread (arg=0x7ffff139f700) at pthread_create.c:333 #10 0x00007ffff65f682d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:109 But if we look into Rows_log_event::do_apply_event() the function rows_event_stmt_cleanup() is called at the end: int Rows_log_event::do_apply_event(Relay_log_info const *rli) { ... end: if (get_flags(STMT_END_F)) { if((error= rows_event_stmt_cleanup(rli, thd))) { ... } ... } ... } 4) But when the statement must be skipped because it has been already applied Rows_log_event::do_apply_event() exits before rows_event_stmt_cleanup() call. See the following code: int Rows_log_event::do_apply_event(Relay_log_info const *rli) { ... enum_gtid_statement_status state= gtid_pre_statement_checks(thd); if (state == GTID_STATEMENT_EXECUTE) { if (gtid_pre_statement_post_implicit_commit_checks(thd)) state= GTID_STATEMENT_CANCEL; } if (state == GTID_STATEMENT_CANCEL) { uint error= thd->get_stmt_da()->mysql_errno(); DBUG_ASSERT(error != 0); rli->report(ERROR_LEVEL, error, "Error executing row event: '%s'", thd->get_stmt_da()->message_text()); thd->is_slave_error= 1; DBUG_RETURN(-1); } else if (state == GTID_STATEMENT_SKIP) DBUG_RETURN(0); ... end: if (get_flags(STMT_END_F)) { if((error= rows_event_stmt_cleanup(rli, thd))) { ... } ... } ... } So in this case rli->rows_query_ev will not be deleted. In debug build such case should lead to crash due to the corresponding assert in Rows_query_log_event::do_apply_event(): int Rows_query_log_event::do_apply_event(Relay_log_info const *rli) { ... DBUG_ASSERT(rli->rows_query_ev == NULL); ... } But for release build there will just memory leak which we can see in this bug report.