Skip to content

Commit 184b5fd

Browse files
committed
Merge pull request alphagov#160 from alphagov/mysql_reset_slave
Add a task to reset a MySQL slave and query its status
2 parents 2bf8942 + 99cabcd commit 184b5fd

File tree

1 file changed

+51
-3
lines changed

1 file changed

+51
-3
lines changed

mysql.py

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@
22

33

44
def run_mysql_command(cmd):
5-
with shell_env(HOME='/root'):
6-
sudo('mysql -e "{}"'.format(cmd))
5+
run('sudo -i mysql -e "{}"'.format(cmd))
76

87

98
def switch_slow_query_log(value):
@@ -68,4 +67,53 @@ def setup_slave_from_master(master):
6867
run_mysql_command("START SLAVE")
6968
run_mysql_command("SET GLOBAL slow_query_log=ON")
7069

71-
run_mysql_command("SHOW SLAVE STATUS\G")
70+
slave_status()
71+
72+
73+
@task
74+
def reset_slave():
75+
"""
76+
Used to reset a slave if MySQL replication is failing
77+
78+
If you see that the slave is 'NULL' seconds behind the master,
79+
the problem may be resolved by running this task.
80+
81+
See docs on 'RESET SLAVE':
82+
https://dev.mysql.com/doc/refman/5.5/en/reset-slave.html
83+
"""
84+
85+
# Confirm slave status in case we need to refer to the values later
86+
slave_status()
87+
run_mysql_command("STOP SLAVE;")
88+
89+
with hide('everything'):
90+
# Store last known log file and position
91+
master_log_file = run("sudo -i mysql -e 'SHOW SLAVE STATUS\G' | grep '^\s*Relay_Master_Log_File:' | awk '{ print $2 }'")
92+
master_log_pos = run("sudo -i mysql -e 'SHOW SLAVE STATUS\G' | grep '^\s*Exec_Master_Log_Pos:' | awk '{ print $2 }'")
93+
94+
if not master_log_file or not master_log_pos:
95+
abort("Failed to determine replication log file and position, aborting.")
96+
97+
# Forget log file and position
98+
run_mysql_command("RESET SLAVE;")
99+
100+
# Repoint log file and position to last known values
101+
run_mysql_command("CHANGE MASTER TO MASTER_LOG_FILE='{}', MASTER_LOG_POS={};" \
102+
.format(master_log_file, master_log_pos))
103+
run_mysql_command("START SLAVE;")
104+
105+
with hide('everything'):
106+
seconds_behind_master = run("sudo -i mysql -e 'SHOW SLAVE STATUS\G' | grep '^\s*Seconds_Behind_Master:' | awk '{ print $2 }'")
107+
108+
# Compare as a string to ensure we got a non-nil value from MySQL
109+
if seconds_behind_master != '0':
110+
abort("Slave is still behind master by {} seconds; run mysql.slave_status to check status" \
111+
.format(seconds_behind_master))
112+
113+
114+
@task
115+
def slave_status():
116+
"""
117+
Show status of MySQL replication on slave; must be run against the slave host
118+
"""
119+
run_mysql_command("SHOW SLAVE STATUS\G;")

0 commit comments

Comments
 (0)