@@ -808,8 +808,10 @@ static ulonglong get_heartbeat_period(THD * thd)
808
808
@param packet buffer to store the heartbeat instance
809
809
@param event_coordinates binlog file name and position of the last
810
810
real event master sent from binlog
811
+ @param send_timestamp flag enables sending the HB event with
812
+ the current timestamp: time().
811
813
812
- @note
814
+ @note
813
815
Among three essential pieces of heartbeat data Log_event::when
814
816
is computed locally.
815
817
The error to send is serious and should force terminating
@@ -818,17 +820,22 @@ static ulonglong get_heartbeat_period(THD * thd)
818
820
static int send_heartbeat_event (NET* net, String* packet,
819
821
const struct event_coordinates *coord,
820
822
bool is_semi_sync_slave,
821
- uint8 checksum_alg_arg)
823
+ uint8 checksum_alg_arg,
824
+ bool send_timestamp)
822
825
{
823
826
DBUG_ENTER (" send_heartbeat_event" );
824
827
char header[LOG_EVENT_HEADER_LEN];
825
828
my_bool do_checksum= checksum_alg_arg != BINLOG_CHECKSUM_ALG_OFF &&
826
829
checksum_alg_arg != BINLOG_CHECKSUM_ALG_UNDEF;
827
830
828
- // NOTE: if @last_master_timestamp is provided we're a slave and we use this
829
- // value in the HB event otherwise we use now()
830
- time_t ts= mysql_bin_log.last_master_timestamp .load ();
831
- if (!ts) ts= time (0 );
831
+ time_t ts= 0 ;
832
+
833
+ if (send_timestamp) {
834
+ // NOTE: if @last_master_timestamp is provided we're a slave and we use this
835
+ // value in the HB event otherwise we use now()
836
+ ts= mysql_bin_log.last_master_timestamp .load ();
837
+ if (!ts) ts= time (0 );
838
+ }
832
839
memcpy (header, &ts, 4 );
833
840
834
841
header[EVENT_TYPE_OFFSET] = HEARTBEAT_LOG_EVENT;
@@ -880,6 +887,15 @@ static int send_heartbeat_event(NET* net, String* packet,
880
887
later. Note that, the caller has to send the last skipped coordinates
881
888
to this function.
882
889
890
+ Note that this function will not send HeartBeat events that carry the current
891
+ timestamp. This this because this function is ONLY used to send HB update
892
+ when the previous transaction has been skipped. Note that HB events'
893
+ timestamps will be used by the slave to calculate the seconds behind master.
894
+
895
+ The only place that makes sense for the event to carry a timestamp is when
896
+ the master is waiting on the update and keeping sending HB events to keep
897
+ the connection.
898
+
883
899
@param[in] net This master-slave network handler
884
900
@param[in] packet packet that is to be sent to the slave.
885
901
@param[in] last_skip_coord coordinates for last skipped transaction
@@ -904,17 +920,24 @@ static int send_last_skip_group_heartbeat(THD *thd, NET* net, String *packet,
904
920
String save_packet;
905
921
int save_offset= *ev_offset;
906
922
907
- /* Save the current read packet */
923
+ /* Save the current read packet */
908
924
save_packet.swap (*packet);
909
925
910
926
if (reset_transmit_packet (thd, 0 , ev_offset, errmsg, observe_transmission,
911
927
packet, packet_buffer, packet_buffer_size,
912
928
semi_sync_slave))
913
929
DBUG_RETURN (-1 );
914
930
915
- /* Send heart beat event to the slave to update slave threads coordinates */
916
- if (send_heartbeat_event (net, packet, last_skip_coord,
917
- semi_sync_slave, checksum_alg_arg))
931
+ /* *
932
+ * Send heart beat event to the slave to update slave threads coordinates
933
+ * Note that we will not send timestamp in these heart beat events
934
+ */
935
+ if (send_heartbeat_event (net,
936
+ packet,
937
+ last_skip_coord,
938
+ semi_sync_slave,
939
+ checksum_alg_arg,
940
+ false ))
918
941
{
919
942
*errmsg= " Failed on my_net_write()" ;
920
943
my_errno= ER_UNKNOWN_ERROR;
@@ -1922,6 +1945,10 @@ void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos,
1922
1945
// Both diff_timespec() and heartbeat_period are in nano seconds.
1923
1946
time_for_hb_event= (diff_timespec (cur_clock, last_event_sent_ts) >=
1924
1947
heartbeat_period);
1948
+ DBUG_EXECUTE_IF (" send_zero_hb_event" ,
1949
+ {
1950
+ time_for_hb_event= true ;
1951
+ });
1925
1952
}
1926
1953
1927
1954
if ((!skip_group && last_skip_group
@@ -1938,6 +1965,10 @@ void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos,
1938
1965
is the first event to be sent to the slave. In this case, it is
1939
1966
no need to send a HB event (which might have coordinates
1940
1967
of previous binlog file).
1968
+
1969
+ This heartbeat event sending only happens when the master is in the
1970
+ middle or has just completed skipping all the trxs. Therefore, HB
1971
+ shouldn't carry Timestamp.
1941
1972
*/
1942
1973
1943
1974
if (send_last_skip_group_heartbeat (thd, net, packet, p_last_skip_coord,
@@ -2210,6 +2241,10 @@ void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos,
2210
2241
If the heartbeat is on, it is better to send a heartbeat
2211
2242
event as the time_out of certain functions (Ex: master_pos_wait()
2212
2243
or semi sync ack timeout) might be less than heartbeat period.
2244
+
2245
+ This can happen when the slave has exact same GTID as the master.
2246
+ In this case, we still send the first HB with 0 timestamp to be
2247
+ safe since the follow up HB with carry the right timestamp
2213
2248
*/
2214
2249
if (skip_group)
2215
2250
{
@@ -2254,8 +2289,19 @@ void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos,
2254
2289
thd->EXIT_COND (&old_stage);
2255
2290
GOTO_ERR;
2256
2291
}
2257
- if (send_heartbeat_event (net, packet, p_coord,
2258
- semi_sync_slave, current_checksum_alg))
2292
+ /* *
2293
+ * HB events sent here are essentially when the master is waiting
2294
+ * on updates and send HB to keep the connection connected.
2295
+ *
2296
+ * This is the only place that sending HB with Timestamp makes
2297
+ * sense and won't break monotonic TS calculated SBM
2298
+ */
2299
+ if (send_heartbeat_event (net,
2300
+ packet,
2301
+ p_coord,
2302
+ semi_sync_slave,
2303
+ current_checksum_alg,
2304
+ true ))
2259
2305
{
2260
2306
errmsg = " Failed on my_net_write()" ;
2261
2307
my_errno= ER_UNKNOWN_ERROR;
@@ -2357,7 +2403,11 @@ void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos,
2357
2403
2358
2404
if (!skip_group && !goto_next_binlog)
2359
2405
{
2360
- /* If the last group was skipped, send a HB event */
2406
+ /* *
2407
+ * If the last group was skipped, send a HB event,
2408
+ * similarly, HB sent here should not carry TS since the last
2409
+ * trx is skipped and we are not sure if we are waiting on update
2410
+ */
2361
2411
if (last_skip_group &&
2362
2412
send_last_skip_group_heartbeat (thd, net, packet,
2363
2413
p_last_skip_coord, &ev_offset,
0 commit comments