Bug #73838 SET GTID_PURGED does not stop WAIT_FOR_EXECUTED_GTID_SET
Submitted: 8 Sep 2014 14:14 Modified: 14 Sep 2015 16:02
Reporter: Sven Sandberg Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server: Replication Severity:S2 (Serious)
Version:5.7 OS:Any
Assigned to: CPU Architecture:Any

[8 Sep 2014 14:14] Sven Sandberg
Description:
WAIT_FOR_EXECUTED_GTID_SET waits until a given set of GTIDs is included in @@GLOBAL.GTID_EXECUTED.
This works for transactions committed either from a normal client session or from a slave thread.
However, if transactions are added to GTID_EXECUTED through SET GTID_PURGED, then WAIT_FOR_EXECUTED_GTID_SET will not notice it.

The problem is a missing signal from the SET GTID_PURGED. So WAIT_FOR_EXECUTED_GTID_SET will wake up and notice the change once a transaction is committed from a client or from a slave thread.

This prevents an interesting use case for WAIT_FOR_EXECUTED_GTID_SET: If this was working, DBA could use WAIT_FOR_EXECUTED_GTID_SET to wait until a restore (e.g. from mysqldump) that ends with SET GTID_PURGED has completed.

How to repeat:
--source include/have_gtid.inc
--let $rpl_gtid_utils= 1
--source include/master-slave.inc

--send
eval
SELECT WAIT_FOR_EXECUTED_GTID_SET('$uuida:1-1000', 5);

--connection default
eval
SET GLOBAL GTID_PURGED = '$uuida:1-1000';

--connection master
# Note that this returns 1, meaning that
# WAIT_FOR_EXECUTED_GTID_SET timed out rather
# than completed successfully as it should.
reap;

exit;

Suggested fix:
(Untested)

=== modified file 'sql/rpl_gtid_state.cc'
--- sql/rpl_gtid_state.cc	revid:balasubramanian.kandasamy@oracle.com-20140908112446-kv7pd0tui348ykbp
+++ sql/rpl_gtid_state.cc	2014-09-08 14:14:04 +0000
@@ -403,6 +403,7 @@ void Gtid_state::unlock_sidnos(const Gti
     if (gs->contains_sidno(sidno))
       unlock_sidno(sidno);
 }
+#endif
 
 
 void Gtid_state::broadcast_sidnos(const Gtid_set *gs)
@@ -413,7 +414,6 @@ void Gtid_state::broadcast_sidnos(const
     if (gs->contains_sidno(sidno))
       broadcast_sidno(sidno);
 }
-#endif
 
 
 enum_return_status Gtid_state::ensure_sidno()

=== modified file 'sql/sys_vars.h'
--- sql/sys_vars.h	revid:balasubramanian.kandasamy@oracle.com-20140908112446-kv7pd0tui348ykbp
+++ sql/sys_vars.h	2014-09-08 14:13:53 +0000
@@ -2212,6 +2212,7 @@ public:
     char *previous_gtid_executed= gtid_state->get_executed_gtids()->to_string();
     char *previous_gtid_lost= gtid_state->get_lost_gtids()->to_string();
     enum_return_status ret= gtid_state->add_lost_gtids(var->save_result.string_value.str);
+    global_sid_lock->broadcast_sidnos(gtid_state->get_lost_gtids());
     char *current_gtid_executed= gtid_state->get_executed_gtids()->to_string();
     char *current_gtid_lost= gtid_state->get_lost_gtids()->to_string();
     global_sid_lock->unlock();
[14 Sep 2015 16:02] Jon Stephens
Documented fix in the 5.7.9 and 5.8.0 changelogs, as follows:

    Transactions added to gtid_executed using SET gtid_purged were
    not taken into account by WAIT_FOR_EXECUTED_GTID_SET() until a
    subsequent transaction was committed by a client or slave
    thread.

Closed.