Удаление части данных истории и динамики изменений из системы мониторинга Zabbix

Иногда в результате ошибки конфигурирования шаблона или ошибки конфигурирования оборудования, в данные системы мониторинга попадает масса ложной информации. Возможна ситуация, когда в период времени от А до Б информация верная, от Б до В – ложная, от В до Г верная. Эта статья ответит на вопрос, как удалить информацию на участке от Б до В, не затронув прочие данные.

Подготовка запросов MySQL.

Если ваш мониторинг осуществляется через zabbix proxy, а сервер выступает в роли коллектора данных, то вам несказанно повезло. Вы безболезненно можете остановить zabbix server, сделать резервную копию базы данных, провести удаление данных и после его запуска сервера получить всю информацию за время проведения работ. Таким образом, вы сможете работать в большей безопасности. Однако пока вы проводите свои работы, вам не будут приходить уведомления о событиях в наблюдаемых объектах, что может быть критично для некоторых компаний. В любом случае, вам стоит подумать над шагами к возворату системы в состояния до вносимых изменений. Я делаю резервное копирование базы данных Zabbix перед любыми подобными работами, работы провожу при выключенном сервере. Для резервного копирования используя следующий скрипт:

# mysqlbackup.sh
# nano /etc/cron.d/mysqlbackup.sh
# chmod it to 0744
USER="user"
PASSWORD="password"
OUTPUTDIR="/usr/src"
MYSQLDUMP="$(which mysqldump)"
MYSQL="$(which mysql)"
KEEPTIME="60"
# Comment for backup all databases in system or list all databases for backup. Seperator: space.
DATABASES="dbname"
# Uncomment for backup all databases in system
# DATABASES=`$MYSQL --user=$USER --password=$PASSWORD -e "SHOW DATABASES;" | tr -d "| " | grep -v Database`
find $OUTPUTDIR -mtime +$KEEPTIME -type f -delete
for DB in $DATABASES; do
    echo $DB
    mkdir -p $OUTPUTDIR/$DB
    $MYSQLDUMP --force --opt --user=$USER --password=$PASSWORD --databases $DB | gzip > "$OUTPUTDIR/$DB/$DB-`date +%d_%m_%y`.gz"
done

Подсвечены строки, требующие внесения ваших параметров!

Пока идёт резервное копирование — займёмся определением исходных данных. Нужно выяснить какие данные нужно удалить и где они находятся. Поможет нам в этом веб интерфейс системы. Веб интерфейс работает независимо от сервера заббикс, поэтому с доступом проблем быть не должно, однако возможно долгое выполнение запросов к интерфейсу в связи с загруженностью базы данных.

Чаще всего ошибки в данных обнаруживаются в двух случаях: неправильно срабатывают триггеры или графики показывают неактуальную информацию. В моём случае имела место вторая ситуация. Мои графики загрузки сетевых интерфейсов выглядели совсем неправдоподобно, и я знал, что 13 сентября были проведены изменения в шаблон:

При ошибке в данных график теряет всякий смысл

Кроме информации по сетевым интерфейсам ошибочной была признана информация и по большинству других параметров данных устройств. Решено было удалить всю информацию по конкретным устройствам за последние две недели. Для этого нам нужно узнать id хостов, чтобы на их базе получить id параметров для удаления. Сделать это можно просто посмотрев на ссылку в веб интерфейсе zabbix. Например, при просмотре графиков:

Красным выделен номер хоста

В моём случае хосты имеют номера 10276, 10245, 10089. На базе данной информации я получаю список всех наблюдаемых параметров прямо из базы данных. Для этого используется следующий sql запрос:

SELECT itemid FROM `zabbix`.`items` WHERE `hostid` = '10276' OR `hostid` = '10245' OR `hostid` = '10089' LIMIT 0, 100000;

Следующий необходимый кусок мозаики — временной промежуток, который нужно удалить. Даты и время в базе данных zabbix хранятся в unixtime формате. Поэтому нам нужно конвертировать начальное и конечное время в этот формат. Моя начальная дата — 14 сентября 2014 года 6 часов вечера, в unixtime формате это 1410703200. Конечная дата — 24 сентября 2014 года 12 часов дня вечера, в unixtime формате это 1411545600. При переводе времени между форматами не забывайте про часовые пояса, это самая частая ошибка. Перевод между часовыми часами вы должны делать до написания запроса, т.е. в уме. Unixtime – часовой пояс GMT. Перевод между форматами можно делать прямо в SQL запросе.

Определив промежуток времени, нам нужно выяснить тип удаляемых данных. От этого зависит внутренняя таблица базы данных zabbix, в которой нужно производить манипуляции. Либо можно пройтись запросами по всем таблицам без разбора. Я предпочитаю второй метод. Он не оставляет никаких следов за указанный период.

