File proxysql_node_monitor of Package proxysql
1
#!/bin/bash
2
# This script will assist to setup Percona XtraDB cluster ProxySQL monitoring script.
3
#####################################################################################
4
5
debug=0
6
7
ERR_FILE="${3:-/dev/null}"
8
if [ -f /etc/proxysql-admin.cnf ]; then
9
source /etc/proxysql-admin.cnf
10
else
11
echo "`date` Assert! proxysql-admin configuration file :/etc/proxysql-admin.cnf does not exists, Terminating!" >> $ERR_FILE
12
exit 1
13
fi
14
15
if [[ -z "$PROXYSQL_DATADIR" ]]; then
16
PROXYSQL_DATADIR='/var/lib/proxysql'
17
fi
18
19
WRITE_HOSTGROUP_ID="${1:-0}"
20
READ_HOSTGROUP_ID="${2:-0}"
21
SLAVEREAD_HOSTGROUP_ID=$READ_HOSTGROUP_ID
22
if [ $SLAVEREAD_HOSTGROUP_ID -eq $WRITE_HOSTGROUP_ID ];then
23
let SLAVEREAD_HOSTGROUP_ID+=1
24
fi
25
26
CHECK_STATUS=0
27
SLAVE_SECONDS_BEHIND=3600 #How far behind can a slave be before its put into OFFLINE_SOFT state
28
CLUSTER_TIMEOUT=3 # Maximum time to wait for cluster status
29
30
proxysql_exec() {
31
query=$1
32
printf "[client]\nuser=${PROXYSQL_USERNAME}\npassword=${PROXYSQL_PASSWORD}\nhost=${PROXYSQL_HOSTNAME}\nport=${PROXYSQL_PORT}\n" | \
33
mysql --defaults-file=/dev/stdin --protocol=tcp -Bse "${query}" 2>/dev/null
34
}
35
36
if [ $debug -eq 1 ];then echo "`date` DEBUG MODE: $MODE" >> $ERR_FILE;fi
37
38
if [ $debug -eq 1 ];then echo "`date` DEBUG check mode name from proxysql data directory " >> $ERR_FILE;fi
39
CLUSTER_NAME=$(proxysql_exec "select comment from scheduler where arg1=$WRITE_HOSTGROUP_ID")
40
if [ -f ${PROXYSQL_DATADIR}/${CLUSTER_NAME}_mode ] ; then
41
MODE=$(cat ${PROXYSQL_DATADIR}/${CLUSTER_NAME}_mode)
42
fi
43
44
if [ "$MODE" == "loadbal" ]; then
45
MODE_COMMENT="READWRITE"
46
WRITE_WEIGHT="1000"
47
else
48
MODE_COMMENT="READ"
49
WRITE_WEIGHT="1000000"
50
fi
51
52
check_cmd(){
53
MPID=$1
54
ERROR_MSG=$2
55
ERROR_INFO=$3
56
if [ ${MPID} -ne 0 ]; then
57
echo "`date` WARNING: $ERROR_MSG." >> $ERR_FILE
58
if [[ ! -z $ERROR_INFO ]]; then
59
echo "`date` $ERROR_INFO." >> $ERR_FILE
60
fi
61
fi
62
}
63
64
#Timeout exists for instances where mysqld may be hung
65
TIMEOUT=10
66
67
mysql_exec() {
68
query=$1
69
printf "[client]\nconnect-timeout=${CLUSTER_TIMEOUT}\nuser=${CLUSTER_USERNAME}\npassword=${CLUSTER_PASSWORD}\nhost=${CLUSTER_HOSTNAME}\nport=${CLUSTER_PORT}\n" | \
70
timeout $TIMEOUT mysql --defaults-file=/dev/stdin --protocol=tcp -Bse "${query}" 2>/dev/null
71
}
72
73
set_slave_status() {
74
# This function checks the status of slave machines and sets their status field
75
# The ws_ip and ws_port variables are used and must be set before calling this function
76
if [ $debug -eq 1 ];then echo "`date` DEBUG START set_slave_status" >> $ERR_FILE;fi
77
# This function will get and return a status of a slave node, 4=GOOD, 2=BEHIND, 0=OTHER
78
SLAVE_STATUS=$(printf "[client]\nuser=${CLUSTER_USERNAME}\npassword=${CLUSTER_PASSWORD}\nhost=${ws_ip}\nport=${ws_port}\n" | timeout $TIMEOUT mysql --defaults-file=/dev/stdin --protocol=tcp -Bse 'SHOW SLAVE STATUS\G' 2>${PROXYSQL_DATADIR}/proxysql_admin_error_info)
79
check_cmd $? "Cannot get status from the slave $ws_ip:$ws_port, Please check cluster login credentials" "`cat ${PROXYSQL_DATADIR}/proxysql_admin_error_info`"
80
SLAVE_STATUS=$(echo "$SLAVE_STATUS" | sed 's/ //g')
81
echo "$SLAVE_STATUS" | grep "^Master_Host:" >/dev/null
82
if [ $? -ne 0 ];then
83
# No status was found, this is not replicating
84
if [ $debug -eq 1 ];then echo "`date` DEBUG set_slave_status: No slave status found, setting to OFFLINE_HARD, status was: $ws_status" >> $ERR_FILE;fi
85
# Only changing the status here as another node might be in the writer hostgroup
86
proxysql_exec "UPDATE mysql_servers set status = 'OFFLINE_HARD', weight=1000 WHERE hostname='$ws_ip' and port=$ws_port;"
87
check_cmd $? "Cannot update Percona XtraDB Cluster node $ws_ip:$ws_port to ProxySQL database, Please check proxysql credentials"
88
echo "`date` ${ws_hg_id}:${i} Slave node set to OFFLINE_HARD status to ProxySQL database." >> $ERR_FILE
89
else
90
slave_master_host=$(echo "$SLAVE_STATUS" | grep "^Master_Host:" | cut -d: -f2)
91
slave_io_running=$(echo "$SLAVE_STATUS" | grep "^Slave_IO_Running:" | cut -d: -f2)
92
slave_sql_running=$(echo "$SLAVE_STATUS" | grep "^Slave_SQL_Running:" | cut -d: -f2)
93
seconds_behind=$(echo "$SLAVE_STATUS" | grep "^Seconds_Behind_Master:" | cut -d: -f2)
94
if [ "$seconds_behind" == "NULL" ];then
95
# When slave_io is not working, the seconds behind value will read 'NULL', convert this to a number higher than the max
96
let seconds_behind=SLAVE_SECONDS_BEHIND+1
97
fi
98
if [ "$slave_io_running" != "Yes" ] && [ "$slave_sql_running" == "Yes" ];then
99
# Cannot connect to the master
100
if [ "$ws_status" == "ONLINE" ];then
101
echo "`date` Slave node (${ws_hg_id}:${i}) This slave cannot connect to it's master: $slave_master_host" >> $ERR_FILE
102
if [ -z "$CLUSTER_OFFLINE" ];then
103
# The cluster is up so this slave should go to OFFLINE_SOFT state
104
proxysql_exec "UPDATE mysql_servers set hostgroup_id = $SLAVEREAD_HOSTGROUP_ID, status = 'OFFLINE_SOFT', weight=1000 WHERE hostname='$ws_ip' and port=$ws_port;"
105
check_cmd $? "Cannot update Percona XtraDB Cluster node $ws_ip:$ws_port to ProxySQL database, Please check proxysql credentials"
106
echo "`date` ${ws_hg_id}:${i} Slave node set to OFFLINE_SOFT status to ProxySQL database." >> $ERR_FILE
107
fi
108
else
109
if [ -n "$CLUSTER_OFFLINE" ];then
110
# The slave is not currently online and cannot connect to its master, but we are here because all cluster nodes are down so put the slave ONLINE
111
if [ $debug -eq 1 ];then echo "`date` DEBUG set_slave_status: Forcing slave $ws_ip:$ws_port ONLINE because cluster is offline" >> $ERR_FILE;fi
112
proxysql_exec "UPDATE mysql_servers set status = 'ONLINE', weight=1000 WHERE hostname='$ws_ip' and port=$ws_port;"
113
check_cmd $? "Cannot update Percona XtraDB Cluster node $ws_ip:$ws_port to ProxySQL database, Please check proxysql credentials"
114
echo "`date` ${SLAVEREAD_HOSTGROUP_ID}:$ws_ip:$ws_port Slave node set to ONLINE status to ProxySQL database." >> $ERR_FILE
115
else
116
echo "`date` Slave node (${ws_hg_id}:${i}) current status '$ws_status' in ProxySQL database!" >> $ERR_FILE
117
fi
118
fi
119
elif [ "$slave_sql_running" != "Yes" ];then
120
# Slave is not replicating
121
if [ "$ws_status" != "OFFLINE_HARD" ];then
122
if [ $debug -eq 1 ];then echo "`date` DEBUG set_slave_status: Setting to OFFLINE_HARD, status was: $ws_status" >> $ERR_FILE;fi
123
proxysql_exec "UPDATE mysql_servers set hostgroup_id = $SLAVEREAD_HOSTGROUP_ID, status = 'OFFLINE_HARD', weight=1000 WHERE hostname='$ws_ip' and port=$ws_port;"
124
check_cmd $? "Cannot update Percona XtraDB Cluster node $ws_ip:$ws_port to ProxySQL database, Please check proxysql credentials"
125
echo "`date` ${ws_hg_id}:${i} Slave node set to OFFLINE_HARD status to ProxySQL database." >> $ERR_FILE
126
else
127
echo "`date` Slave node (${ws_hg_id}:${i}) current status '$ws_status' in ProxySQL database!" >> $ERR_FILE
128
fi
129
elif [ $seconds_behind -gt $SLAVE_SECONDS_BEHIND ];then
130
# Slave is more than the set number of seconds behind, return status 2
131
if [ "$ws_status" != "OFFLINE_SOFT" ];then
132
if [ $debug -eq 1 ];then echo "`date` DEBUG set_slave_status: Setting to OFFLINE_SOFT, status was: $ws_status" >> $ERR_FILE;fi
133
proxysql_exec "UPDATE mysql_servers set hostgroup_id = $SLAVEREAD_HOSTGROUP_ID, status = 'OFFLINE_SOFT', weight=1000 WHERE hostname='$ws_ip' and port=$ws_port;"
134
check_cmd $? "Cannot update Percona XtraDB Cluster node $ws_ip:$ws_port to ProxySQL database, Please check proxysql credentials"
135
echo "`date` ${ws_hg_id}:${i} Slave node set to OFFLINE_SOFT status to ProxySQL database." >> $ERR_FILE
136
else
137
echo "`date` Slave node (${ws_hg_id}:${i}) current status '$ws_status' in ProxySQL database!" >> $ERR_FILE
138
fi
139
else
140
if [ "$ws_status" != "ONLINE" ];then
141
if [ $debug -eq 1 ];then echo "`date` DEBUG set_slave_status: Setting to ONLINE, status was: $ws_status" >> $ERR_FILE;fi
142
proxysql_exec "UPDATE mysql_servers set status = 'ONLINE', weight=1000 WHERE hostname='$ws_ip' and port=$ws_port;"
143
check_cmd $? "Cannot update Percona XtraDB Cluster node $ws_ip:$ws_port to ProxySQL database, Please check proxysql credentials"
144
echo "`date` ${ws_hg_id}:${i} Slave node set to ONLINE status to ProxySQL database." >> $ERR_FILE
145
else
146
echo "`date` Slave node (${ws_hg_id}:${i}) current status '$ws_status' in ProxySQL database!" >> $ERR_FILE
147
fi
148
fi
149
fi
150
if [ $debug -eq 1 ];then echo "`date` DEBUG END set_slave_status" >> $ERR_FILE;fi
151
}
152
153
# Update Percona XtraDB Cluster nodes in ProxySQL database
154
update_cluster(){
155
if [ $debug -eq 1 ];then echo "`date` DEBUG START update_cluster" >> $ERR_FILE;fi
156
current_hosts=(`proxysql_exec "SELECT hostname,port FROM mysql_servers where hostgroup_id in ( $WRITE_HOSTGROUP_ID, $READ_HOSTGROUP_ID, $SLAVEREAD_HOSTGROUP_ID )" | sed 's|\t|:|g' | tr '\n' ' '`)
157
wsrep_address=(`mysql_exec "SHOW STATUS LIKE 'wsrep_incoming_addresses'" | awk '{print $2}' | sed 's|,| |g'`)
158
if [ ${#wsrep_address[@]} -eq 0 ]; then
159
# Cluster might be down, but is there a slave to fall back to?
160
slave_hosts=(`proxysql_exec "SELECT hostname,port FROM mysql_servers where hostgroup_id in ( $WRITE_HOSTGROUP_ID, $SLAVEREAD_HOSTGROUP_ID ) and comment = 'SLAVEREAD'" | sed 's|\t|:|g' | tr '\n' ' '`)
161
if [ ${#slave_hosts[@]} -eq 0 ]; then
162
echo "`date` Alert! wsrep_incoming_addresses is empty. Terminating!" >> $ERR_FILE
163
exit 1
164
fi
165
fi
166
167
for i in "${wsrep_address[@]}"; do
168
if [[ ! " ${current_hosts[@]} " =~ " ${i} " ]]; then
169
if [ $debug -eq 1 ];then echo "`date` DEBUG Host $i in cluster membership was not found in ProxySQL, adding it" >> $ERR_FILE;fi
170
ws_ip=$(echo $i | cut -d':' -f1)
171
ws_port=$(echo $i | cut -d':' -f2)
172
ws_hg_status=$(echo `proxysql_exec "SELECT hostgroup_id,status from mysql_servers WHERE hostname='$ws_ip' and port=$ws_port"`)
173
ws_hg_id=$(echo $ws_hg_status | cut -d' ' -f1)
174
ws_status=$(echo $ws_hg_status | cut -d' ' -f2)
175
echo "`date` Cluster node (${ws_hg_id}:${i}) does not exists in ProxySQL database!" >> $ERR_FILE
176
proxysql_exec "INSERT INTO mysql_servers (hostname,hostgroup_id,port,weight,comment) VALUES ('$ws_ip',$READ_HOSTGROUP_ID,$ws_port,1000,'$MODE_COMMENT');"
177
check_cmd $? "Cannot add Percona XtraDB Cluster node $ws_ip:$ws_port (hostgroup $READ_HOSTGROUP_ID) to ProxySQL database, Please check proxysql credentials"
178
echo "`date` Added ${ws_hg_id}:${i} node into ProxySQL database." >> $ERR_FILE
179
CHECK_STATUS=1
180
fi
181
done
182
183
for i in "${current_hosts[@]}"; do
184
if [[ ! " ${wsrep_address[@]} " =~ " ${i} " ]]; then
185
if [ $debug -eq 1 ];then echo "`date` DEBUG Host $i not found in cluster membership" >> $ERR_FILE;fi
186
# The current host in current_hosts was not found in cluster membership, set it OFFLINE_HARD unless its a slave node
187
ws_ip=$(echo $i | cut -d':' -f1)
188
ws_port=$(echo $i | cut -d':' -f2)
189
ws_hg_status=$(echo `proxysql_exec "SELECT hostgroup_id,status,comment from mysql_servers WHERE hostname='$ws_ip' and port=$ws_port"`)
190
ws_hg_id=$(echo $ws_hg_status | cut -d' ' -f1)
191
ws_status=$(echo $ws_hg_status | cut -d' ' -f2)
192
comment=$(echo $ws_hg_status | cut -d' ' -f3)
193
if [ "$comment" == "SLAVEREAD" ];then
194
if [ $debug -eq 1 ];then echo "`date` DEBUG Host $i is a slave, checking its health" >> $ERR_FILE;fi
195
#This is a slave, check health differently
196
set_slave_status
197
else
198
if [ "$ws_status" == "OFFLINE_SOFT" ]; then
199
echo "`date` Cluster node ${ws_hg_id}:${i} does not exists in cluster membership! Changing status from OFFLINE_SOFT to OFFLINE_HARD" >> $ERR_FILE
200
proxysql_exec "UPDATE mysql_servers set status = 'OFFLINE_HARD', hostgroup_id = $READ_HOSTGROUP_ID, comment='$MODE_COMMENT', weight=1000 WHERE hostname='$ws_ip' and port=$ws_port"
201
check_cmd $? "Cannot update Percona XtraDB Cluster writer node in ProxySQL database, Please check proxysql credentials"
202
CHECK_STATUS=1
203
fi
204
node_status=$(echo `proxysql_exec "SELECT status from mysql_servers WHERE hostname='$ws_ip' and port=$ws_port"`)
205
echo "`date` Cluster node (${ws_hg_id}:${i}) current status '$node_status' in ProxySQL database!" >> $ERR_FILE
206
if [ "$MODE" == "singlewrite" ]; then
207
checkwriter_hid=`proxysql_exec "select hostgroup_id from mysql_servers where comment='WRITE' and status='ONLINE' and hostgroup_id in ($WRITE_HOSTGROUP_ID)"`
208
if [[ -z "$checkwriter_hid" ]]; then
209
current_hosts=(`proxysql_exec "SELECT hostname,port FROM mysql_servers WHERE status='ONLINE' and comment='READ' and hostgroup_id='$READ_HOSTGROUP_ID' ORDER BY random() LIMIT 1" | sed 's|\t|:|g' | tr '\n' ' '`)
210
ws_ip=$(echo $current_hosts | cut -d':' -f1)
211
ws_port=$(echo $current_hosts | cut -d':' -f2)
212
echo "`date` No writer found, promoting $ws_ip:$ws_port as writer node!" >> $ERR_FILE
213
proxysql_exec "UPDATE mysql_servers set hostgroup_id = $WRITE_HOSTGROUP_ID, comment='WRITE', weight=1000000 WHERE hostname='$ws_ip' and port=$ws_port"
214
check_cmd $? "Cannot update Percona XtraDB Cluster writer node in ProxySQL database, Please check proxysql credentials"
215
CHECK_STATUS=1
216
fi
217
fi
218
219
fi
220
fi
221
done
222
223
for i in "${wsrep_address[@]}"; do
224
if [[ ! " ${current_hosts[@]} " == " ${i} " ]]; then
225
if [ $debug -eq 1 ];then echo "`date` DEBUG Host $i was found in cluster membership" >> $ERR_FILE;fi
226
# current_hosts contains the node in wsrep_addresses
227
ws_ip=$(echo $i | cut -d':' -f1)
228
ws_port=$(echo $i | cut -d':' -f2)
229
ws_hg_status=$(echo `proxysql_exec "SELECT hostgroup_id,status from mysql_servers WHERE hostname='$ws_ip' and port=$ws_port"`)
230
ws_hg_id=$(echo $ws_hg_status | cut -d' ' -f1)
231
ws_status=$(echo $ws_hg_status | cut -d' ' -f2)
232
echo "`date` Cluster node (${ws_hg_id}:${i}) current status '$ws_status' in ProxySQL database!" >> $ERR_FILE
233
if [ "$ws_status" == "OFFLINE_HARD" ]; then
234
# The node was OFFLINE_HARD, but its now in the cluster list so lets make it OFFLINE_SOFT
235
proxysql_exec "UPDATE mysql_servers set status = 'OFFLINE_SOFT', weight=1000 WHERE hostname='$ws_ip' and port=$ws_port;"
236
check_cmd $? "Cannot update Percona XtraDB Cluster node $ws_ip:$ws_port to ProxySQL database, Please check proxysql credentials"
237
echo "`date` ${ws_hg_id}:${i} node set to OFFLINE_SOFT status to ProxySQL database." >> $ERR_FILE
238
CHECK_STATUS=1
239
fi
240
fi
241
done
242
if [ $debug -eq 1 ];then echo "`date` DEBUG End update_cluster" >> $ERR_FILE;fi
243
}
244
245
mode_change_check(){
246
if [ $debug -eq 1 ];then echo "`date` DEBUG START mode_change_check" >> $ERR_FILE;fi
247
248
if [ -f $HOST_PRIORITY_FILE ];then
249
# Get the list of hosts from the host_priority file ignoring blanks and any lines that start with '#'
250
priority_hosts=(`cat $HOST_PRIORITY_FILE | grep ^[^#]`)
251
fi
252
# File sample:
253
# 10.11.12.21:3306
254
# 10.21.12.21:3306
255
# 10.31.12.21:3306
256
#
257
258
# Check if the current writer is in an OFFLINE_SOFT state
259
checkwriter_hid=`proxysql_exec "select hostgroup_id from mysql_servers where comment in ('WRITE', 'READWRITE') and status='OFFLINE_SOFT' and hostgroup_id in ($WRITE_HOSTGROUP_ID)"`
260
if [[ -n "$checkwriter_hid" ]]; then
261
# Found a writer node that was in 'OFFLINE_SOFT' state, move it to the READ hostgroup unless the MODE is 'loadbal'
262
if [ "$MODE" != "loadbal" ];then
263
if [ $debug -eq 1 ];then echo "`date` DEBUG mode_change_check: Found OFFLINE_SOFT writer, changing to READ status and hostgroup $READ_HOSTGROUP_ID" >> $ERR_FILE;fi
264
proxysql_exec "UPDATE mysql_servers set hostgroup_id = $READ_HOSTGROUP_ID, comment='READ', weight=1000 WHERE comment='WRITE' and status='OFFLINE_SOFT' and hostgroup_id='$WRITE_HOSTGROUP_ID'"
265
check_cmd $? "Cannot update Percona XtraDB Cluster writer node in ProxySQL database, Please check proxysql credentials"
266
CHECK_STATUS=1
267
fi
268
269
# If that temp file exists use it otherwise choose random as is done now
270
unset current_hosts
271
if [ -z $priority_hosts ];then
272
# Order file wasn't found, behave as before
273
current_hosts=(`proxysql_exec "SELECT hostname,port FROM mysql_servers WHERE status='ONLINE' and comment in ('READ', 'READWRITE') and hostgroup_id='$READ_HOSTGROUP_ID' ORDER BY random() LIMIT 1" | sed 's|\t|:|g' | tr '\n' ' '`)
274
else
275
# Get the list of all ONLINE reader nodes in ProxySQL
276
current_hosts=(`proxysql_exec "SELECT hostname,port FROM mysql_servers WHERE status='ONLINE' and comment='READ' and hostgroup_id='$READ_HOSTGROUP_ID' " | sed 's|\t|:|g' | tr '\n' ' '`)
277
278
# Find the highest priority host from the online reader hosts
279
for i in "${priority_hosts[@]}"; do
280
if [[ " ${current_hosts[@]} " =~ " ${i} " ]]; then
281
# This host in priority_hosts was found in the list of current_hosts
282
current_hosts=${i}
283
found_host=1
284
break
285
fi
286
done
287
if [ -z $found_host ];then
288
# None of the priority hosts were found as active, picking the first on the list from what is available.
289
current_hosts=(`echo $current_hosts | cut -d' ' -f1`)
290
unset found_host
291
fi
292
fi
293
294
# If the $current_hosts variabe is empty here then it's time to put the SLAVEREAD node in if there is one
295
if [ -z "$current_hosts" ];then
296
# Verify a slave is not already in the write hostgroup
297
if [ $debug -eq 1 ];then echo "`date` DEBUG mode_change_check: No cluster members available, check if any slaves are already in the writer hostgroup" >> $ERR_FILE;fi
298
slave_check=(`proxysql_exec "SELECT hostname,port FROM mysql_servers WHERE status='ONLINE' and comment='SLAVEREAD' and hostgroup_id=$WRITE_HOSTGROUP_ID ORDER BY random() LIMIT 1" | sed 's|\t|:|g' | tr '\n' ' '`)
299
if [ -z "$slave_check" ];then
300
# no slaves were currently in the writer group
301
if [ $debug -eq 1 ];then echo "`date` DEBUG mode_change_check: No slaves currently in the writer group" >> $ERR_FILE;fi
302
current_hosts=(`proxysql_exec "SELECT hostname,port FROM mysql_servers WHERE status='ONLINE' and comment='SLAVEREAD' ORDER BY random() LIMIT 1" | sed 's|\t|:|g' | tr '\n' ' '`)
303
slave_write="1"
304
else
305
if [ $debug -eq 1 ];then echo "`date` DEBUG mode_change_check: A slave is already in the writer hostgroup" >> $ERR_FILE;fi
306
fi
307
fi
308
309
ws_ip=$(echo $current_hosts | cut -d':' -f1)
310
ws_port=$(echo $current_hosts | cut -d':' -f2)
311
312
# If the cluster is failed and a slave was already in as writer, the current_hosts variable will be empty
313
if [ "$slave_write" == "1" ] && [ -n "$current_hosts" ];then
314
if [ $debug -eq 1 ];then echo "`date` DEBUG mode_change_check1: Changing $ws_ip:$ws_port to hostgroup $WRITE_HOSTGROUP_ID" >> $ERR_FILE;fi
315
proxysql_exec "UPDATE mysql_servers set hostgroup_id = $WRITE_HOSTGROUP_ID, weight=$WRITE_WEIGHT WHERE hostname='$ws_ip' and port=$ws_port"
316
check_cmd $? "Cannot update Percona XtraDB Cluster writer node in ProxySQL database, Please check proxysql credentials"
317
echo "`date` $ws_ip:$ws_port (slave) is ONLINE, switching to write hostgroup" >> $ERR_FILE
318
CHECK_STATUS=1
319
elif [ "$MODE" != "loadbal" ] && [ -n "$current_hosts" ];then
320
# Only do this if the MODE is not 'loadbal'
321
if [ $debug -eq 1 ];then echo "`date` DEBUG mode_change_check1: Changing $ws_ip:$ws_port to WRITE status and hostgroup $WRITE_HOSTGROUP_ID" >> $ERR_FILE;fi
322
proxysql_exec "UPDATE mysql_servers set hostgroup_id = $WRITE_HOSTGROUP_ID, comment='WRITE', weight=$WRITE_WEIGHT WHERE hostname='$ws_ip' and port=$ws_port"
323
check_cmd $? "Cannot update Percona XtraDB Cluster writer node in ProxySQL database, Please check proxysql credentials"
324
echo "`date` $ws_ip:$ws_port is ONLINE, switching to write hostgroup" >> $ERR_FILE
325
CHECK_STATUS=1
326
fi
327
else
328
# The current writer was not in OFFLINE_SOFT state
329
# Now check if the current writer is a slave node and pull it out if other nodes are available
330
# Should check if a slave is the current writer and pull it out if a cluster node is available
331
checkslave_hid=`proxysql_exec "select hostgroup_id from mysql_servers where hostgroup_id='$WRITE_HOSTGROUP_ID' AND comment='SLAVEREAD'"`
332
# Set a variable containing a random available cluster node
333
available_cluster_hosts=(`proxysql_exec "SELECT hostname,port FROM mysql_servers WHERE status='ONLINE' and comment in ('READ', 'READWRITE') ORDER BY random() LIMIT 1" | sed 's|\t|:|g' | tr '\n' ' '`)
334
if [[ -n "$checkslave_hid" ]]; then
335
# The current writer is a slave, check for other ONLINE nodes to put in
336
if [ -n "$available_cluster_hosts" ];then
337
# There is a regular cluster node available, pull out the slave
338
if [ $debug -eq 1 ];then echo "`date` DEBUG mode_change_check1: Changing any SLAVEREAD nodes in hostgroup $WRITE_HOSTGROUP_ID to hostgroup $SLAVEREAD_HOSTGROUP_ID" >> $ERR_FILE;fi
339
proxysql_exec "UPDATE mysql_servers set hostgroup_id = $SLAVEREAD_HOSTGROUP_ID, weight=1000 WHERE hostgroup_id='$WRITE_HOSTGROUP_ID' and comment='SLAVEREAD'"
340
check_cmd $? "Cannot update Percona XtraDB Cluster writer node in ProxySQL database, Please check proxysql credentials"
341
writer_was_slave=1
342
fi
343
fi
344
345
if [ -z $priority_hosts ];then
346
# Order file wasn't found
347
# Do not change the config of a cluster node if the MODE is 'loadbal'
348
if [ -n "$available_cluster_hosts" ] && [ -n "$writer_was_slave" ] && [ "$MODE" != "loadbal" ];then
349
# There is a regular cluster node available, put it back in the writer hostgroup
350
ws_ip=$(echo $available_cluster_hosts | cut -d':' -f1)
351
ws_port=$(echo $available_cluster_hosts | cut -d':' -f2)
352
if [ $debug -eq 1 ];then echo "`date` DEBUG mode_change_check2: Changing $ws_ip:$ws_port to WRITE status and hostgroup $WRITE_HOSTGROUP_ID" >> $ERR_FILE;fi
353
proxysql_exec "UPDATE mysql_servers set hostgroup_id = $WRITE_HOSTGROUP_ID, comment='WRITE', weight=$WRITE_WEIGHT WHERE hostname='$ws_ip' and port=$ws_port"
354
check_cmd $? "Cannot update Percona XtraDB Cluster writer node in ProxySQL database, Please check proxysql credentials"
355
echo "`date` $ws_ip:$ws_port is ONLINE, switching to write hostgroup" >> $ERR_FILE
356
CHECK_STATUS=1
357
fi
358
else
359
# Check here if the highest priority node is the writer
360
# Get the list of all ONLINE nodes in ProxySQL, can't use available_cluster_hosts here
361
current_hosts=(`proxysql_exec "SELECT hostname,port FROM mysql_servers WHERE status='ONLINE' and hostgroup_id in($READ_HOSTGROUP_ID,$WRITE_HOSTGROUP_ID) AND comment<>'SLAVEREAD'" | sed 's|\t|:|g' | tr '\n' ' '`)
362
363
# Find the highest priority host from the online hosts
364
for i in "${priority_hosts[@]}"; do
365
if [[ " ${current_hosts[@]} " =~ " ${i} " ]]; then
366
# This host in priority_hosts was found in the list of current_hosts
367
current_hosts=${i}
368
found_host=1
369
break
370
fi
371
done
372
373
# Only initiate changing hosts if a more priority host was found
374
if [ -n $found_host ];then
375
# Check to see if the host in 'current_host' is the writer
376
current_writer=(`proxysql_exec "SELECT hostname,port FROM mysql_servers WHERE status='ONLINE' and comment='WRITE' and hostgroup_id=$WRITE_HOSTGROUP_ID" | sed 's|\t|:|g' | tr '\n' ' '`)
377
if [ "$current_hosts" != "$current_writer" ];then
378
# Switch the writer around
379
if [ -n "$current_writer" ];then
380
# Move the current writer host to reader hostgroup if there is one
381
ws_ip=$(echo $current_writer | cut -d':' -f1)
382
ws_port=$(echo $current_writer | cut -d':' -f2)
383
if [ $debug -eq 1 ];then echo "`date` DEBUG mode_change_check3: Changing $ws_ip:$ws_port to READ status and hostgroup $READ_HOSTGROUP_ID" >> $ERR_FILE;fi
384
proxysql_exec "UPDATE mysql_servers set hostgroup_id = $READ_HOSTGROUP_ID, comment='READ', weight=1000 WHERE hostname='$ws_ip' and port=$ws_port"
385
check_cmd $? "Cannot update Percona XtraDB Cluster reader node in ProxySQL database, Please check proxysql credentials"
386
echo "`date` $ws_ip:$ws_port is ONLINE but a higher priority node is available, switching to read hostgroup" >> $ERR_FILE
387
fi
388
# Move the priority host to the writer hostgroup
389
ws_ip=$(echo $current_hosts | cut -d':' -f1)
390
ws_port=$(echo $current_hosts | cut -d':' -f2)
391
if [ $debug -eq 1 ];then echo "`date` DEBUG mode_change_check3: Changing $ws_ip:$ws_port to WRITE status and hostgroup $WRITE_HOSTGROUP_ID" >> $ERR_FILE;fi
392
proxysql_exec "UPDATE mysql_servers set hostgroup_id = $WRITE_HOSTGROUP_ID, comment='WRITE', weight=$WRITE_WEIGHT WHERE hostname='$ws_ip' and port=$ws_port"
393
check_cmd $? "Cannot update Percona XtraDB Cluster writer node in ProxySQL database, Please check proxysql credentials"
394
echo "`date` $ws_ip:$ws_port is ONLINE and highest priority, switching to write hostgroup" >> $ERR_FILE
395
CHECK_STATUS=1
396
fi
397
else
398
if [ -n "$available_cluster_hosts" ] && [ -n "$writer_was_slave" ];then
399
# There is a regular cluster node available, pull out the slave and put the cluster node back in the writer hostgroup
400
ws_ip=$(echo $available_cluster_hosts | cut -d':' -f1)
401
ws_port=$(echo $available_cluster_hosts | cut -d':' -f2)
402
if [ $debug -eq 1 ];then echo "`date` DEBUG mode_change_check4: Changing $ws_ip:$ws_port to hostgroup $WRITE_HOSTGROUP_ID" >> $ERR_FILE;fi
403
proxysql_exec "UPDATE mysql_servers set hostgroup_id = $WRITE_HOSTGROUP_ID, weight=$WRITE_WEIGHT WHERE hostname='$ws_ip' and port=$ws_port"
404
check_cmd $? "Cannot update Percona XtraDB Cluster writer node in ProxySQL database, Please check proxysql credentials"
405
echo "`date` $ws_ip:$ws_port is ONLINE, switching to write hostgroup" >> $ERR_FILE
406
CHECK_STATUS=1
407
fi
408
fi
409
fi
410
fi
411
if [ $debug -eq 1 ];then echo "`date` DEBUG END mode_change_check" >> $ERR_FILE;fi
412
}
413
414
# Monitoring user needs 'REPLICATION CLIENT' privilege
415
echo "`date` ###### Percona XtraDB Cluster status ######" >> $ERR_FILE
416
CLUSTER_USERNAME=$(proxysql_exec "SELECT variable_value FROM global_variables WHERE variable_name='mysql-monitor_username'")
417
check_cmd $? "Could not retrieve cluster login info from ProxySQL. Please check cluster login credentials"
418
419
CLUSTER_PASSWORD=$(proxysql_exec "SELECT variable_value FROM global_variables WHERE variable_name='mysql-monitor_password'")
420
check_cmd $? "Could not retrieve cluster login info from ProxySQL. Please check cluster login credentials"
421
422
CLUSTER_HOST_INFO=`proxysql_exec "SELECT hostname,port FROM mysql_servers WHERE status='ONLINE' and comment<>'SLAVEREAD' and hostgroup_id in ($WRITE_HOSTGROUP_ID, $READ_HOSTGROUP_ID) limit 1"`
423
check_cmd $? "Could not retrieve cluster node info from ProxySQL. Please check cluster login credentials"
424
425
CLUSTER_HOSTS=($(proxysql_exec "SELECT hostname || '-' || port FROM mysql_servers WHERE status='ONLINE' and comment<>'SLAVEREAD' and hostgroup_id in ($WRITE_HOSTGROUP_ID, $READ_HOSTGROUP_ID)"))
426
CLUSTER_TIMEOUT=($(proxysql_exec "SELECT MAX(interval_ms / 1000 - 1, 1) FROM scheduler"))
427
428
for i in "${CLUSTER_HOSTS[@]}"; do
429
CLUSTER_HOSTNAME=$(echo $i | cut -d'-' -f1)
430
CLUSTER_PORT=$(echo $i | cut -d'-' -f2)
431
CHECK_SERVER_STATUS=$(mysql_exec "SELECT @@port")
432
if [[ -n $CHECK_SERVER_STATUS ]]; then
433
CLUSTER_HOST_INFO="${CHECK_SERVER_STATUS}"
434
break
435
else
436
CLUSTER_HOST_INFO=""
437
fi
438
done
439
440
if [[ -z $CLUSTER_HOST_INFO ]]; then
441
if [ $debug -eq 1 ];then echo "`date` DEBUG Can't get cluster info, checking if a slave is available" >> $ERR_FILE;fi
442
# Set CLUSTER_OFFLINE variable, used my the set_slave_status function and the bottom of this script
443
CLUSTER_OFFLINE=1
444
# No Cluster nodes are available, but is a slave available?
445
SLAVE_CHECK=`proxysql_exec "SELECT hostname,port FROM mysql_servers WHERE comment='SLAVEREAD' limit 1"`
446
if [[ ! -z $SLAVE_CHECK ]]; then
447
SLAVE_HOST_INFO=`proxysql_exec "SELECT hostname,port FROM mysql_servers WHERE status='ONLINE' and comment='SLAVEREAD' and hostgroup_id in ($WRITE_HOSTGROUP_ID, $SLAVEREAD_HOSTGROUP_ID) limit 1"`
448
check_cmd $? "Could not retrieve cluster login info from ProxySQL. Please check cluster login credentials"
449
if [[ -z $SLAVE_HOST_INFO ]]; then
450
if [ $debug -eq 1 ];then echo "`date` DEBUG No online slaves were found, will recheck" >> $ERR_FILE;fi
451
# Check for a slave in a status other than 'ONLINE'
452
# This is an emergency measure, just put a random slave online
453
# Would be nice to try to find the most up to date slave if there is more than one, but that would require
454
# a query to all slaves to check their positions, probably not worth the overhead - something to think about
455
slave_host=(`proxysql_exec "SELECT hostname,port FROM mysql_servers where comment='SLAVEREAD' and hostgroup_id in ($WRITE_HOSTGROUP_ID, $SLAVEREAD_HOSTGROUP_ID) ORDER BY random() LIMIT 1" | sed 's|\t|:|g' | tr '\n' ' '`)
456
if [ $debug -eq 1 ];then echo "`date` DEBUG Trying to bring slave: $slave_host ONLINE due to cluster being down" >> $ERR_FILE;fi
457
ws_ip=$(echo $slave_host | cut -d':' -f1)
458
ws_port=$(echo $slave_host | cut -d':' -f2)
459
set_slave_status
460
else
461
if [ $debug -eq 1 ];then echo "`date` DEBUG online slaves were found" >> $ERR_FILE;fi
462
# Run function here to move the slave into the write hostgroup
463
mode_change_check
464
fi
465
fi
466
SLAVE_HOST_INFO=`proxysql_exec "SELECT hostname,port FROM mysql_servers WHERE status='ONLINE' and comment='SLAVEREAD' and hostgroup_id='$WRITE_HOSTGROUP_ID' limit 1"`
467
if [[ -z $SLAVE_HOST_INFO ]]; then
468
offline_hosts=(`proxysql_exec "SELECT hostgroup_id,hostname,port,status FROM mysql_servers where hostgroup_id in ( $WRITE_HOSTGROUP_ID, $READ_HOSTGROUP_ID, $SLAVEREAD_HOSTGROUP_ID )" | sed 's|\t|:|g' | tr '\n' ' '`)
469
for i in "${offline_hosts[@]}"; do
470
offline_host=(`echo ${i} | awk -F: '{print $1 ":" $2 ":" $3}'`)
471
offline_host_status=(`echo ${i} | cut -d':' -f4`)
472
echo "`date` Cluster node ($offline_host) current status '$offline_host_status' in ProxySQL database!" >> $ERR_FILE
473
done
474
else
475
echo "`date` Percona XtraDB Cluster nodes are offline, a slave node is in the writer hostgroup, please check status" >> $ERR_FILE
476
fi
477
else
478
update_cluster
479
mode_change_check
480
fi
481
482
if [ $CHECK_STATUS -eq 0 ]; then
483
if [ -z "$CLUSTER_OFFLINE" ];then
484
echo "`date` Percona XtraDB Cluster membership looks good" >> $ERR_FILE
485
else
486
echo "`date` Percona XtraDB Cluster is offline!" >> $ERR_FILE
487
fi
488
else
489
echo "`date` ###### Loading mysql_servers config into runtime ######" >> $ERR_FILE
490
proxysql_exec "LOAD MYSQL SERVERS TO RUNTIME"
491
fi
492
exit 0
493