Pull to refresh

Проверка репликации MySQL master-master через Zabbix

Reading time 3 min
Views 5.8K
После настройки MySQL репликации master-master, следующий логический шаг это настройка проверки этой системы. Читая туториалы по интернету стало ясно, что подобная репликация — дело популярное, а слетает оно на раз два три. Поэтому решил вставить проверку — а работает ли репликация до сих пор, или что-нибудь произошло и все слетело.
Первые же несколько гугл запросов показали, что верить «SHOW SLAVE STATUS\G» нельзя: Штука хорошая, но врет часто и помногу. Немного подумав, я пришел к следующему решению:

*На двух серверах создается database, в ней табличка, в которую по крону пишут оба сервера. Репликация автоматически должна переносить данные с одного на другой сервер.
*Пишется скрипт, который вызывается по крону для обновления данных.
*Пишется скрипт, который читает табличку и смотрит когда последний раз обновились данные с «другого» сервера. Если все хорошо — пишет 1, если нет — 0 (такой статус легче проверять заббиксом)
*Вписывается свой UserParameter в конфиг заббикс агента. Добавляются триггеры в заббикс
*Кофе

Подготовка

На обоих серверах создаем базу и таблицы:

create database repl_check;
use repl_check;
create table repl_status(s_id int, server_time TIMESTAMP);
insert into repl_status values(1,NOW());


Не забываем включить эту базу в репликацию, надо добавить в /etc/my.cnf строчку
binlog-do-db=repl_check

Перезапускаем оба mysql сервера.

Подаем признаки жизни

На каждом сервере свой конфиг, и уникальный server_id. Изначально я попробовал использовать глобальный @@server_id, который определен в my.cnf для репликации, но бинарный лог передает команду полностью, и каждый сервер выполняет его для разного server_id, (Тоесть первый обновляет строчку, где server_id=1, а второй там где server_id=2), и я решил не мучаться, а просто вписывать уникальные server_id для каждого сервера.
max_seconds_diff это максимальная разница, до которой сервер считает что все нормально. В принципе там может быть быть маленькое значение, но я решил не впадать в фанатизм. Если будет реальная проблема, узнаю через 3 минуты в любом случае.

config.php
<?php
$username="root";
$password="";
$dbname="repl_check";
$server_id=1;
$max_seconds_diff = 130;
?>


repl_update.php
<?php
include('config.php');

$sql_conn = mysql_connect("localhost",$username,$password);
if ($sql_conn == NULL)
die("failed connecting");
mysql_select_db($dbname);

$sql_query = "update repl_status set server_time=NOW() where s_id like " . intval($server_id);
mysql_query($sql_query,$sql_conn);

mysql_close($sql_conn);
?>


Добавляем его в крон. Теперь кажду минуту оба сервера будут обновлять базу, каждый строчку с своим server_id
crontab -e
* * * * * php /home/myuser/scripts/check_repl/repl_update.php

Все, табличка обновляется каждую минуту.

Распознаем признаки жизни.

check_repl.php
<?php
include('config.php');

$sql_conn = mysql_connect("localhost",$username,$password);
if ($sql_conn == NULL)
die("failed connecting");
mysql_select_db($dbname);

$time_result = mysql_query("select time_to_sec(timediff(NOW(), max(server_time))) as serv_time_diff from repl_status where s_id != " . intval($server_id));
$result_row = mysql_fetch_array($time_result, MYSQL_ASSOC);
$seconds_diff = intval($result_row["serv_time_diff"]);

mysql_free_result($time_result);
mysql_close($sql_conn);

if ($seconds_diff > $max_seconds_diff)
print "0"; //bad
else
print "1"; //good!
?>


Для удобства я еще добавил рядом скрипт:

check_repl.sh
#!/bin/sh
php /home/myuser/scripts/check_repl/check_repl.php


Для проверки, на одном из серверов надо запустить «slave stop», подождать 2-3 минуты и запустить check_repl.sh. В этом случае мы должны получить 0. Если запустить «slave start», через минуту статус уже должен выровняться.

Заббикс

Вот эту строчку надо добавить в /etc/zabbix/zabbix_agentd.conf (или где лежит конфиг)
UserParameter=mysql_repl.check,/home/myuser/scripts/check_repl/check_repl.sh

Это значит, что если заббикс (или zabbix_get) запросят item с ключем mysql_repl.check, то запустится наш скрипт и мы получим его значение (0 или 1)

После этого надо перезапустить агентд заббикса и можно добавлять item и trigger в заббикс. В Item, в поле Show value надо выставить Service state (в этом случае 0 это down, 1 up)
mysql_repl.check
И триггер на него: {MyHost:mysql_repl.check.last(0)}<1

Не забывайте, что item и trigger надо добавить на оба хоста. Где слетит репликация — там и зажжется триггер.

Все.
Желаю высокой доступности вашим mysql серверам.
Tags:
Hubs:
+15
Comments 4
Comments Comments 4

Articles