В заббикс за хранения исторических данных отвечают следующие таблицы:

  • history – числовые данные с плавающей запятой;
  • history_uint – целые числа;
  • history_str – строковые данные до 255 символов;
  • history_log – данные типа логов;
  • history_text – текстовые данные.

В исторические таблицы записываются непосредственно снимаемые данные. Срок их хранения устанавливается в шаблонах отдельным параметром. Долгое хранение данных в этих таблицах не имеет смысла, так как графики с детализацией более 1 недели строятся по трендам и этот параметр жёстко записан в коде zabbix. По объёму данных исторические таблицы обычно одни из самых объёмных во всех установках систем мониторинга zabbix.

За хранения трендов отвечает всего две таблицы:

  • trends – числовые данные с плавающей запятой;
  • trends_uint – целые числа;

Тренды являются встроенным механизмом обработки данных истории, где для каждого часа хранятся значения минимума, максимума и усредненное значение, а также общее количество значений за этот час. Поэтому таблицы трендов занимают значительно меньше места в системе хранения. Тренды на русском – динамика изменений, да простит меня русский язык за кальку.

Проверка запросов MySQL и выполнение удаления.

Итак, осталось запустить запрос и проверить правильность его написания в вашем случае. Запрос на просмотр удаляемых данных будет выглядеть так:

# Для таблицы history:
SELECT * FROM `zabbix`.`history` WHERE `clock` > (UNIX_TIMESTAMP("2014-09-14 14:00:00")) AND `clock` < (UNIX_TIMESTAMP("2014-09-24 08:00:00")) AND `itemid` IN (SELECT itemid FROM `zabbix`.`items` WHERE `hostid` = '10276' OR `hostid` = '10245' OR `hostid` = '10089') LIMIT 0, 1000;
# Для таблицы history_uint:
SELECT * FROM `zabbix`.`history_uint` WHERE `clock` > (UNIX_TIMESTAMP("2014-09-14 14:00:00")) AND `clock` < (UNIX_TIMESTAMP("2014-09-24 08:00:00")) AND `itemid` IN (SELECT itemid FROM `zabbix`.`items` WHERE `hostid` = '10276' OR `hostid` = '10245' OR `hostid` = '10089') LIMIT 0, 1000;
# Для таблицы history_str:
SELECT * FROM `zabbix`.`history_str` WHERE `clock` > (UNIX_TIMESTAMP("2014-09-14 14:00:00")) AND `clock` < (UNIX_TIMESTAMP("2014-09-24 08:00:00")) AND `itemid` IN (SELECT itemid FROM `zabbix`.`items` WHERE `hostid` = '10276' OR `hostid` = '10245' OR `hostid` = '10089') LIMIT 0, 1000;
# Для таблицы history_log:
SELECT * FROM `zabbix`.`history_log` WHERE `clock` > (UNIX_TIMESTAMP("2014-09-14 14:00:00")) AND `clock` < (UNIX_TIMESTAMP("2014-09-24 08:00:00")) AND `itemid` IN (SELECT itemid FROM `zabbix`.`items` WHERE `hostid` = '10276' OR `hostid` = '10245' OR `hostid` = '10089') LIMIT 0, 1000;
# Для таблицы history_text:
SELECT * FROM `zabbix`.`history_text` WHERE `clock` > (UNIX_TIMESTAMP("2014-09-14 14:00:00")) AND `clock` < (UNIX_TIMESTAMP("2014-09-24 08:00:00")) AND `itemid` IN (SELECT itemid FROM `zabbix`.`items` WHERE `hostid` = '10276' OR `hostid` = '10245' OR `hostid` = '10089') LIMIT 0, 1000;
# Для таблицы trends:
SELECT * FROM `zabbix`.`trends` WHERE `clock` > (UNIX_TIMESTAMP("2014-09-14 14:00:00")) AND `clock` < (UNIX_TIMESTAMP("2014-09-24 08:00:00")) AND `itemid` IN (SELECT itemid FROM `zabbix`.`items` WHERE `hostid` = '10276' OR `hostid` = '10245' OR `hostid` = '10089') LIMIT 0, 1000;
# Для таблицы trends_uint:
SELECT * FROM `zabbix`.`trends_uint` WHERE `clock` > (UNIX_TIMESTAMP("2014-09-14 14:00:00")) AND `clock` < (UNIX_TIMESTAMP("2014-09-24 08:00:00")) AND `itemid` IN (SELECT itemid FROM `zabbix`.`items` WHERE `hostid` = '10276' OR `hostid` = '10245' OR `hostid` = '10089') LIMIT 0, 1000;
#Общий вид запроса:
SELECT * FROM `имя бд`.`имя таблицы` WHERE `clock` > (UNIX_TIMESTAMP(" время от ")) AND `clock` < (UNIX_TIMESTAMP(" время до ")) AND `itemid` IN (SELECT itemid FROM `имя бд`.`items` WHERE `hostid` = 'номер хоста') LIMIT 0, 1000;

