Партиция базы данных Заббикса.
Если Заббикс начинает: тормозить, выпадать в ошибки, ему не хватает памяти, слишком долго работает хаусскипер housekeeper (дом работница))) очистка базы данных истории. Нужно что то делать наращивать мощность железа ставить более производительный жесткий диск.
Либо попробовать сделать Партицию базы данных.
Секционирование (англ. partitioning) — разделение хранимых объектов баз данных
(таких как таблиц, индексов, материализованных представлений)
на отдельные части с раздельными параметрами физического хранения
Подготовка проверка настройка mysql
Резервное копирование и дамп таблиц
Разбивка партицирование вручную для текущей уже истории
Загрузка истории из дампа уже в партицированые таблицы
Выбор способа дальнейшего автоматического партицирования и удаление истории
1 способ создание таблицы manage_partitions в mysql zabbixdb по ней будут работать процедуры и событие, создание 5 процедур и 1 событие в mysql
2 Способ скрипт на perl добавленный в cron
Проверены оба способа на версии Zabbix 4.2.1
Ниже будем работать со следующим таблицами (количество таблиц и как часто будут создаваться и хранится файлы можете задать на свое усмотрение)
файл на каждый 1 день (8 таблиц) (срок хранения истории 90 дней)
history
history_text
history_uint
history_log
history_str
trends_uint
trends
events
файл на каждый 1 месяц (4 таблицы) (срок хранения истории 90 дней)
service_alarms
acknowledges
alerts
auditlog
Выше версии 2.2 указываю что следующие таблицы можно не разбивать я все же их разбил
Показать
events
service_alarms
acknowledges
alerts
auditlog
Если эти таблицы занимают у вас не много места и вы их не будете трогать, вам ненужно выполнять пункт
изменить первичный ключ на индекс и удалить зависимости идущих от других таблиц на таблицы которые нам нужно разбить, иначе выйдет ошибка и не даст нам произвести очистку и разбитие таблиц на партацию!!!
И другие команды связанные с данными таблицами!!!
service_alarms
acknowledges
alerts
auditlog
Если эти таблицы занимают у вас не много места и вы их не будете трогать, вам ненужно выполнять пункт
изменить первичный ключ на индекс и удалить зависимости идущих от других таблиц на таблицы которые нам нужно разбить, иначе выйдет ошибка и не даст нам произвести очистку и разбитие таблиц на партацию!!!
И другие команды связанные с данными таблицами!!!
Как работает стандартная очистка housekeeper
Показать
Например у нас мониторится пинг каждые 30 секунд, значит каждые 30 секунд будет сохранятся значение в базу данных в историю. И так с каждого элемента данных, а таких элементов может быть не одна тысяча и время запроса разное очень критичные каждую секунду какие то раз в 30 минут и тп. Данные хранятся в виде количества секунд, прошедших с начала «эпохи Юникса». Диапазон значений: 1970-01-01 00:00:00 Есть конвектор онлайн из секунд в дату или онлайн из секунд в дату 2. А теперь представим Очистка истории ищет в таблицах устаревшее время и удалят старые данные за уже не нужный период времени истории в этот же момент пишется куча новых данных в эти же таблицы. Очистка работает медленно. если железо слабое то может длится не один день и просто не успевать чистить старое с появлением нового.
Все базы и таблицы хранятся в одном файле /var/lib/mysql/ibdata1
Просмотреть размер можно командами
cd /var/lib/mysql/
ls -l --block-size=G
После очистки таблиц файл ibdata1 не уменьшается в размерах а просто освобождается внутри для новых данных!
В файле конфигурации Заббикс сервера nano /usr/local/etc/zabbix_server.conf есть 2 параметра отвечающие за очистку таблиц истории в базе данных.
Например у меня было так
HousekeepingFrequency=24 (запуск каждые 24 часа)
MaxHousekeeperDelete=0 (без ограничение на удаление)
Опция: HousekeepingFrequency
Как часто Zabbix будет выполнять очистку (в часах) устаревшую информацию из базы данных.
Чтобы предотвратить перегрузку Housekeeper, не более 4 раз часов устаревшей информации удаляются за один цикл обслуживания для каждого элемента. Для снижения нагрузки на запуск сервера очистка откладывается на 30 минут после запуска сервера.
При HousekeepingFrequency = 0 может быть выполнена только с использованием параметра управления во время выполнения (т е запуск вручную командой или из крона).
В этом случае период устаревшей информации, удаленной за один цикл обслуживания, в 4 раза период с последнего цикла ведения очистки, но не менее 4 часов и не более 4 дней.
Обязательно: нет
Диапазон: 0-24
HousekeepingFrequency = 24
Опция: MaxHousekeeperDelete
Таблица «Очистка» содержит «задания» в формате:
[housekeeper id], [Имя таблицы], [поле], [значение].
Не более чем строки 'MaxHousekeeperDelete' (соответствует [Имя таблицы], [поле], [значение])
будет удалено за одну задачу за один цикл обслуживания.
Если установлено значение 0, то ограничение не используется вообще. В этом случае вы должны знать, что вы делаете!
Обязательно: нет
Диапазон: 0-1000000
По умолчанию:
# MaxHousekeeperDelete = 5000
MaxHousekeeperDelete = 0
Все базы и таблицы хранятся в одном файле /var/lib/mysql/ibdata1
Просмотреть размер можно командами
cd /var/lib/mysql/
ls -l --block-size=G
После очистки таблиц файл ibdata1 не уменьшается в размерах а просто освобождается внутри для новых данных!
В файле конфигурации Заббикс сервера nano /usr/local/etc/zabbix_server.conf есть 2 параметра отвечающие за очистку таблиц истории в базе данных.
Например у меня было так
HousekeepingFrequency=24 (запуск каждые 24 часа)
MaxHousekeeperDelete=0 (без ограничение на удаление)
Опция: HousekeepingFrequency
Как часто Zabbix будет выполнять очистку (в часах) устаревшую информацию из базы данных.
Чтобы предотвратить перегрузку Housekeeper, не более 4 раз часов устаревшей информации удаляются за один цикл обслуживания для каждого элемента. Для снижения нагрузки на запуск сервера очистка откладывается на 30 минут после запуска сервера.
При HousekeepingFrequency = 0 может быть выполнена только с использованием параметра управления во время выполнения (т е запуск вручную командой или из крона).
В этом случае период устаревшей информации, удаленной за один цикл обслуживания, в 4 раза период с последнего цикла ведения очистки, но не менее 4 часов и не более 4 дней.
Обязательно: нет
Диапазон: 0-24
HousekeepingFrequency = 24
Опция: MaxHousekeeperDelete
Таблица «Очистка» содержит «задания» в формате:
[housekeeper id], [Имя таблицы], [поле], [значение].
Не более чем строки 'MaxHousekeeperDelete' (соответствует [Имя таблицы], [поле], [значение])
будет удалено за одну задачу за один цикл обслуживания.
Если установлено значение 0, то ограничение не используется вообще. В этом случае вы должны знать, что вы делаете!
Обязательно: нет
Диапазон: 0-1000000
По умолчанию:
# MaxHousekeeperDelete = 5000
MaxHousekeeperDelete = 0
Еще есть такой конфиг пример 3 версии
Показать
В src/zabbix_server/housekeeper/housekeeper.c в строке 236 определено следующее::
или Debian лежит тут /usr/local/sbin название файла zabbix_server
min_clock = MIN(now - keep_history * SEC_PER_DAY, min_clock + 4 * CONFIG_HOUSEKEEPING_FREQUENCY * SEC_PER_HOUR);
У этого есть недостаток:
если вы изменяете элемент от значения по умолчанию "храните историю в днях" 60 к,
скажем, 2, это займет очень много времени для всех старых данных, которые будут очищены.
Я предлагаю изменить это:
min_clock = MIN(now - keep_history * SEC_PER_DAY, min_clock + 32 * CONFIG_HOUSEKEEPING_FREQUENCY * SEC_PER_HOUR);
В текущем коде, если у вас есть почасовая уборка работает, он будет только удалять" в настоящее время наименьшее значение часов + 4 часа " стоит данных.
При изменении истории хранения от 60 дней до 2, это занимает очень много времени
Либо жестко закодированное значение 4 должно быть параметром config с достаточными предупреждениями о возможности табличных и транзакционных журналов,
либо значение по умолчанию должно быть немного увеличено, чтобы ускорить очистку старой истории.
или Debian лежит тут /usr/local/sbin название файла zabbix_server
min_clock = MIN(now - keep_history * SEC_PER_DAY, min_clock + 4 * CONFIG_HOUSEKEEPING_FREQUENCY * SEC_PER_HOUR);
У этого есть недостаток:
если вы изменяете элемент от значения по умолчанию "храните историю в днях" 60 к,
скажем, 2, это займет очень много времени для всех старых данных, которые будут очищены.
Я предлагаю изменить это:
min_clock = MIN(now - keep_history * SEC_PER_DAY, min_clock + 32 * CONFIG_HOUSEKEEPING_FREQUENCY * SEC_PER_HOUR);
В текущем коде, если у вас есть почасовая уборка работает, он будет только удалять" в настоящее время наименьшее значение часов + 4 часа " стоит данных.
При изменении истории хранения от 60 дней до 2, это занимает очень много времени
Либо жестко закодированное значение 4 должно быть параметром config с достаточными предупреждениями о возможности табличных и транзакционных журналов,
либо значение по умолчанию должно быть немного увеличено, чтобы ускорить очистку старой истории.
Отключим housekeeper
nano /usr/local/etc/zabbix_server.conf
Меняем параметр HousekeepingFrequency=0 (старая версия DisableHousekeeping=1)
Сохраняем F2 Y
Данный параметр задает запуск по расписанию планировщик событий например Крон или запуск вручную командой
Показать
имеется возможность отключить автоматическую очистку истории, указав HousekeepingFrequency равным 0. В этом случае процедуру очистки истории можно запустить только с помощью опции контроля управления housekeeper_execute и периодом удаления устаревшей информации является 4 кратный период начиная с последнего цикла удаления истории, но не менее чем 4 часа и не более 4 дней.
Пример использования административных функций для вызова выполнения очистки базы данных:
Ручной запуск командой shell> zabbix_server -c /usr/local/etc/zabbix_server.conf -R housekeeper_execute
или zabbix_server -R housekeeper_execute
Пример использования административных функций для вызова выполнения очистки базы данных:
Ручной запуск командой shell> zabbix_server -c /usr/local/etc/zabbix_server.conf -R housekeeper_execute
или zabbix_server -R housekeeper_execute
service zabbix-server restart
mysql -V версия MySql
На момент написания Версия Server version: 10.1.38-MariaDB-0+deb9u1 Debian 9.8
Заходим в mysql mysql -uroot -pПароль
Проверяем что Партиционирование у нас активно командой
SELECT plugin_status FROM information_schema.plugins WHERE plugin_name = 'partition';
Проверяем переменную должно быть Да
show variables like 'have_symlink';
Далее проверяем есть ли у нас BlackHole (черная дыра, данные идут «вникуда») для таблицы housekeeper он нам нужен будет.
у меня его нет по умолчанию.
SHOW ENGINES;
Если вы получили BlackHole YES то все хорошо, если этого параметра нет устанавливаем.
Устанавливается командой
INSTALL SONAME 'ha_blackhole';
Информация о blackhole
Повторно проверяем
SHOW ENGINES;
Теперь должно все появится.
Можно проверить его работу создав тестовую базу и таблицу
Показать
CREATE DATABASE testdb character set utf8 collate utf8_bin; создать базу тест
GRANT ALL PRIVILEGES on testdb.* to root@localhost IDENTIFIED BY ''; права на базу тест
use testdb выбор базы тест
CREATE TABLE test(i INT, c CHAR(10)) ENGINE = BLACKHOLE; создать таблицу
INSERT INTO test VALUES(1,'record one'), (2,'record two'); создать строки в таблице
SELECT * FROM test; выбрать все в таблице просмотр таблицы
В таблице должно быть пусто данные ушли в никуда
выходим из тестовой базы exit
GRANT ALL PRIVILEGES on testdb.* to root@localhost IDENTIFIED BY ''; права на базу тест
use testdb выбор базы тест
CREATE TABLE test(i INT, c CHAR(10)) ENGINE = BLACKHOLE; создать таблицу
INSERT INTO test VALUES(1,'record one'), (2,'record two'); создать строки в таблице
SELECT * FROM test; выбрать все в таблице просмотр таблицы
В таблице должно быть пусто данные ушли в никуда
выходим из тестовой базы exit
Выбираем базу данных Заббикса
use zabbixdb
show tables; можно просмотреть таблицы в базе
И выполняем команду
ALTER TABLE housekeeper ENGINE = BLACKHOLE;
Это нужно так как при отключенном housekeeper для элементов, Zabbix сервера и веб- интерфейсом будет продолжать писать служебную информацию для будущего использования в таблицу housekeepe. А так данные пойдут в никуда в черную дыру.
Убедитесь в том, что первый планировщик событий включен значение должно быть ON (Обычно выключен)
SHOW GLOBAL VARIABLES LIKE 'event_scheduler';
Команда включения
SET GLOBAL event_scheduler = ON;
Выходим из mysql exit
Вы также должны поместить строку в « my.cnf файл» , в раздел [mysqld] как «event_scheduler = on» в случае перезагрузки.
nano /etc/mysql/mariadb.conf.d/50-server.cnf
Дальше делаем резервную копию обязательно даже если у вас свежо установленная база и в не ничего нет!!!!
Можно скопировать всю папку mysql находится она /var/lib/mysql
Через консоль mc или командой
Изменения будут в 3х базах information_schema (performance_schema), mysql, zabbixdb
описание mysqldump
Показать
Данная утилита позволяет получить дамп (``моментальный снимок'') содержимого базы данных или совокупности баз для создания резервной копии или пересылки данных на другой SQL-сервер баз данных (не обязательно MySQL-сервер). Дамп будет содержать набор команд SQL для создания и/или заполнения таблиц.
Если данных много может занять длительное время больше суток!
Выгрузка по команде происходит в текущую директорию (папку) можно перейти в root папку набрав cd root и выполнить команды
Смотрим например от какого числа у нас начинается например таблица (история) имя таблицы history (это в дальнейшем нужно будет для создания файлов под историю от какого числа начинать)
SELECT FROM_UNIXTIME(MIN(CLOCK)) FROM `history`;
describe history; - Получение информации о столбцах кому интересно
Снимаем дамп копии Вся база Заббикс сервера и отдельно таблицы которые будем партировать.
mysqldump -u root -p zabbixdb > zabbixdb.sql
mysqldump -u root -p zabbixdb history > history.sql
mysqldump -u root -p zabbixdb history_uint > history_uint.sql
mysqldump -u root -p zabbixdb history_log > history_log.sql
mysqldump -u root -p zabbixdb history_str > history_str.sql
mysqldump -u root -p zabbixdb history_text > history_text.sql
mysqldump -u root -p zabbixdb acknowledges > acknowledges.sql
mysqldump -u root -p zabbixdb alerts > alerts.sql
mysqldump -u root -p zabbixdb auditlog > auditlog.sql
mysqldump -u root -p zabbixdb events > events.sql
mysqldump -u root -p zabbixdb trends > trends.sql
mysqldump -u root -p zabbixdb trends_uint > trends_uint.sql
mysqldump -u root -p zabbixdb service_alarms > service_alarms.sql
mysqldump -u root -p zabbixdb housekeeper > housekeeper.sql
должно получится так
Показать
Проверяем командой ls -l или смотрим в mc
В конце имени содержит букву h не перепутайте.
mysqldump -u root -p --no-create-info --lock-tables zabbixdb history > historyh.sql
mysqldump -u root -p --no-create-info --lock-tables zabbixdb history_uint > history_uinth.sql
mysqldump -u root -p --no-create-info --lock-tables zabbixdb history_log > history_logh.sql
mysqldump -u root -p --no-create-info --lock-tables zabbixdb history_str > history_strh.sql
mysqldump -u root -p --no-create-info --lock-tables zabbixdb history_text > history_texth.sql
mysqldump -u root -p --no-create-info --lock-tables zabbixdb acknowledges > acknowledgesh.sql
mysqldump -u root -p --no-create-info --lock-tables zabbixdb alerts > alertsh.sql
mysqldump -u root -p --no-create-info --lock-tables zabbixdb auditlog > auditlogh.sql
mysqldump -u root -p --no-create-info --lock-tables zabbixdb events > eventsh.sql
mysqldump -u root -p --no-create-info --lock-tables zabbixdb trends > trendsh.sql
mysqldump -u root -p --no-create-info --lock-tables zabbixdb trends_uint > trends_uinth.sql
mysqldump -u root -p --no-create-info --lock-tables zabbixdb service_alarms > service_alarmsh.sql
mysqldump -u root -p --no-create-info --lock-tables zabbixdb housekeeper > housekeeperh.sql
должно получится так
Показать
Проверяем командой ls -l или смотрим в mc
останавливаем Заббикс Сервер
service zabbix-server stop
Еще раз напоминаю если вы решили не трогать данные таблицы (events, service_alarms, acknowledges, alerts, auditlog) данный пункт выполнять не нужно! сразу переходим к пункту очистки таблицы
Заходим в mysql mysql -uroot -pПароль
mysql> use zabbixdb; выбор базы данных
Дальше нам нужно изменить первичный ключ на индекс и удалить зависимости идущих от других таблиц на таблицы которые нам нужно разбить, иначе выйдет ошибка и не даст нам произвести очистку и разбитие таблиц на партацию!!!
Водим следующие команды
ALTER TABLE `auditlog` DROP PRIMARY KEY, ADD KEY `auditlog_0` (`auditid`);
(команда удаляет ключ первичный PRIMARY и создает тоже самое но индекс auditlog_0)
ALTER TABLE `auditlog` DROP FOREIGN KEY `c_auditlog_1`;
(удаляет связь с таблицей пользователей user)
ALTER TABLE `auditlog_details` DROP FOREIGN KEY `c_auditlog_details_1`;
(удаляет связь из таблицы auditlog_details в таблицу auditlog)
Пример для таблицы auditlog скрины и команды
Показать
Просмотр в phpmyadmin
До удаления В командной строке
use zabbixdb; выбираем базу данных
Разные команды
show tables; просмотр таблиц в базе
describe auditlog; - Получение информации о столбцах
show create table auditlog; просмотр данных о таблице (так же партицирование если оно есть)
просмотреть все внешние ключи таблицы или столбца
Для таблицы:
SELECT
TABLE_NAME,COLUMN_NAME,CONSTRAINT_NAME,
REFERENCED_TABLE_NAME,REFERENCED_COLUMN_NAME
FROM
INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE
REFERENCED_TABLE_SCHEMA = 'zabbixdb' AND
REFERENCED_TABLE_NAME = 'auditlog';
Для столбца:
SELECT
TABLE_NAME,COLUMN_NAME,CONSTRAINT_NAME,
REFERENCED_TABLE_NAME,REFERENCED_COLUMN_NAME
FROM
INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE
REFERENCED_TABLE_SCHEMA = '<database>' AND
REFERENCED_COLUMN_NAME = '<column>';
Если вы используете InnoDB и определенный FK, вы можете запросить базу данных information_schema,
например:
SELECT * FROM information_schema.TABLE_CONSTRAINTS
WHERE information_schema.TABLE_CONSTRAINTS.CONSTRAINT_TYPE = 'FOREIGN KEY'
AND information_schema.TABLE_CONSTRAINTS.TABLE_SCHEMA = 'zabbixdb'
AND information_schema.TABLE_CONSTRAINTS.TABLE_NAME = 'auditlog'; еще команды
Посмотрим после выполнения команд
ALTER TABLE `auditlog` DROP PRIMARY KEY, ADD KEY `auditlog_0` (`auditid`);
(команда удаляет ключ первичный PRIMARY и создает тоже самое но индекс auditlog_0) ALTER TABLE `auditlog` DROP FOREIGN KEY `c_auditlog_1`;
(удаляет связь с таблицей пользователей user) ALTER TABLE `auditlog_details` DROP FOREIGN KEY `c_auditlog_details_1`;
(удаляет связь из таблицы auditlog_details в таблицу auditlog)
До удаления После выполнения команды удаления
До удаления В командной строке
use zabbixdb; выбираем базу данных
Разные команды
show tables; просмотр таблиц в базе
describe auditlog; - Получение информации о столбцах
show create table auditlog; просмотр данных о таблице (так же партицирование если оно есть)
просмотреть все внешние ключи таблицы или столбца
Для таблицы:
SELECT
TABLE_NAME,COLUMN_NAME,CONSTRAINT_NAME,
REFERENCED_TABLE_NAME,REFERENCED_COLUMN_NAME
FROM
INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE
REFERENCED_TABLE_SCHEMA = 'zabbixdb' AND
REFERENCED_TABLE_NAME = 'auditlog';
Для столбца:
SELECT
TABLE_NAME,COLUMN_NAME,CONSTRAINT_NAME,
REFERENCED_TABLE_NAME,REFERENCED_COLUMN_NAME
FROM
INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE
REFERENCED_TABLE_SCHEMA = '<database>' AND
REFERENCED_COLUMN_NAME = '<column>';
Если вы используете InnoDB и определенный FK, вы можете запросить базу данных information_schema,
например:
SELECT * FROM information_schema.TABLE_CONSTRAINTS
WHERE information_schema.TABLE_CONSTRAINTS.CONSTRAINT_TYPE = 'FOREIGN KEY'
AND information_schema.TABLE_CONSTRAINTS.TABLE_SCHEMA = 'zabbixdb'
AND information_schema.TABLE_CONSTRAINTS.TABLE_NAME = 'auditlog'; еще команды
Посмотрим после выполнения команд
ALTER TABLE `auditlog` DROP PRIMARY KEY, ADD KEY `auditlog_0` (`auditid`);
(команда удаляет ключ первичный PRIMARY и создает тоже самое но индекс auditlog_0) ALTER TABLE `auditlog` DROP FOREIGN KEY `c_auditlog_1`;
(удаляет связь с таблицей пользователей user) ALTER TABLE `auditlog_details` DROP FOREIGN KEY `c_auditlog_details_1`;
(удаляет связь из таблицы auditlog_details в таблицу auditlog)
До удаления После выполнения команды удаления
ALTER TABLE `service_alarms` DROP PRIMARY KEY, ADD KEY `service_alarms_0` (`servicealarmid`);
ALTER TABLE `service_alarms` DROP FOREIGN KEY `c_service_alarms_1`;
ALTER TABLE `alerts` DROP PRIMARY KEY, ADD KEY `alerts_0` (`alertid`);
ALTER TABLE `alerts` DROP FOREIGN KEY `c_alerts_1`, DROP FOREIGN KEY `c_alerts_2`, DROP FOREIGN KEY `c_alerts_3`, DROP FOREIGN KEY `c_alerts_4`, DROP FOREIGN KEY `c_alerts_5`, DROP FOREIGN KEY `c_alerts_6`;
ALTER TABLE `acknowledges` DROP PRIMARY KEY, ADD KEY `acknowledges_0` (`acknowledgeid`);
ALTER TABLE `acknowledges` DROP FOREIGN KEY `c_acknowledges_1`, DROP FOREIGN KEY `c_acknowledges_2`;
ALTER TABLE `events` DROP PRIMARY KEY, ADD KEY `events_0` (`eventid`);
ALTER TABLE `event_recovery` DROP PRIMARY KEY, ADD KEY `event_recovery_0` (`eventid`);
ALTER TABLE `event_recovery` DROP FOREIGN KEY `c_event_recovery_1`, DROP FOREIGN KEY `c_event_recovery_2`, DROP FOREIGN KEY `c_event_recovery_3`;
ALTER TABLE `event_suppress` DROP FOREIGN KEY `c_event_suppress_1`;
ALTER TABLE `event_tag` DROP FOREIGN KEY `c_event_tag_1`;
ALTER TABLE `problem` DROP FOREIGN KEY `c_problem_1`, DROP FOREIGN KEY `c_problem_2`;
Пример команд для возврата связей как было до удаления на всякий случай
Показать
Когда сделана партицирование таблиц связи на данные таблицы не восстанавливаются все работает нормально и без них, если их востановить возможно заблокируется файл и невозможно будет его удалить, или куда идут связи будут оставаться какие либо данные от удаленных уже таблиц.
ALTER TABLE `auditlog` DROP INDEX `auditlog_0`,ADD PRIMARY KEY (`auditid`);
ALTER TABLE `auditlog` ADD CONSTRAINT `c_auditlog_1` FOREIGN KEY (`userid`) REFERENCES `users`(`userid`) ON DELETE CASCADE ON UPDATE RESTRICT;
ALTER TABLE `auditlog_details` ADD CONSTRAINT `c_auditlog_details_1` FOREIGN KEY (`auditid`) REFERENCES `auditlog`(`auditid`) ON DELETE CASCADE ON UPDATE RESTRICT;
ALTER TABLE `service_alarms` DROP INDEX `service_alarms_0`,ADD PRIMARY KEY (`servicealarmid`);
ALTER TABLE `service_alarms` ADD CONSTRAINT `c_service_alarms_1` FOREIGN KEY (`serviceid`) REFERENCES `services`(`serviceid`) ON DELETE CASCADE ON UPDATE RESTRICT;
ALTER TABLE `alerts` DROP INDEX `alerts_0`,ADD PRIMARY KEY (`alertid`);
ALTER TABLE `alerts` ADD CONSTRAINT `c_alerts_1` FOREIGN KEY (`actionid`) REFERENCES `actions`(`actionid`) ON DELETE CASCADE ON UPDATE RESTRICT;
ALTER TABLE `alerts` ADD CONSTRAINT `c_alerts_2` FOREIGN KEY (`eventid`) REFERENCES `events`(`eventid`) ON DELETE CASCADE ON UPDATE RESTRICT;
ALTER TABLE `alerts` ADD CONSTRAINT `c_alerts_3` FOREIGN KEY (`userid`) REFERENCES `users`(`userid`) ON DELETE CASCADE ON UPDATE RESTRICT;
ALTER TABLE `alerts` ADD CONSTRAINT `c_alerts_4` FOREIGN KEY (`mediatypeid`) REFERENCES `media_type`(`mediatypeid`) ON DELETE CASCADE ON UPDATE RESTRICT;
ALTER TABLE `alerts` ADD CONSTRAINT `c_alerts_5` FOREIGN KEY (`p_eventid`) REFERENCES `events`(`eventid`) ON DELETE CASCADE ON UPDATE RESTRICT;
ALTER TABLE `alerts` ADD CONSTRAINT `c_alerts_6` FOREIGN KEY (`acknowledgeid`) REFERENCES `acknowledges`(`acknowledgeid`) ON DELETE CASCADE ON UPDATE RESTRICT;
ALTER TABLE `acknowledges` DROP INDEX `acknowledges_0`,ADD PRIMARY KEY (`acknowledgeid`);
ALTER TABLE `acknowledges` ADD CONSTRAINT `c_acknowledges_1` FOREIGN KEY (`userid`) REFERENCES `users`(`userid`) ON DELETE CASCADE ON UPDATE RESTRICT;
ALTER TABLE `acknowledges` ADD CONSTRAINT `c_acknowledges_2` FOREIGN KEY (`eventid`) REFERENCES `events`(`eventid`) ON DELETE CASCADE ON UPDATE RESTRICT;
ALTER TABLE `events` DROP INDEX `events_0`,ADD PRIMARY KEY (`eventid`);
ALTER TABLE `event_recovery` DROP INDEX `event_recovery_0`,ADD PRIMARY KEY (`eventid`);
ALTER TABLE `event_recovery` ADD CONSTRAINT `c_event_recovery_1` FOREIGN KEY (`eventid`) REFERENCES `events`(`eventid`) ON DELETE CASCADE ON UPDATE RESTRICT;
ALTER TABLE `event_recovery` ADD CONSTRAINT `c_event_recovery_2` FOREIGN KEY (`r_eventid`) REFERENCES `events`(`eventid`) ON DELETE CASCADE ON UPDATE RESTRICT;
ALTER TABLE `event_recovery` ADD CONSTRAINT `c_event_recovery_3` FOREIGN KEY (`c_eventid`) REFERENCES `events`(`eventid`) ON DELETE CASCADE ON UPDATE RESTRICT;
ALTER TABLE `event_suppress` ADD CONSTRAINT `c_event_suppress_1` FOREIGN KEY (`eventid`) REFERENCES `events`(`eventid`) ON DELETE CASCADE ON UPDATE RESTRICT;
ALTER TABLE `event_tag` ADD CONSTRAINT `c_event_tag_1` FOREIGN KEY (`eventid`) REFERENCES `events`(`eventid`) ON DELETE CASCADE ON UPDATE RESTRICT;
ALTER TABLE `problem` ADD CONSTRAINT `c_problem_1` FOREIGN KEY (`eventid`) REFERENCES `events`(`eventid`) ON DELETE CASCADE ON UPDATE RESTRICT;
ALTER TABLE `problem` ADD CONSTRAINT `c_problem_2` FOREIGN KEY (`r_eventid`) REFERENCES `events`(`eventid`) ON DELETE CASCADE ON UPDATE RESTRICT;
ALTER TABLE `auditlog` DROP INDEX `auditlog_0`,ADD PRIMARY KEY (`auditid`);
ALTER TABLE `auditlog` ADD CONSTRAINT `c_auditlog_1` FOREIGN KEY (`userid`) REFERENCES `users`(`userid`) ON DELETE CASCADE ON UPDATE RESTRICT;
ALTER TABLE `auditlog_details` ADD CONSTRAINT `c_auditlog_details_1` FOREIGN KEY (`auditid`) REFERENCES `auditlog`(`auditid`) ON DELETE CASCADE ON UPDATE RESTRICT;
ALTER TABLE `service_alarms` DROP INDEX `service_alarms_0`,ADD PRIMARY KEY (`servicealarmid`);
ALTER TABLE `service_alarms` ADD CONSTRAINT `c_service_alarms_1` FOREIGN KEY (`serviceid`) REFERENCES `services`(`serviceid`) ON DELETE CASCADE ON UPDATE RESTRICT;
ALTER TABLE `alerts` DROP INDEX `alerts_0`,ADD PRIMARY KEY (`alertid`);
ALTER TABLE `alerts` ADD CONSTRAINT `c_alerts_1` FOREIGN KEY (`actionid`) REFERENCES `actions`(`actionid`) ON DELETE CASCADE ON UPDATE RESTRICT;
ALTER TABLE `alerts` ADD CONSTRAINT `c_alerts_2` FOREIGN KEY (`eventid`) REFERENCES `events`(`eventid`) ON DELETE CASCADE ON UPDATE RESTRICT;
ALTER TABLE `alerts` ADD CONSTRAINT `c_alerts_3` FOREIGN KEY (`userid`) REFERENCES `users`(`userid`) ON DELETE CASCADE ON UPDATE RESTRICT;
ALTER TABLE `alerts` ADD CONSTRAINT `c_alerts_4` FOREIGN KEY (`mediatypeid`) REFERENCES `media_type`(`mediatypeid`) ON DELETE CASCADE ON UPDATE RESTRICT;
ALTER TABLE `alerts` ADD CONSTRAINT `c_alerts_5` FOREIGN KEY (`p_eventid`) REFERENCES `events`(`eventid`) ON DELETE CASCADE ON UPDATE RESTRICT;
ALTER TABLE `alerts` ADD CONSTRAINT `c_alerts_6` FOREIGN KEY (`acknowledgeid`) REFERENCES `acknowledges`(`acknowledgeid`) ON DELETE CASCADE ON UPDATE RESTRICT;
ALTER TABLE `acknowledges` DROP INDEX `acknowledges_0`,ADD PRIMARY KEY (`acknowledgeid`);
ALTER TABLE `acknowledges` ADD CONSTRAINT `c_acknowledges_1` FOREIGN KEY (`userid`) REFERENCES `users`(`userid`) ON DELETE CASCADE ON UPDATE RESTRICT;
ALTER TABLE `acknowledges` ADD CONSTRAINT `c_acknowledges_2` FOREIGN KEY (`eventid`) REFERENCES `events`(`eventid`) ON DELETE CASCADE ON UPDATE RESTRICT;
ALTER TABLE `events` DROP INDEX `events_0`,ADD PRIMARY KEY (`eventid`);
ALTER TABLE `event_recovery` DROP INDEX `event_recovery_0`,ADD PRIMARY KEY (`eventid`);
ALTER TABLE `event_recovery` ADD CONSTRAINT `c_event_recovery_1` FOREIGN KEY (`eventid`) REFERENCES `events`(`eventid`) ON DELETE CASCADE ON UPDATE RESTRICT;
ALTER TABLE `event_recovery` ADD CONSTRAINT `c_event_recovery_2` FOREIGN KEY (`r_eventid`) REFERENCES `events`(`eventid`) ON DELETE CASCADE ON UPDATE RESTRICT;
ALTER TABLE `event_recovery` ADD CONSTRAINT `c_event_recovery_3` FOREIGN KEY (`c_eventid`) REFERENCES `events`(`eventid`) ON DELETE CASCADE ON UPDATE RESTRICT;
ALTER TABLE `event_suppress` ADD CONSTRAINT `c_event_suppress_1` FOREIGN KEY (`eventid`) REFERENCES `events`(`eventid`) ON DELETE CASCADE ON UPDATE RESTRICT;
ALTER TABLE `event_tag` ADD CONSTRAINT `c_event_tag_1` FOREIGN KEY (`eventid`) REFERENCES `events`(`eventid`) ON DELETE CASCADE ON UPDATE RESTRICT;
ALTER TABLE `problem` ADD CONSTRAINT `c_problem_1` FOREIGN KEY (`eventid`) REFERENCES `events`(`eventid`) ON DELETE CASCADE ON UPDATE RESTRICT;
ALTER TABLE `problem` ADD CONSTRAINT `c_problem_2` FOREIGN KEY (`r_eventid`) REFERENCES `events`(`eventid`) ON DELETE CASCADE ON UPDATE RESTRICT;
ALTER TABLE `history_log` DROP PRIMARY KEY, ADD PRIMARY KEY (`id`,`clock`);
ALTER TABLE `history_log` DROP KEY `history_log_2`;
ALTER TABLE `history_log` ADD UNIQUE INDEX `history_log_2`(`itemid`,`id`,`clock`);
ALTER TABLE `history_text` DROP PRIMARY KEY, ADD PRIMARY KEY (`id`,`clock`);
ALTER TABLE `history_text` DROP KEY `history_text_2`;
ALTER TABLE `history_text` ADD UNIQUE INDEX `history_text_2`(`itemid`,`id`,`clock`);
ALTER TABLE `history_log` DROP PRIMARY KEY, ADD INDEX `history_log_0` (`id`);
ALTER TABLE `history_log` DROP KEY `history_log_2`;
ALTER TABLE `history_text` DROP PRIMARY KEY, ADD INDEX `history_text_0` (`id`);
ALTER TABLE `history_text` DROP KEY `history_text_2`;
Очищаем таблицы от данных.
truncate table history;
truncate table history_uint;
truncate table history_text;
truncate table history_str;
truncate table history_log;
truncate table alerts;
truncate table service_alarms;
truncate table trends;
truncate table trends_uint;
truncate table acknowledges;
truncate table auditlog;
truncate table events;
Создаем вручную нужное количество файлов (дней) для восстановления истории которую нам нужно востановить. (мы смотрели дату начала истории при создании копий таблиц)
Партация создается до указанного числа например до >2019-05-20 значит таблица будет за 19 число и имя будет P2019_05_19
Например у вас сегодня 1 число месяца у вас должен быть файл с именем pГГГГ_ММ_01 это файл будет содержать данные до ("ГГГГ-ММ-02 00:00:00") до 2 числа месяца и тд
файлы создадутся в cd /var/lib/mysql/zabbixdb
1 день таблицы
history
history_text
history_uint
history_log
history_str
trends_uint
trends
events
Повторяем команду меня название таблицы events на другие таблицы
Пример для 2019 05 20 до 2019 05 27 будет 8 файлов на 8 дней истории
ALTER TABLE `events` PARTITION BY RANGE ( clock)
(PARTITION p2019_05_20 VALUES LESS THAN (UNIX_TIMESTAMP("2019-05-21 00:00:00") div 1) ENGINE = InnoDB,
PARTITION p2019_05_21 VALUES LESS THAN (UNIX_TIMESTAMP("2019-05-22 00:00:00") div 1) ENGINE = InnoDB,
PARTITION p2019_05_22 VALUES LESS THAN (UNIX_TIMESTAMP("2019-05-23 00:00:00") div 1) ENGINE = InnoDB,
PARTITION p2019_05_23 VALUES LESS THAN (UNIX_TIMESTAMP("2019-05-24 00:00:00") div 1) ENGINE = InnoDB,
PARTITION p2019_05_24 VALUES LESS THAN (UNIX_TIMESTAMP("2019-05-25 00:00:00") div 1) ENGINE = InnoDB,
PARTITION p2019_05_25 VALUES LESS THAN (UNIX_TIMESTAMP("2019-05-26 00:00:00") div 1) ENGINE = InnoDB,
PARTITION p2019_05_26 VALUES LESS THAN (UNIX_TIMESTAMP("2019-05-27 00:00:00") div 1) ENGINE = InnoDB,
PARTITION p2019_05_27 VALUES LESS THAN (UNIX_TIMESTAMP("2019-05-28 00:00:00") div 1) ENGINE = InnoDB);
месяц
service_alarms
acknowledges
alerts
auditlog
создаем по 2 файла истории за 2 месяца за май и июнь
Повторяем команду меня название таблицы service_alarms
ALTER TABLE `service_alarms` PARTITION BY RANGE ( clock)
(PARTITION p2019_05_01 VALUES LESS THAN (UNIX_TIMESTAMP("2019-06-01 00:00:00") div 1) ENGINE = InnoDB,
PARTITION p2019_06_01 VALUES LESS THAN (UNIX_TIMESTAMP("2019-07-01 00:00:00") div 1) ENGINE = InnoDB);
ALTER TABLE `acknowledges` PARTITION BY RANGE ( clock)
(PARTITION p2019_05_01 VALUES LESS THAN (UNIX_TIMESTAMP("2019-06-01 00:00:00") div 1) ENGINE = InnoDB,
PARTITION p2019_06_01 VALUES LESS THAN (UNIX_TIMESTAMP("2019-07-01 00:00:00") div 1) ENGINE = InnoDB);
ALTER TABLE `alerts` PARTITION BY RANGE ( clock)
(PARTITION p2019_05_01 VALUES LESS THAN (UNIX_TIMESTAMP("2019-06-01 00:00:00") div 1) ENGINE = InnoDB,
PARTITION p2019_06_01 VALUES LESS THAN (UNIX_TIMESTAMP("2019-07-01 00:00:00") div 1) ENGINE = InnoDB);
ALTER TABLE `auditlog` PARTITION BY RANGE ( clock)
(PARTITION p2019_05_01 VALUES LESS THAN (UNIX_TIMESTAMP("2019-06-01 00:00:00") div 1) ENGINE = InnoDB,
PARTITION p2019_06_01 VALUES LESS THAN (UNIX_TIMESTAMP("2019-07-01 00:00:00") div 1) ENGINE = InnoDB);
Пример ввода команд)
Показать
Они так же должны присутствовать пример в mc Удалить не правильно созданные пример
ALTER TABLE `history_log` DROP PARTITION p2019_05_20;
show create table history; Проверить просмотр данных о таблице так же партицирование создалось или нет пример таблица history
Показать
Восстанавливаем данные, в партиционированные таблицы которая без функции create в конце есть буква h не перепутайте
mysql -u root -p zabbixdb < historyh.sql
mysql -u root -p zabbixdb < history_uinth.sql
mysql -u root -p zabbixdb < history_texth.sql
mysql -u root -p zabbixdb < history_logh.sql
mysql -u root -p zabbixdb < history_strh.sql
mysql -u root -p zabbixdb < acknowledgesh.sql
mysql -u root -p zabbixdb < alertsh.sql
mysql -u root -p zabbixdb < auditlogh.sql
mysql -u root -p zabbixdb < eventsh.sql
mysql -u root -p zabbixdb < service_alarmsh.sql
mysql -u root -p zabbixdb < trendsh.sql
mysql -u root -p zabbixdb < trends_uinth.sql
Выглядит это так Если у вас вылетела ошибка с параметром clock значит у вас не хватает файлов с партацией данного времени, некуда записывать данные от определенного времени.
Далее у нас есть 2 варианта создания новых файлов партицирования и их удаления. Первый это из MySql , Второй скриптом добавленного (в планировщик заданий) Cron. Выбирайте на свой вкус. У меня сделано первым способом.
Первый способ!
Создаем таблицу manage_partitions в базе данных zabbixdb настроек секционирования. В этой таблице будут хранится настройки секционирования для таблиц Zabbix.
Заходим в mysql mysql -uroot -pПароль
mysql> use zabbixdb; выбор базы данных
Создание таблицы
CREATE TABLE `manage_partitions` (
`tablename` VARCHAR(64) NOT NULL COMMENT 'Имя секционируемой таблицы',
`period` VARCHAR(64) NOT NULL COMMENT 'Период секционирования: day week month',
`keep_history` INT(3) UNSIGNED NOT NULL DEFAULT '1' COMMENT 'Количество дней недель месяцев хранения секций',
`last_updated` DATETIME DEFAULT NULL COMMENT 'Время последнего добавления секции',
`comments` VARCHAR(128) DEFAULT '1' COMMENT 'Комментарии',
PRIMARY KEY (`tablename`)
) ENGINE=INNODB;
Просмотреть можно командой SHOW CREATE TABLE `manage_partitions`;
Должно быть так
обозначение периода времени
Показать
day День
week Неделю
month Месяц
year Год
Неделя ( 00.. 53), где 53 это количество недель в году
12.7 Функции даты и времени
Создавать файл
каждый 1 день хранить 90 дней
history
history_text
history_uint
каждую неделю хранить 12 недель
history_log
history_str
trends_uint
trends
events
каждые месяц хранить 3 месяца
service_alarms
acknowledges
alerts
auditlog
day День
week Неделю
month Месяц
year Год
INSERT INTO manage_partitions (tablename, period, keep_history, last_updated, comments) VALUES ('history', 'day', 90, now(), '');
INSERT INTO manage_partitions (tablename, period, keep_history, last_updated, comments) VALUES ('history_text', 'day', 90, now(), '');
INSERT INTO manage_partitions (tablename, period, keep_history, last_updated, comments) VALUES ('history_uint', 'day', 90, now(), '');
INSERT INTO manage_partitions (tablename, period, keep_history, last_updated, comments) VALUES ('history_log', 'week', 12, now(), '');
INSERT INTO manage_partitions (tablename, period, keep_history, last_updated, comments) VALUES ('history_str', 'week', 12, now(), '');
INSERT INTO manage_partitions (tablename, period, keep_history, last_updated, comments) VALUES ('trends_uint', 'week', 12, now(), '');
INSERT INTO manage_partitions (tablename, period, keep_history, last_updated, comments) VALUES ('trends', 'week', 12, now(), '');
INSERT INTO manage_partitions (tablename, period, keep_history, last_updated, comments) VALUES ('events', 'week', 12, now(), '');
INSERT INTO manage_partitions (tablename, period, keep_history, last_updated, comments) VALUES ('service_alarms', 'month', 3, now(), '');
INSERT INTO manage_partitions (tablename, period, keep_history, last_updated, comments) VALUES ('acknowledges', 'month', 3, now(), '');
INSERT INTO manage_partitions (tablename, period, keep_history, last_updated, comments) VALUES ('alerts', 'month', 3, now(), '');
INSERT INTO manage_partitions (tablename, period, keep_history, last_updated, comments) VALUES ('auditlog', 'month', 3, now(), '');
week Неделю
month Месяц
year Год
Неделя ( 00.. 53), где 53 это количество недель в году
12.7 Функции даты и времени
С Проба сделать с неделями некоторые таблицы чтоб не было так много файлов
Показать
Создавать файл
каждый 1 день хранить 90 дней
history
history_text
history_uint
каждую неделю хранить 12 недель
history_log
history_str
trends_uint
trends
events
каждые месяц хранить 3 месяца
service_alarms
acknowledges
alerts
auditlog
day День
week Неделю
month Месяц
year Год
INSERT INTO manage_partitions (tablename, period, keep_history, last_updated, comments) VALUES ('history', 'day', 90, now(), '');
INSERT INTO manage_partitions (tablename, period, keep_history, last_updated, comments) VALUES ('history_text', 'day', 90, now(), '');
INSERT INTO manage_partitions (tablename, period, keep_history, last_updated, comments) VALUES ('history_uint', 'day', 90, now(), '');
INSERT INTO manage_partitions (tablename, period, keep_history, last_updated, comments) VALUES ('history_log', 'week', 12, now(), '');
INSERT INTO manage_partitions (tablename, period, keep_history, last_updated, comments) VALUES ('history_str', 'week', 12, now(), '');
INSERT INTO manage_partitions (tablename, period, keep_history, last_updated, comments) VALUES ('trends_uint', 'week', 12, now(), '');
INSERT INTO manage_partitions (tablename, period, keep_history, last_updated, comments) VALUES ('trends', 'week', 12, now(), '');
INSERT INTO manage_partitions (tablename, period, keep_history, last_updated, comments) VALUES ('events', 'week', 12, now(), '');
INSERT INTO manage_partitions (tablename, period, keep_history, last_updated, comments) VALUES ('service_alarms', 'month', 3, now(), '');
INSERT INTO manage_partitions (tablename, period, keep_history, last_updated, comments) VALUES ('acknowledges', 'month', 3, now(), '');
INSERT INTO manage_partitions (tablename, period, keep_history, last_updated, comments) VALUES ('alerts', 'month', 3, now(), '');
INSERT INTO manage_partitions (tablename, period, keep_history, last_updated, comments) VALUES ('auditlog', 'month', 3, now(), '');
где day', 90 - 90 дней , month', 3,- 3 месяца. Здесь именно указать месяц или дни в дальнейшем по этим параметрам будут создаваться новый файлы таблиц а так же удаляться старые с истечением срока хранения!
INSERT INTO manage_partitions (tablename, period, keep_history, last_updated, comments) VALUES ('history', 'day', 90, now(), '');
INSERT INTO manage_partitions (tablename, period, keep_history, last_updated, comments) VALUES ('history_text', 'day', 90, now(), '');
INSERT INTO manage_partitions (tablename, period, keep_history, last_updated, comments) VALUES ('history_uint', 'day', 90, now(), '');
INSERT INTO manage_partitions (tablename, period, keep_history, last_updated, comments) VALUES ('history_log', 'week', 12, now(), '');
INSERT INTO manage_partitions (tablename, period, keep_history, last_updated, comments) VALUES ('history_str', 'week', 12, now(), '');
INSERT INTO manage_partitions (tablename, period, keep_history, last_updated, comments) VALUES ('trends_uint', 'week', 12, now(), '');
INSERT INTO manage_partitions (tablename, period, keep_history, last_updated, comments) VALUES ('trends', 'week', 12, now(), '');
INSERT INTO manage_partitions (tablename, period, keep_history, last_updated, comments) VALUES ('events', 'week', 12, now(), '');
INSERT INTO manage_partitions (tablename, period, keep_history, last_updated, comments) VALUES ('service_alarms', 'month', 3, now(), '');
INSERT INTO manage_partitions (tablename, period, keep_history, last_updated, comments) VALUES ('acknowledges', 'month', 3, now(), '');
INSERT INTO manage_partitions (tablename, period, keep_history, last_updated, comments) VALUES ('alerts', 'month', 3, now(), '');
INSERT INTO manage_partitions (tablename, period, keep_history, last_updated, comments) VALUES ('auditlog', 'month', 3, now(), '');
ИЛИ ТАК кому как удобнее
INSERT INTO manage_partitions (tablename, period, keep_history, last_updated, comments) VALUES ('history', 'day', 90, now(), '');
INSERT INTO manage_partitions (tablename, period, keep_history, last_updated, comments) VALUES ('history_log', 'day', 90, now(), '');
INSERT INTO manage_partitions (tablename, period, keep_history, last_updated, comments) VALUES ('history_str', 'day', 90, now(), '');
INSERT INTO manage_partitions (tablename, period, keep_history, last_updated, comments) VALUES ('history_text', 'day', 90, now(), '');
INSERT INTO manage_partitions (tablename, period, keep_history, last_updated, comments) VALUES ('history_uint', 'day', 90, now(), '');
INSERT INTO manage_partitions (tablename, period, keep_history, last_updated, comments) VALUES ('trends_uint', 'day', 90, now(), '');
INSERT INTO manage_partitions (tablename, period, keep_history, last_updated, comments) VALUES ('trends', 'day', 90, now(), '');
INSERT INTO manage_partitions (tablename, period, keep_history, last_updated, comments) VALUES ('events', 'day', 90, now(), '');
INSERT INTO manage_partitions (tablename, period, keep_history, last_updated, comments) VALUES ('service_alarms', ' month', 3, now(), '');
INSERT INTO manage_partitions (tablename, period, keep_history, last_updated, comments) VALUES ('acknowledges', ' month', 3, now(), '');
INSERT INTO manage_partitions (tablename, period, keep_history, last_updated, comments) VALUES ('alerts', ' month', 3, now(), '');
INSERT INTO manage_partitions (tablename, period, keep_history, last_updated, comments) VALUES ('auditlog', ' month', 3, now(), '');
Получаем
SELECT * FROM manage_partitions; Или же еще с неделями возможен вариант Создадим 5 процедур и 1 событие
Процедура проверки наличия требуемых секций
Заходим в mysql mysql -uroot -pПароль
DELIMITER $$
USE `zabbixdb`$$
DROP PROCEDURE IF EXISTS `create_next_partitions`$$
CREATE PROCEDURE `create_next_partitions`(IN_SCHEMANAME VARCHAR(64))
COMMENT 'Процедура проверки наличия требуемых секций'
BEGIN
DECLARE TABLENAME_TMP VARCHAR(64);
DECLARE PERIOD_TMP VARCHAR(12);
DECLARE DONE INT DEFAULT 0;
DECLARE get_prt_tables CURSOR FOR
SELECT `tablename`, `period`
FROM manage_partitions;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN get_prt_tables;
loop_create_part: LOOP
IF DONE THEN
LEAVE loop_create_part;
END IF;
FETCH get_prt_tables INTO TABLENAME_TMP, PERIOD_TMP;
CASE WHEN PERIOD_TMP = 'day' THEN
CALL `create_partition_by_day`(IN_SCHEMANAME, TABLENAME_TMP);
WHEN PERIOD_TMP = 'week' THEN
CALL `create_partition_by_week`(IN_SCHEMANAME, TABLENAME_TMP);
WHEN PERIOD_TMP = 'month' THEN
CALL `create_partition_by_month`(IN_SCHEMANAME, TABLENAME_TMP);
ELSE
BEGIN
ITERATE loop_create_part;
END;
END CASE;
UPDATE manage_partitions set last_updated = NOW() WHERE tablename = TABLENAME_TMP;
END LOOP loop_create_part;
CLOSE get_prt_tables;
END$$
DELIMITER ;
Создание секции по дням
mysql>
DELIMITER $$
USE `zabbixdb`$$
DROP PROCEDURE IF EXISTS `create_partition_by_day`$$
CREATE PROCEDURE `create_partition_by_day`(IN_SCHEMANAME VARCHAR(64), IN_TABLENAME VARCHAR(64))
COMMENT 'Создание секции по дням'
BEGIN
DECLARE ROWS_CNT INT UNSIGNED;
DECLARE BEGINTIME TIMESTAMP;
DECLARE ENDTIME INT UNSIGNED;
DECLARE PARTITIONNAME VARCHAR(16);
SET BEGINTIME = DATE(NOW()) + INTERVAL 1 DAY;
SET PARTITIONNAME = DATE_FORMAT( BEGINTIME, 'p%Y_%m_%d' );
SET ENDTIME = UNIX_TIMESTAMP(BEGINTIME + INTERVAL 1 DAY) div 1;
SELECT COUNT(*) INTO ROWS_CNT
FROM information_schema.partitions
WHERE table_schema = IN_SCHEMANAME AND table_name = IN_TABLENAME AND partition_name = PARTITIONNAME;
IF ROWS_CNT = 0 THEN
SET @SQL = CONCAT( 'ALTER TABLE `', IN_SCHEMANAME, '`.`', IN_TABLENAME, '`',
' ADD PARTITION (PARTITION ', PARTITIONNAME, ' VALUES LESS THAN (', ENDTIME, '));' );
PREPARE STMT FROM @SQL;
EXECUTE STMT;
DEALLOCATE PREPARE STMT;
ELSE
SELECT CONCAT("partition `", PARTITIONNAME, "` for table `",IN_SCHEMANAME, ".", IN_TABLENAME, "` already exists") AS result;
END IF;
END$$
DELIMITER ;
Создание секции по неделям
mysql>
DELIMITER $$
USE `zabbixdb`$$
DROP PROCEDURE IF EXISTS `create_partition_by_week`$$
CREATE PROCEDURE `create_partition_by_week`(IN_SCHEMANAME VARCHAR(64), IN_TABLENAME VARCHAR(64))
COMMENT 'Создание секции по неделям'
BEGIN
DECLARE ROWS_CNT INT UNSIGNED;
DECLARE BEGINTIME TIMESTAMP;
DECLARE ENDTIME INT UNSIGNED;
DECLARE PARTITIONNAME VARCHAR(16);
SET BEGINTIME = DATE(NOW()) + INTERVAL 1 WEEK;
SET PARTITIONNAME = DATE_FORMAT( BEGINTIME, 'p%Y_%m_%d_%u' );
SET ENDTIME = UNIX_TIMESTAMP(BEGINTIME + INTERVAL 1 WEEK) div 1;
SELECT COUNT(*) INTO ROWS_CNT
FROM information_schema.partitions
WHERE table_schema = IN_SCHEMANAME AND table_name = IN_TABLENAME AND partition_name = PARTITIONNAME;
IF ROWS_CNT = 0 THEN
SET @SQL = CONCAT( 'ALTER TABLE `', IN_SCHEMANAME, '`.`', IN_TABLENAME, '`',
' ADD PARTITION (PARTITION ', PARTITIONNAME, ' VALUES LESS THAN (', ENDTIME, '));' );
PREPARE STMT FROM @SQL;
EXECUTE STMT;
DEALLOCATE PREPARE STMT;
ELSE
SELECT CONCAT("partition `", PARTITIONNAME, "` for table `",IN_SCHEMANAME, ".", IN_TABLENAME, "` already exists") AS result;
END IF;
END$$
DELIMITER ;
Создание секций по месяцам
mysql>
DELIMITER $$
USE `zabbixdb`$$
DROP PROCEDURE IF EXISTS `create_partition_by_month`$$
CREATE PROCEDURE `create_partition_by_month`(IN_SCHEMANAME VARCHAR(64), IN_TABLENAME VARCHAR(64))
COMMENT 'Создание секций по месяцам'
BEGIN
DECLARE ROWS_CNT INT UNSIGNED;
DECLARE BEGINTIME TIMESTAMP;
DECLARE ENDTIME INT UNSIGNED;
DECLARE PARTITIONNAME VARCHAR(16);
SET BEGINTIME = DATE(NOW() - INTERVAL DAY(NOW()) DAY + INTERVAL 1 DAY + INTERVAL 1 MONTH);
SET PARTITIONNAME = DATE_FORMAT( BEGINTIME, 'p%Y_%m' );
SET ENDTIME = UNIX_TIMESTAMP(BEGINTIME + INTERVAL 1 MONTH) div 1;
SELECT COUNT(*) INTO ROWS_CNT
FROM information_schema.partitions
WHERE table_schema = IN_SCHEMANAME AND table_name = IN_TABLENAME AND partition_name = PARTITIONNAME;
IF ROWS_CNT = 0 THEN
SET @SQL = CONCAT( 'ALTER TABLE `', IN_SCHEMANAME, '`.`', IN_TABLENAME, '`',
' ADD PARTITION (PARTITION ', PARTITIONNAME, ' VALUES LESS THAN (', ENDTIME, '));' );
PREPARE STMT FROM @SQL;
EXECUTE STMT;
DEALLOCATE PREPARE STMT;
ELSE
SELECT CONCAT("partition `", PARTITIONNAME, "` for table `",IN_SCHEMANAME, ".", IN_TABLENAME, "` already exists") AS result;
END IF;
END$$
DELIMITER ;
Проверка наличия устаревших секций и удаление
mysql>
DELIMITER $$
USE `zabbixdb`$$
DROP PROCEDURE IF EXISTS `drop_partitions`$$
CREATE PROCEDURE `drop_partitions`(IN_SCHEMANAME VARCHAR(64))
COMMENT 'Проверка наличия устаревших секций и удаление'
BEGIN
DECLARE TABLENAME_TMP VARCHAR(64);
DECLARE PARTITIONNAME_TMP VARCHAR(64);
DECLARE VALUES_LESS_TMP INT;
DECLARE PERIOD_TMP VARCHAR(12);
DECLARE KEEP_HISTORY_TMP INT;
DECLARE KEEP_HISTORY_BEFORE INT;
DECLARE DONE INT DEFAULT 0;
DECLARE get_partitions CURSOR FOR
SELECT p.`table_name`, p.`partition_name`, LTRIM(RTRIM(p.`partition_description`)), mp.`period`, mp.`keep_history`
FROM information_schema.partitions p
JOIN manage_partitions mp ON mp.tablename = p.table_name
WHERE p.table_schema = IN_SCHEMANAME
ORDER BY p.table_name, p.subpartition_ordinal_position;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN get_partitions;
loop_check_prt: LOOP
IF DONE THEN
LEAVE loop_check_prt;
END IF;
FETCH get_partitions INTO TABLENAME_TMP, PARTITIONNAME_TMP, VALUES_LESS_TMP, PERIOD_TMP, KEEP_HISTORY_TMP;
CASE WHEN PERIOD_TMP = 'day' THEN
SET KEEP_HISTORY_BEFORE = UNIX_TIMESTAMP(DATE(NOW() - INTERVAL KEEP_HISTORY_TMP DAY));
WHEN PERIOD_TMP = 'month' THEN
SET KEEP_HISTORY_BEFORE = UNIX_TIMESTAMP(DATE(NOW() - INTERVAL KEEP_HISTORY_TMP MONTH - INTERVAL DAY(NOW())-1 DAY));
ELSE
BEGIN
ITERATE loop_check_prt;
END;
END CASE;
IF KEEP_HISTORY_BEFORE >= VALUES_LESS_TMP THEN
CALL drop_old_partition(IN_SCHEMANAME, TABLENAME_TMP, PARTITIONNAME_TMP);
END IF;
END LOOP loop_check_prt;
CLOSE get_partitions;
END$$
DELIMITER ;
Ниже под сполером ошибочный скрипт подписчик поправил Процедура не создалась из-за ошибки в синтаксисе.
Кто делал так и была ошибка выше выложен уже без ошибки в чем была ошибка под сполером
Ошибка
Показать
Отличие скриптов моего и подписчика, у меня были доп строки откуда они взялись.... возможно скопировались с чем то...
на 3 команды больше
FETCH get_partitions INTO TABLENAME_TMP, PARTITIONNAME_TMP, VALUES_LESS_TMP, PERIOD_TMP, KEEP_HISTORY_TMP;
CASE WHEN PERIOD_TMP = 'week' THEN
SET KEEP_HISTORY_BEFORE = UNIX_TIMESTAMP(DATE(NOW() - INTERVAL KEEP_HISTORY_TMP WEEK));
на 3 команды больше
FETCH get_partitions INTO TABLENAME_TMP, PARTITIONNAME_TMP, VALUES_LESS_TMP, PERIOD_TMP, KEEP_HISTORY_TMP;
CASE WHEN PERIOD_TMP = 'week' THEN
SET KEEP_HISTORY_BEFORE = UNIX_TIMESTAMP(DATE(NOW() - INTERVAL KEEP_HISTORY_TMP WEEK));
старая версия с ошибкой
Показать
DELIMITER $$
USE `zabbixdb`$$
DROP PROCEDURE IF EXISTS `drop_partitions`$$
CREATE PROCEDURE `drop_partitions`(IN_SCHEMANAME VARCHAR(64))
COMMENT 'Проверка наличия устаревших секций и удаление'
BEGIN
DECLARE TABLENAME_TMP VARCHAR(64);
DECLARE PARTITIONNAME_TMP VARCHAR(64);
DECLARE VALUES_LESS_TMP INT;
DECLARE PERIOD_TMP VARCHAR(12);
DECLARE KEEP_HISTORY_TMP INT;
DECLARE KEEP_HISTORY_BEFORE INT;
DECLARE DONE INT DEFAULT 0;
DECLARE get_partitions CURSOR FOR
SELECT p.`table_name`, p.`partition_name`, LTRIM(RTRIM(p.`partition_description`)), mp.`period`, mp.`keep_history`
FROM information_schema.partitions p
JOIN manage_partitions mp ON mp.tablename = p.table_name
WHERE p.table_schema = IN_SCHEMANAME
ORDER BY p.table_name, p.subpartition_ordinal_position;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN get_partitions;
loop_check_prt: LOOP
IF DONE THEN
LEAVE loop_check_prt;
END IF;
FETCH get_partitions INTO TABLENAME_TMP, PARTITIONNAME_TMP, VALUES_LESS_TMP, PERIOD_TMP, KEEP_HISTORY_TMP;
CASE WHEN PERIOD_TMP = 'day' THEN
SET KEEP_HISTORY_BEFORE = UNIX_TIMESTAMP(DATE(NOW() - INTERVAL KEEP_HISTORY_TMP DAY));
FETCH get_partitions INTO TABLENAME_TMP, PARTITIONNAME_TMP, VALUES_LESS_TMP, PERIOD_TMP, KEEP_HISTORY_TMP;
CASE WHEN PERIOD_TMP = 'week' THEN
SET KEEP_HISTORY_BEFORE = UNIX_TIMESTAMP(DATE(NOW() - INTERVAL KEEP_HISTORY_TMP WEEK));
WHEN PERIOD_TMP = 'month' THEN
SET KEEP_HISTORY_BEFORE = UNIX_TIMESTAMP(DATE(NOW() - INTERVAL KEEP_HISTORY_TMP MONTH - INTERVAL DAY(NOW())-1 DAY));
ELSE
BEGIN
ITERATE loop_check_prt;
END;
END CASE;
IF KEEP_HISTORY_BEFORE >= VALUES_LESS_TMP THEN
CALL drop_old_partition(IN_SCHEMANAME, TABLENAME_TMP, PARTITIONNAME_TMP);
END IF;
END LOOP loop_check_prt;
CLOSE get_partitions;
END$$
DELIMITER ;
USE `zabbixdb`$$
DROP PROCEDURE IF EXISTS `drop_partitions`$$
CREATE PROCEDURE `drop_partitions`(IN_SCHEMANAME VARCHAR(64))
COMMENT 'Проверка наличия устаревших секций и удаление'
BEGIN
DECLARE TABLENAME_TMP VARCHAR(64);
DECLARE PARTITIONNAME_TMP VARCHAR(64);
DECLARE VALUES_LESS_TMP INT;
DECLARE PERIOD_TMP VARCHAR(12);
DECLARE KEEP_HISTORY_TMP INT;
DECLARE KEEP_HISTORY_BEFORE INT;
DECLARE DONE INT DEFAULT 0;
DECLARE get_partitions CURSOR FOR
SELECT p.`table_name`, p.`partition_name`, LTRIM(RTRIM(p.`partition_description`)), mp.`period`, mp.`keep_history`
FROM information_schema.partitions p
JOIN manage_partitions mp ON mp.tablename = p.table_name
WHERE p.table_schema = IN_SCHEMANAME
ORDER BY p.table_name, p.subpartition_ordinal_position;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN get_partitions;
loop_check_prt: LOOP
IF DONE THEN
LEAVE loop_check_prt;
END IF;
FETCH get_partitions INTO TABLENAME_TMP, PARTITIONNAME_TMP, VALUES_LESS_TMP, PERIOD_TMP, KEEP_HISTORY_TMP;
CASE WHEN PERIOD_TMP = 'day' THEN
SET KEEP_HISTORY_BEFORE = UNIX_TIMESTAMP(DATE(NOW() - INTERVAL KEEP_HISTORY_TMP DAY));
FETCH get_partitions INTO TABLENAME_TMP, PARTITIONNAME_TMP, VALUES_LESS_TMP, PERIOD_TMP, KEEP_HISTORY_TMP;
CASE WHEN PERIOD_TMP = 'week' THEN
SET KEEP_HISTORY_BEFORE = UNIX_TIMESTAMP(DATE(NOW() - INTERVAL KEEP_HISTORY_TMP WEEK));
WHEN PERIOD_TMP = 'month' THEN
SET KEEP_HISTORY_BEFORE = UNIX_TIMESTAMP(DATE(NOW() - INTERVAL KEEP_HISTORY_TMP MONTH - INTERVAL DAY(NOW())-1 DAY));
ELSE
BEGIN
ITERATE loop_check_prt;
END;
END CASE;
IF KEEP_HISTORY_BEFORE >= VALUES_LESS_TMP THEN
CALL drop_old_partition(IN_SCHEMANAME, TABLENAME_TMP, PARTITIONNAME_TMP);
END IF;
END LOOP loop_check_prt;
CLOSE get_partitions;
END$$
DELIMITER ;
mysql>
DELIMITER $$
USE `zabbixdb`$$
DROP PROCEDURE IF EXISTS `drop_old_partition`$$
CREATE PROCEDURE `drop_old_partition`(IN_SCHEMANAME VARCHAR(64), IN_TABLENAME VARCHAR(64), IN_PARTITIONNAME VARCHAR(64))
COMMENT 'Удаление указанной секции'
BEGIN
DECLARE ROWS_CNT INT UNSIGNED;
SELECT COUNT(*) INTO ROWS_CNT
FROM information_schema.partitions
WHERE table_schema = IN_SCHEMANAME AND table_name = IN_TABLENAME AND partition_name = IN_PARTITIONNAME;
IF ROWS_CNT = 1 THEN
SET @SQL = CONCAT( 'ALTER TABLE `', IN_SCHEMANAME, '`.`', IN_TABLENAME, '`',
' DROP PARTITION ', IN_PARTITIONNAME, ';' );
PREPARE STMT FROM @SQL;
EXECUTE STMT;
DEALLOCATE PREPARE STMT;
ELSE
SELECT CONCAT("partition `", IN_PARTITIONNAME, "` for table `",IN_SCHEMANAME, ".", IN_TABLENAME, "` not exists") AS result;
END IF;
END$$
DELIMITER ;
Управление разбиениями, планировщик (events)
DELIMITER $$
USE `zabbixdb` $$
CREATE EVENT `e_part_manage`
ON SCHEDULE EVERY 1 DAY
STARTS '2019-05-29 00:00:00'
ON COMPLETION PRESERVE
ENABLE
COMMENT 'Управление созданием и удалением секций'
DO BEGIN
CALL zabbix.drop_partitions('zabbixdb');
CALL zabbix.create_next_partitions('zabbixdb');
END$$
DELIMITER ;
То что есть ошибки токена в phpmyadmin ничего страшного все будет работать просто так отображается в phpmyadmin Как запустить процедуры вручную указываем схему нашу БД zabbixbd и соответствующую таблицу для этой процедуры Событие e_part_manage заданное на определенное время вызывает call 2 процедуры
create_next_partitions эта же процедура запускает еще 3 процедуры create_partition_by_ 1 day 2 week 3 month перебирая все соответствия переменных из таблицы manage_partitions имя таблицы и период на какой срок создать партацию день неделю месяц от текущей даты (т.е. это не значит что у вас неделя будет с понедельника а месяц с начала месяца отсчет будет в днях с момента запуска процедур) (записывается время последнего добавления раздела last_updated)
запускается 2 процедура drop_partitions Проверка наличия устаревших секций и удаление по таблице manage_partitions перебор по переменным столбцам соответствие имя таблицы соответствие ее к день неделя или месяц далее значение в днях старше скольких дней не должно быть партаций.
Кому интересно видосик про создания событий
MySQL 8 CREATE EVENT работа с событиями
Второй способ через Скрипт
Разбиение с помощью внешнего скрипта
Показать
Внешний хранимый скрипт можно использовать вместо хранимых процедур. Хотя это должно быть запланировано вне базы данных, обычно это будет проще и легче отлаживать. Предлагается добавить ежедневную работу cron. Скрипт поддерживает создание новых разделов и удаление старых.
Примечание. Перед добавлением сценария в качестве задания cron требуемый период хранения и тип раздела для каждой таблицы должны быть установлены в самом сценарии. Установка 0 для keep_history позволит сохранить только один активный в данный момент раздел.
Примечание. Выберите нужную версию Zabbix и раскомментируйте и закомментируйте нужные строки (zabbix 2.2 без возможности включения определенных элементов управления домработницей). Для zabbix начиная с 2.2 прокомментируйте 5 строк, как это предлагается внутри скрипта.
Примечание. В настоящее время сценарий предполагает использование версии MySQL до версии 5.6. Для MySQL версии 5.6 и выше, 2 строки внутри скрипта должны быть закомментированы / некомментированы.
Примечание. Если вы используете systemd / journald, вы можете увидеть вывод скрипта в syslog или с помощью journalctl -t mysql_zbx_part.
Примечание. Перед добавлением сценария в качестве задания cron требуемый период хранения и тип раздела для каждой таблицы должны быть установлены в самом сценарии. Установка 0 для keep_history позволит сохранить только один активный в данный момент раздел.
Примечание. Выберите нужную версию Zabbix и раскомментируйте и закомментируйте нужные строки (zabbix 2.2 без возможности включения определенных элементов управления домработницей). Для zabbix начиная с 2.2 прокомментируйте 5 строк, как это предлагается внутри скрипта.
Примечание. В настоящее время сценарий предполагает использование версии MySQL до версии 5.6. Для MySQL версии 5.6 и выше, 2 строки внутри скрипта должны быть закомментированы / некомментированы.
Примечание. Если вы используете systemd / journald, вы можете увидеть вывод скрипта в syslog или с помощью journalctl -t mysql_zbx_part.
30 дней
history
history_log
history_str
history_text
history_uint
2 месяца
trends
trends_uint
Следующие таблицы на ваше усмотрение рекомендуют их разбивать если заббикс ниже версии 2.2
acknowledges 23 месяца
alerts 6 месяцев
auditlog 24 месяца
events 12 месяцев
service_alarms 6 месяцев
Скриптом что нужно будет сделать
Установка Perl и DateTime
Показать
yum install -y perl-Sys-Syslog - установка Perl
Устанавливаем дополнительные пакеты для запуска функций используемого скрипта разметки Perl.
yum install perl-CPAN perl-DateTime-TimeZone perl-DBD-MySQL perl-Sys-Syslog
Debian
При ошибке Can't locate DateTime.pm
установить модуль DateTime
cpan :: cpanminus
Потверждаем YES
установка
cpanm DateTime
или
perl -MCPAN -e shell
install DateTime
У кого скрипт ругается на DBD::mysql устанавливаем его
install DBD::mysql если так не ставится альтернативный вариант пакетом
apt-get install libdbd-mysql-perl
У меня отличается путь mysql_socket=/var/lib/mysql/mysql.sock'; новый mysql_socket=/var/run/mysqld/mysqld.sock'; или mysql_socket=/run/mysqld/mysqld.sock';
Устанавливаем дополнительные пакеты для запуска функций используемого скрипта разметки Perl.
yum install perl-CPAN perl-DateTime-TimeZone perl-DBD-MySQL perl-Sys-Syslog
Debian
При ошибке Can't locate DateTime.pm
установить модуль DateTime
cpan :: cpanminus
Потверждаем YES
установка
cpanm DateTime
или
perl -MCPAN -e shell
install DateTime
У кого скрипт ругается на DBD::mysql устанавливаем его
install DBD::mysql если так не ставится альтернативный вариант пакетом
apt-get install libdbd-mysql-perl
У меня отличается путь mysql_socket=/var/lib/mysql/mysql.sock'; новый mysql_socket=/var/run/mysqld/mysqld.sock'; или mysql_socket=/run/mysqld/mysqld.sock';
mkdir /etc/zabbix
Создаем скрип
nano /etc/zabbix/zabbix_partitioning.pl
изменить имя базы логин пароль подключения к базе и другие параметры если вам нужно иначе.
закомментировать # команды для заббикс версии 2.2 если у вас более новая
Закоментировать MySql версию 5.5 или 5.6 в зависимости что у вас ниже 5.5 или выше 5.6
Проверено на Версия Server version: 10.1.38-MariaDB-0+deb9u1 Debian 9.8 все работает.
Скрипт
Показать
#!/usr/bin/perl
use strict;
use Data::Dumper;
use DBI;
use Sys::Syslog qw(:standard :macros);
use DateTime;
use POSIX qw(strftime);
openlog("mysql_zbx_part", "ndelay,pid", LOG_LOCAL0);
my $db_schema = 'zabbixdb';
my $dsn = 'DBI:mysql:'.$db_schema.':mysql_socket=/var/run/mysqld/mysqld.sock';
my $db_user_name = 'Пользователь для подключения к базе данных zabbixdb';
my $db_password = '<Пароль>';
my $tables = { 'history' => { 'period' => 'day', 'keep_history' => '30'},
'history_log' => { 'period' => 'day', 'keep_history' => '30'},
'history_str' => { 'period' => 'day', 'keep_history' => '30'},
'history_text' => { 'period' => 'day', 'keep_history' => '30'},
'history_uint' => { 'period' => 'day', 'keep_history' => '30'},
'trends' => { 'period' => 'month', 'keep_history' => '2'},
'trends_uint' => { 'period' => 'month', 'keep_history' => '2'},
# комментируйте следующие 5 строк, если вы разбиваете базу данных zabbix, начиная с 2.2
# они обычно использовались для базы данных zabbix до 2.2 т е не будут разбавится следующие 5 таблиц acknowledges alerts auditlog events service_alarms
# количество разделов 10 - 1 текущий + на 9 дней вперед создание файлов - amount_partitions = 10
# 'acknowledges' => { 'period' => 'month', 'keep_history' => '23'},
# 'alerts' => { 'period' => 'month', 'keep_history' => '6'},
# 'auditlog' => { 'period' => 'month', 'keep_history' => '24'},
# 'events' => { 'period' => 'month', 'keep_history' => '12'},
# 'service_alarms' => { 'period' => 'month', 'keep_history' => '6'},
};
my $amount_partitions = 10;
my $curr_tz = 'Europe/Moscow';
my $part_tables;
my $dbh = DBI->connect($dsn, $db_user_name, $db_password, {'ShowErrorStatement' => 1});
unless ( check_have_partition() ) {
print "Ваша установка MySQL не поддерживает разбиение таблиц.\n";
syslog(LOG_CRIT, 'Ваша установка MySQL не поддерживает разбиение таблиц.');
exit 1;
}
my $sth = $dbh->prepare(qq{SELECT table_name, partition_name, lower(partition_method) as partition_method,
rtrim(ltrim(partition_expression)) as partition_expression,
partition_description, table_rows
FROM information_schema.partitions
WHERE partition_name IS NOT NULL AND table_schema = ?});
$sth->execute($db_schema);
while (my $row = $sth->fetchrow_hashref()) {
$part_tables->{$row->{'table_name'}}->{$row->{'partition_name'}} = $row;
}
$sth->finish();
foreach my $key (sort keys %{$tables}) {
unless (defined($part_tables->{$key})) {
syslog(LOG_ERR, 'Разметка для "'.$key.'" не найден! Таблица может быть не разделена.');
next;
}
create_next_partition($key, $part_tables->{$key}, $tables->{$key}->{'period'});
remove_old_partitions($key, $part_tables->{$key}, $tables->{$key}->{'period'}, $tables->{$key}->{'keep_history'})
}
delete_old_data();
$dbh->disconnect();
sub check_have_partition {
my $result = 0;
# MySQL 5.5
#my $sth = $dbh->prepare(qq{SELECT variable_value FROM information_schema.global_variables WHERE variable_name = 'have_partitioning'});
# MySQL 5.6
my $sth = $dbh->prepare(qq{SELECT plugin_status FROM information_schema.plugins WHERE plugin_name = 'partition'});
$sth->execute();
my $row = $sth->fetchrow_array();
$sth->finish();
# MySQL 5.5
#return 1 if $row eq 'YES';
# MySQL 5.6
return 1 if $row eq 'ACTIVE';
}
sub create_next_partition {
my $table_name = shift;
my $table_part = shift;
my $period = shift;
for (my $curr_part = 0; $curr_part < $amount_partitions; $curr_part++) {
my $next_name = name_next_part($tables->{$table_name}->{'period'}, $curr_part);
my $found = 0;
foreach my $partition (sort keys %{$table_part}) {
if ($next_name eq $partition) {
syslog(LOG_INFO, "Следующий раздел для $table_name уже создан. Это $next_name");
$found = 1;
}
}
if ( $found == 0 ) {
syslog(LOG_INFO, "Создание раздела для таблицы $table_name table ($next_name)");
my $query = 'ALTER TABLE '."$db_schema.$table_name".' ADD PARTITION (PARTITION '.$next_name.
' VALUES less than (UNIX_TIMESTAMP("'.date_next_part($tables->{$table_name}->{'period'}, $curr_part).'") div 1))';
syslog(LOG_DEBUG, $query);
$dbh->do($query);
}
}
}
sub remove_old_partitions {
my $table_name = shift;
my $table_part = shift;
my $period = shift;
my $keep_history = shift;
my $curr_date = DateTime->now;
$curr_date->set_time_zone( $curr_tz );
if ( $period eq 'day' ) {
$curr_date->add(days => -$keep_history);
$curr_date->add(hours => -$curr_date->strftime('%H'));
$curr_date->add(minutes => -$curr_date->strftime('%M'));
$curr_date->add(seconds => -$curr_date->strftime('%S'));
}
elsif ( $period eq 'week' ) {
}
elsif ( $period eq 'month' ) {
$curr_date->add(months => -$keep_history);
$curr_date->add(days => -$curr_date->strftime('%d')+1);
$curr_date->add(hours => -$curr_date->strftime('%H'));
$curr_date->add(minutes => -$curr_date->strftime('%M'));
$curr_date->add(seconds => -$curr_date->strftime('%S'));
}
foreach my $partition (sort keys %{$table_part}) {
if ($table_part->{$partition}->{'partition_description'} <= $curr_date->epoch) {
syslog(LOG_INFO, "Удаление старого раздела $partition из таблицы $table_name table");
my $query = "ALTER TABLE $db_schema.$table_name DROP PARTITION $partition";
syslog(LOG_DEBUG, $query);
$dbh->do($query);
}
}
}
sub name_next_part {
my $period = shift;
my $curr_part = shift;
my $name_template;
my $curr_date = DateTime->now;
$curr_date->set_time_zone( $curr_tz );
if ( $period eq 'day' ) {
my $curr_date = $curr_date->truncate( to => 'day' );
$curr_date->add(days => 1 + $curr_part);
$name_template = $curr_date->strftime('p%Y_%m_%d');
}
elsif ($period eq 'week') {
my $curr_date = $curr_date->truncate( to => 'week' );
$curr_date->add(days => 7 * $curr_part);
$name_template = $curr_date->strftime('p%Y_%m_w%W');
}
elsif ($period eq 'month') {
my $curr_date = $curr_date->truncate( to => 'month' );
$curr_date->add(months => 1 + $curr_part);
$name_template = $curr_date->strftime('p%Y_%m');
}
return $name_template;
}
sub date_next_part {
my $period = shift;
my $curr_part = shift;
my $period_date;
my $curr_date = DateTime->now;
$curr_date->set_time_zone( $curr_tz );
if ( $period eq 'day' ) {
my $curr_date = $curr_date->truncate( to => 'day' );
$curr_date->add(days => 2 + $curr_part);
$period_date = $curr_date->strftime('%Y-%m-%d');
}
elsif ($period eq 'week') {
my $curr_date = $curr_date->truncate( to => 'week' );
$curr_date->add(days => 7 * $curr_part + 1);
$period_date = $curr_date->strftime('%Y-%m-%d');
}
elsif ($period eq 'month') {
my $curr_date = $curr_date->truncate( to => 'month' );
$curr_date->add(months => 2 + $curr_part);
$period_date = $curr_date->strftime('%Y-%m-%d');
}
return $period_date;
}
sub delete_old_data {
$dbh->do("DELETE FROM sessions WHERE lastaccess < UNIX_TIMESTAMP(NOW() - INTERVAL 1 MONTH)");
$dbh->do("TRUNCATE housekeeper");
$dbh->do("DELETE FROM auditlog_details WHERE NOT EXISTS (SELECT NULL FROM auditlog WHERE auditlog.auditid = auditlog_details.auditid)");
}
use strict;
use Data::Dumper;
use DBI;
use Sys::Syslog qw(:standard :macros);
use DateTime;
use POSIX qw(strftime);
openlog("mysql_zbx_part", "ndelay,pid", LOG_LOCAL0);
my $db_schema = 'zabbixdb';
my $dsn = 'DBI:mysql:'.$db_schema.':mysql_socket=/var/run/mysqld/mysqld.sock';
my $db_user_name = 'Пользователь для подключения к базе данных zabbixdb';
my $db_password = '<Пароль>';
my $tables = { 'history' => { 'period' => 'day', 'keep_history' => '30'},
'history_log' => { 'period' => 'day', 'keep_history' => '30'},
'history_str' => { 'period' => 'day', 'keep_history' => '30'},
'history_text' => { 'period' => 'day', 'keep_history' => '30'},
'history_uint' => { 'period' => 'day', 'keep_history' => '30'},
'trends' => { 'period' => 'month', 'keep_history' => '2'},
'trends_uint' => { 'period' => 'month', 'keep_history' => '2'},
# комментируйте следующие 5 строк, если вы разбиваете базу данных zabbix, начиная с 2.2
# они обычно использовались для базы данных zabbix до 2.2 т е не будут разбавится следующие 5 таблиц acknowledges alerts auditlog events service_alarms
# количество разделов 10 - 1 текущий + на 9 дней вперед создание файлов - amount_partitions = 10
# 'acknowledges' => { 'period' => 'month', 'keep_history' => '23'},
# 'alerts' => { 'period' => 'month', 'keep_history' => '6'},
# 'auditlog' => { 'period' => 'month', 'keep_history' => '24'},
# 'events' => { 'period' => 'month', 'keep_history' => '12'},
# 'service_alarms' => { 'period' => 'month', 'keep_history' => '6'},
};
my $amount_partitions = 10;
my $curr_tz = 'Europe/Moscow';
my $part_tables;
my $dbh = DBI->connect($dsn, $db_user_name, $db_password, {'ShowErrorStatement' => 1});
unless ( check_have_partition() ) {
print "Ваша установка MySQL не поддерживает разбиение таблиц.\n";
syslog(LOG_CRIT, 'Ваша установка MySQL не поддерживает разбиение таблиц.');
exit 1;
}
my $sth = $dbh->prepare(qq{SELECT table_name, partition_name, lower(partition_method) as partition_method,
rtrim(ltrim(partition_expression)) as partition_expression,
partition_description, table_rows
FROM information_schema.partitions
WHERE partition_name IS NOT NULL AND table_schema = ?});
$sth->execute($db_schema);
while (my $row = $sth->fetchrow_hashref()) {
$part_tables->{$row->{'table_name'}}->{$row->{'partition_name'}} = $row;
}
$sth->finish();
foreach my $key (sort keys %{$tables}) {
unless (defined($part_tables->{$key})) {
syslog(LOG_ERR, 'Разметка для "'.$key.'" не найден! Таблица может быть не разделена.');
next;
}
create_next_partition($key, $part_tables->{$key}, $tables->{$key}->{'period'});
remove_old_partitions($key, $part_tables->{$key}, $tables->{$key}->{'period'}, $tables->{$key}->{'keep_history'})
}
delete_old_data();
$dbh->disconnect();
sub check_have_partition {
my $result = 0;
# MySQL 5.5
#my $sth = $dbh->prepare(qq{SELECT variable_value FROM information_schema.global_variables WHERE variable_name = 'have_partitioning'});
# MySQL 5.6
my $sth = $dbh->prepare(qq{SELECT plugin_status FROM information_schema.plugins WHERE plugin_name = 'partition'});
$sth->execute();
my $row = $sth->fetchrow_array();
$sth->finish();
# MySQL 5.5
#return 1 if $row eq 'YES';
# MySQL 5.6
return 1 if $row eq 'ACTIVE';
}
sub create_next_partition {
my $table_name = shift;
my $table_part = shift;
my $period = shift;
for (my $curr_part = 0; $curr_part < $amount_partitions; $curr_part++) {
my $next_name = name_next_part($tables->{$table_name}->{'period'}, $curr_part);
my $found = 0;
foreach my $partition (sort keys %{$table_part}) {
if ($next_name eq $partition) {
syslog(LOG_INFO, "Следующий раздел для $table_name уже создан. Это $next_name");
$found = 1;
}
}
if ( $found == 0 ) {
syslog(LOG_INFO, "Создание раздела для таблицы $table_name table ($next_name)");
my $query = 'ALTER TABLE '."$db_schema.$table_name".' ADD PARTITION (PARTITION '.$next_name.
' VALUES less than (UNIX_TIMESTAMP("'.date_next_part($tables->{$table_name}->{'period'}, $curr_part).'") div 1))';
syslog(LOG_DEBUG, $query);
$dbh->do($query);
}
}
}
sub remove_old_partitions {
my $table_name = shift;
my $table_part = shift;
my $period = shift;
my $keep_history = shift;
my $curr_date = DateTime->now;
$curr_date->set_time_zone( $curr_tz );
if ( $period eq 'day' ) {
$curr_date->add(days => -$keep_history);
$curr_date->add(hours => -$curr_date->strftime('%H'));
$curr_date->add(minutes => -$curr_date->strftime('%M'));
$curr_date->add(seconds => -$curr_date->strftime('%S'));
}
elsif ( $period eq 'week' ) {
}
elsif ( $period eq 'month' ) {
$curr_date->add(months => -$keep_history);
$curr_date->add(days => -$curr_date->strftime('%d')+1);
$curr_date->add(hours => -$curr_date->strftime('%H'));
$curr_date->add(minutes => -$curr_date->strftime('%M'));
$curr_date->add(seconds => -$curr_date->strftime('%S'));
}
foreach my $partition (sort keys %{$table_part}) {
if ($table_part->{$partition}->{'partition_description'} <= $curr_date->epoch) {
syslog(LOG_INFO, "Удаление старого раздела $partition из таблицы $table_name table");
my $query = "ALTER TABLE $db_schema.$table_name DROP PARTITION $partition";
syslog(LOG_DEBUG, $query);
$dbh->do($query);
}
}
}
sub name_next_part {
my $period = shift;
my $curr_part = shift;
my $name_template;
my $curr_date = DateTime->now;
$curr_date->set_time_zone( $curr_tz );
if ( $period eq 'day' ) {
my $curr_date = $curr_date->truncate( to => 'day' );
$curr_date->add(days => 1 + $curr_part);
$name_template = $curr_date->strftime('p%Y_%m_%d');
}
elsif ($period eq 'week') {
my $curr_date = $curr_date->truncate( to => 'week' );
$curr_date->add(days => 7 * $curr_part);
$name_template = $curr_date->strftime('p%Y_%m_w%W');
}
elsif ($period eq 'month') {
my $curr_date = $curr_date->truncate( to => 'month' );
$curr_date->add(months => 1 + $curr_part);
$name_template = $curr_date->strftime('p%Y_%m');
}
return $name_template;
}
sub date_next_part {
my $period = shift;
my $curr_part = shift;
my $period_date;
my $curr_date = DateTime->now;
$curr_date->set_time_zone( $curr_tz );
if ( $period eq 'day' ) {
my $curr_date = $curr_date->truncate( to => 'day' );
$curr_date->add(days => 2 + $curr_part);
$period_date = $curr_date->strftime('%Y-%m-%d');
}
elsif ($period eq 'week') {
my $curr_date = $curr_date->truncate( to => 'week' );
$curr_date->add(days => 7 * $curr_part + 1);
$period_date = $curr_date->strftime('%Y-%m-%d');
}
elsif ($period eq 'month') {
my $curr_date = $curr_date->truncate( to => 'month' );
$curr_date->add(months => 2 + $curr_part);
$period_date = $curr_date->strftime('%Y-%m-%d');
}
return $period_date;
}
sub delete_old_data {
$dbh->do("DELETE FROM sessions WHERE lastaccess < UNIX_TIMESTAMP(NOW() - INTERVAL 1 MONTH)");
$dbh->do("TRUNCATE housekeeper");
$dbh->do("DELETE FROM auditlog_details WHERE NOT EXISTS (SELECT NULL FROM auditlog WHERE auditlog.auditid = auditlog_details.auditid)");
}
./zabbix_partitioning.pl - выполним (запустим) скрипт
Проверяем заходим в mysql выбираем базу данных zabbixdb
проверяем партицирование
show create table history_uint; просмотр данных о таблице (так же партицирование если оно есть)
выходим из mysql
Добавим задание (в планировщик заданий) cron и запустите его дважды в ночь (в маловероятном случае, если оно не сработает в первый раз)
vi /etc/cron.d/zabbix_part
# Zabbix ежедневное разбиение таблицы
# Zabbix daily table partitioning
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
00 23 * * * root perl /etc/zabbix/zabbix_partitioning.pl 1>/var/log/zabbix/zabbix_partitioning.log 2>&1
00 2 * * * root perl /etc/zabbix/zabbix_partitioning.pl 1>/var/log/zabbix/zabbix_partitioning.log 2>&1
формат: *минута *час *день_месяца *месяц *день_недели *команда изменить путь на свой где лежит скрипт вывод логов в папку
После всего периодически стоит проверять логи
создались ли файлы и удаляются ли старые
После перезапуска рекомендую проверить логи чтобы не было никаких серьезных ошибок там
nano /tmp/zabbix_server.log - тут будет писаться если не хватает какого то файла таблицы на текущий день тобиш некуда писать данные
nano /var/log/zabbix/zabbix_partitioning.log - если используется скрипт через cron
так же можно посмотреть
nano /var/log/mysql/error.log
nano /var/log/apache2/error.log
и другие логи по данному пути /var/log/
Примеры ошибк
Показать
В некоторых случаях при отсутствии файлов не войдет на веб интерфейс
nano /tmp/zabbix_server.log есть ошибка но отсутствие файла
Был такой нюанс указали service_alarms хранить 30 месяцев в место 3
ниже было еще trends и trends_uint и все вставало на файле с 30 месяцами все 3 файла не создавались данная ошибка просматривалась в логах, а все невнимательность)
Так же может войти и вроде как все работать но по факту некоторые проверки просто стоят на месте ничего не мониторят.nano /tmp/zabbix_server.log есть ошибка но отсутствие файла
Был такой нюанс указали service_alarms хранить 30 месяцев в место 3
ниже было еще trends и trends_uint и все вставало на файле с 30 месяцами все 3 файла не создавались данная ошибка просматривалась в логах, а все невнимательность)
MySQL Database partitioning for ZABBIX
Источники
zabbix.org mysql_partitioning
Разбиение (секционирование) в бд zabbix MySQL