1414 QueryEvent , RotateEvent , FormatDescriptionEvent ,
1515 XidEvent , GtidEvent , StopEvent ,
1616 BeginLoadQueryEvent , ExecuteLoadQueryEvent ,
17- NotImplementedEvent )
17+ HeartbeatLogEvent , NotImplementedEvent )
1818from .row_event import (
1919 UpdateRowsEvent , WriteRowsEvent , DeleteRowsEvent , TableMapEvent )
2020
@@ -134,7 +134,8 @@ def __init__(self, connection_settings, server_id, ctl_connection_settings=None,
134134 freeze_schema = False , skip_to_timestamp = None ,
135135 report_slave = None , slave_uuid = None ,
136136 pymysql_wrapper = None ,
137- fail_on_table_metadata_unavailable = False ):
137+ fail_on_table_metadata_unavailable = False ,
138+ slave_heartbeat = None ):
138139 """
139140 Attributes:
140141 ctl_connection_settings: Connection settings for cluster holding schema information
@@ -154,6 +155,11 @@ def __init__(self, connection_settings, server_id, ctl_connection_settings=None,
154155 slave_uuid: Report slave_uuid in SHOW SLAVE HOSTS.
155156 fail_on_table_metadata_unavailable: Should raise exception if we can't get
156157 table information on row_events
158+ slave_heartbeat: (seconds) Should master actively send heartbeat on
159+ connection. This also reduces traffic in GTID replication
160+ on replication resumption (in case many event to skip in
161+ binlog). See MASTER_HEARTBEAT_PERIOD in mysql documentation
162+ for semantics
157163 """
158164
159165 self .__connection_settings = connection_settings
@@ -192,6 +198,7 @@ def __init__(self, connection_settings, server_id, ctl_connection_settings=None,
192198 if report_slave :
193199 self .report_slave = ReportSlave (report_slave )
194200 self .slave_uuid = slave_uuid
201+ self .slave_heartbeat = slave_heartbeat
195202
196203 if pymysql_wrapper :
197204 self .pymysql_wrapper = pymysql_wrapper
@@ -268,6 +275,22 @@ def __connect_to_stream(self):
268275 cur .execute ("set @slave_uuid= '%s'" % self .slave_uuid )
269276 cur .close ()
270277
278+ if self .slave_heartbeat :
279+ # 4294967 is documented as the max value for heartbeats
280+ net_timeout = float (self .__connection_settings .get ('read_timeout' ,
281+ 4294967 ))
282+ # If heartbeat is too low, the connection will disconnect before,
283+ # this is also the behavior in mysql
284+ heartbeat = float (min (net_timeout / 2. , self .slave_heartbeat ))
285+ if heartbeat > 4294967 :
286+ heartbeat = 4294967
287+
288+ # master_heartbeat_period is nanoseconds
289+ heartbeat = int (heartbeat * 1000000000 )
290+ cur = self ._stream_connection .cursor ()
291+ cur .execute ("set @master_heartbeat_period= %d" % heartbeat )
292+ cur .close ()
293+
271294 self ._register_slave ()
272295
273296 if not self .auto_position :
@@ -450,7 +473,9 @@ def _allowed_event_list(self, only_events, ignored_events,
450473 WriteRowsEvent ,
451474 DeleteRowsEvent ,
452475 TableMapEvent ,
453- NotImplementedEvent ))
476+ HeartbeatLogEvent ,
477+ NotImplementedEvent ,
478+ ))
454479 if ignored_events is not None :
455480 for e in ignored_events :
456481 events .remove (e )
0 commit comments