Запрос должен вернуть список объектов, соответствующих заданным условиям. В конце строки запроса стоит фраза «LIMIT 0, 1000», которая лимитирует количество строк в ответе. Для понимания правильности достаточно 1000 строк. Если же сделать запрос безграничным, то это может вызвать значительную нагрузку на сервер баз данных. Здесь важно учитывать, остаётся он или нет рабочим в момент проведения манипуляций.

Если ответ на запрос получен, значит всё сделано верно. Осталось изменить тип запроса на запрос удаления. Удалять мы будем через команду DELETE.

# Для таблицы history:
DELETE FROM `zabbix`.`history` WHERE `clock` > (UNIX_TIMESTAMP("2014-09-14 14:00:00")) AND `clock` < (UNIX_TIMESTAMP("2014-09-24 08:00:00")) AND `itemid` IN (SELECT itemid FROM `zabbix`.`items` WHERE `hostid` = '10276' OR `hostid` = '10245' OR `hostid` = '10089') LIMIT 1000;
# Для таблицы history_uint:
DELETE FROM `zabbix`.`history_uint` WHERE `clock` > (UNIX_TIMESTAMP("2014-09-14 14:00:00")) AND `clock` < (UNIX_TIMESTAMP("2014-09-24 08:00:00")) AND `itemid` IN (SELECT itemid FROM `zabbix`.`items` WHERE `hostid` = '10276' OR `hostid` = '10245' OR `hostid` = '10089') LIMIT 1000;
# Для таблицы history_str:
DELETE FROM `zabbix`.`history_str` WHERE `clock` > (UNIX_TIMESTAMP("2014-09-14 14:00:00")) AND `clock` < (UNIX_TIMESTAMP("2014-09-24 08:00:00")) AND `itemid` IN (SELECT itemid FROM `zabbix`.`items` WHERE `hostid` = '10276' OR `hostid` = '10245' OR `hostid` = '10089') LIMIT 1000;
# Для таблицы history_log:
DELETE FROM `zabbix`.`history_log` WHERE `clock` > (UNIX_TIMESTAMP("2014-09-14 14:00:00")) AND `clock` < (UNIX_TIMESTAMP("2014-09-24 08:00:00")) AND `itemid` IN (SELECT itemid FROM `zabbix`.`items` WHERE `hostid` = '10276' OR `hostid` = '10245' OR `hostid` = '10089') LIMIT 1000;
# Для таблицы history_text:
DELETE FROM `zabbix`.`history_text` WHERE `clock` > (UNIX_TIMESTAMP("2014-09-14 14:00:00")) AND `clock` < (UNIX_TIMESTAMP("2014-09-24 08:00:00")) AND `itemid` IN (SELECT itemid FROM `zabbix`.`items` WHERE `hostid` = '10276' OR `hostid` = '10245' OR `hostid` = '10089') LIMIT 1000;
# Для таблицы trends:
DELETE FROM `zabbix`.`trends` WHERE `clock` > (UNIX_TIMESTAMP("2014-09-14 14:00:00")) AND `clock` < (UNIX_TIMESTAMP("2014-09-24 08:00:00")) AND `itemid` IN (SELECT itemid FROM `zabbix`.`items` WHERE `hostid` = '10276' OR `hostid` = '10245' OR `hostid` = '10089') LIMIT 1000;
# Для таблицы trends_uint:
DELETE FROM `zabbix`.`trends_uint` WHERE `clock` > (UNIX_TIMESTAMP("2014-09-14 14:00:00")) AND `clock` < (UNIX_TIMESTAMP("2014-09-24 08:00:00")) AND `itemid` IN (SELECT itemid FROM `zabbix`.`items` WHERE `hostid` = '10276' OR `hostid` = '10245' OR `hostid` = '10089') LIMIT 1000;
#Общий вид запроса:
DELETE FROM `имя бд`.`имя таблицы` WHERE `clock` > (UNIX_TIMESTAMP(" время от ")) AND `clock` < (UNIX_TIMESTAMP(" время до ")) AND `itemid` IN (SELECT itemid FROM `имя бд`.`items` WHERE `hostid` = 'номер хоста') LIMIT 1000;

Приведённые запросы тоже имеют лимит количества строк на выполнение. Это сделано, чтобы вы могли оценить загрузку вашего сервера баз данных и системы хранения в момент выполнения команды. Команда DELETE работает очень медленно и ресурсоёмко. В зависимости от участка удаляемых данных выполнение данной команды может занять несколько часов, в экстремальных, не лимитированных случаях – несколько дней.

Заключение.

Я думаю, что данную задачу можно оптимизировать на участке синтаксиса SQL запроса, однако алгоритм выполнения задачи будет соответствовать указанному в статье. Я с радостью отвечу на ваши вопросы или критику в комментариях к статье. Результат наших монипуляций виден в правильном графике:

Результат удаления данных из таблице на графике

На большом графике провал есть, но в целом график более информативен:

График zabbix с большими данными

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *