Class: MysqlReplicationMonitor

Inherits:
Object
  • Object
show all
Defined in:
lib/mysql_replication_monitor.rb

Overview

utility to check the replication status between MySQL master and slave dbs set up to replicate to each other

All that is needed is to specify the two dbs by their rails database config (environment) names (e.g. ‘staging_master’, ‘staging_slave’ or whatever).

examples:

# specify both master and slave db configs
monitor = MysqlReplicationMonitor.new(:master => 'master', :slave => 'slave)
# default slave to the current environment
monitor = MysqlReplicationMonitor.new(:master => 'master')
# override the default time to cache the statuses (in seconds)
monitor = MysqlReplicationMonitor.new(:master => 'master', :slave => 'slave,
                                      :refresh_time => 10)
# override the default database config file (not recommended)
monitor = MysqlReplicationMonitor.new(:master => 'master', :slave => 'slave,
                                      :db_config_file => 'foofile.txt')

Defined Under Namespace

Classes: NoReplicationError

Instance Method Summary collapse

Constructor Details

#initialize(options) ⇒ MysqlReplicationMonitor

constructor accepts environment labels for the dbs to query replication status for. if one or the other is not specified, will use the rails environment that the class is currently running under. this object can cache status to reduce traffic on master and slave if this class’s objects are to be called frequently (see :refresh_time option) options:

:master => string containing environment to query the master db status
:slave  => string containing environment to query the slave db status
(one or the other is optional, but never both)
:refresh_time => how many seconds can elapse since last time the dbs
                 were polled before we need to hit dbs again (in between
                 any status methods called will just return cached
                 values). optional, default => 1 (cache very briefly).
                 recommend not setting this to 0, as calls like
                 slave_running? will result in two db hits.
:db_config_file => file containing database config settings. optional,
                   default is rails default (recommended)



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/mysql_replication_monitor.rb', line 47

def initialize(options)
  if options.blank? || (!options.include?(:master) &&
                        !options.include?(:slave))
    raise "Invalid options configuration: should be a hash that includes " +
          "either :master or :slave or both"
  end

  # if asked to override database config file, use the special init()
  # function
  if options[:db_config_file]
    MultipleConnectionHandler.init(:config_file => options[:db_config_file])
  end

  @master_env = options[:master] || RAILS_ENV
  @slave_env = options[:slave] || RAILS_ENV

  @slave_status = nil
  @master_status = nil

  @refresh_time = options[:refresh_time] || 1
  @last_refresh = nil
end

Instance Method Details

#master_and_slave_in_sync?Boolean

indicates if master and slave currently have same log file and log file position. note that if returns false, doesn’t necessarily mean anything is wrong…just that slave is lagging. but if returns true, it may be that slave_running? is false.


Returns:

  • (Boolean)


109
110
111
112
113
114
# File 'lib/mysql_replication_monitor.rb', line 109

def master_and_slave_in_sync?
  cache_check_or_refresh

  @master_status['Position'] == @slave_status['Exec_Master_Log_Pos'] &&
  @master_status['File'] == @slave_status['Relay_Master_Log_File']
end

#raw_master_statusObject

return a hashed version of the result of running SHOW MASTER STATUS




164
165
166
167
168
# File 'lib/mysql_replication_monitor.rb', line 164

def raw_master_status
  cache_check_or_refresh

  @master_status
end

#raw_slave_status(options = {}) ⇒ Object

return a hashed version of the result of running SHOW SLAVE STATUS options:

:refresh_if_stale: indicate whether to refresh the status if it's stale
                   default is true, which should pretty much always be
                   used, unless you're doing some inspection and want to
                   be sure to see the same status that was used by the
                   most recent method call.



153
154
155
156
157
158
159
# File 'lib/mysql_replication_monitor.rb', line 153

def raw_slave_status(options = {})
  if options.blank? || options[:refresh_if_stale]
    cache_check_or_refresh
  end

  @slave_status
end

#refreshObject

force a refresh of the cached status. overrides :refresh_time option.




73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/mysql_replication_monitor.rb', line 73

def refresh
  @master_status = MultipleConnectionHandler.connection(@master_env).
                     execute("SHOW MASTER STATUS").all_hashes[0]
  @slave_status = MultipleConnectionHandler.connection(@slave_env).
                     execute("SHOW SLAVE STATUS").all_hashes[0]

  @last_refresh = Time.now

  if @master_status.blank? && @slave_status.blank?
    raise NoReplicationError,
          "Neither master (#{@master_env}) nor slave (#{@slave_env}) " +
            "appear to be configured for replication"
  elsif @master_status.blank?
    raise NoReplicationError,
          "Master (#{@master_env}) does not appear to be configured for replication"
  elsif @slave_status.blank?
    raise NoReplicationError,
          "Slave (#{@slave_env}) does not appear to be configured for replication"
  end
end

#seconds_behindObject

returns slave’s report of seconds behind master. note: this isn’t super- reliable, especially if the I/O thread is not running.




138
139
140
141
142
# File 'lib/mysql_replication_monitor.rb', line 138

def seconds_behind
  cache_check_or_refresh

  @slave_status['Seconds_Behind_Master'].to_i
end

#slave_io_running?Boolean

returns true if the slave IO thread is running


Returns:

  • (Boolean)


119
120
121
122
123
# File 'lib/mysql_replication_monitor.rb', line 119

def slave_io_running?
  cache_check_or_refresh

  @slave_status['Slave_IO_Running'].downcase == 'yes'
end

#slave_running?Boolean

indicates if both IO and SQL threads are running


Returns:

  • (Boolean)


97
98
99
100
101
# File 'lib/mysql_replication_monitor.rb', line 97

def slave_running?
  cache_check_or_refresh

  slave_io_running? && slave_sql_running?
end

#slave_sql_running?Boolean

returns true if the slave SQL thread is running


Returns:

  • (Boolean)


128
129
130
131
132
# File 'lib/mysql_replication_monitor.rb', line 128

def slave_sql_running?
  cache_check_or_refresh

  @slave_status['Slave_SQL_Running'].downcase == 'yes'
end