Для решения проблемы больших объёмов базы есть несколько вариантов:
- Удалить ненужные узлы сети, уменьшить период хранения истории (history) и динамики изменений (trends), отключить сбор ненужных метрик к шаблонах и т.д.
- Если же размер базы всё равно достаточно объемный, можно применить партиционирование таблиц, о котором и будет рассказано.
Партиционирование появилось в MySQL v5.1 и позволяет добиться от базы более оптимальной\быстрой работы запросов. Это относится к тем моментам, когда выборка происходит из большого количества данных в таблицах.
При использовании в конфиге MySQL параметра file_per_table, каждая таблица будет иметь физический файл на диске. При использовании партиций, большие таблицы разбиваются на логические части. С точки зрения БД, это будет одна таблица, но с точки зрения физического хранения уже получается несколько физических файлов.
Нижеописанное будет применено к Zabbix Server 4.0.5 и MySQL 5.6. По идее, будет работать со всеми версиями Zabbix, начиная с 3.2 и до 4.х, т.к. структура базы, а точнее нужные таблицы, которые подлежат партиционированию, не менялись. Но лучше всегда уточнять в оф. документации для конкретной версии.
- Виды партиций
- Способ управления партициями
- Таблицы с данными в Zabbix
- Разделение на партиции. Предварительная теория и настройка
- Разделение на партиции. Пример для таблиц, в которых уже есть данные
- Разделение на партиции. Пример для пустых таблиц (новая установка)
- Процедуры MySQL
- Очистка данных (Housekeeper)
- Автоматическое создание партиций
- Использованные источники
Виды партиций
Тип партиций, который будет использован – Range. При его использовании, таблица делится на диапазоны, установленные в ключевом столбце. Диапазоны не должны перекрываться (например, диапазоны дат или идентификаторов). Есть также другие виды партиций, например, hash, list и прочие. Но обсуждение этих типов выходит за рамки данной статьи.
Для детального изучения вопроса о партиционировании в MySQL, лучше всего обратиться к оф. докуметации.
Способ управления партициями
Имеется два основных решения:
- использование процедур MySQL (будет использован в данном статье);
- использование внешних скриптов (perl, bash и прочие).
Таблицы с данными в Zabbix
В Zabbix есть несколько таблиц, которые хранят различные типы исторических данных. Если вы знаете назначение каждой таблицы, становится легче оценить периоды, которые необходимо использовать в партициях. Ниже приведен список таблиц для хранения данных.
- history
- history_uint
- history_str
- history_text
- history_log
- trends
- trends_uint
Таблицы trends* отвечают за динамику изменений, таблицы history* – соответственно за историю данных нужных типов.
Разделение на партиции. Предварительная теория и настройка
Теперь подошли непосредственно к вопросу о создании партиций. В данном случае, я буду использовать партиционирование по дням и применительно ко всем таблицам history* и trends*.
Первоначально я выбрал вариант с созданием партиций по месяцам и для таблиц, которые были слишком объемными на тот момент (только history и history_uint). Но как показала практика, со временем оставшиеся таблицы стали разрастаться, а потому удобнее и проще всего делать партиции по дням и на все таблицы, особенно если это первичная установка Zabbix.
Из минусов – при больших выборках за 3 и более дней на комплексных экранах с нескольких серверов будут небольшие задержки. Но меня такой вариант абсолютно устроил.
Итак: если же есть какие-то особые требования, то уже надо выбирать из исходных данных относительно партиционирования в целом, а если же нужно просто разбить таблицы для очистки, то лучше разбивать по дням и на все history* и trends* таблицы.
Перед началом всех работ нужно убедиться, что в MySQL включен планировщик (и исправить, если не включён, в т.ч. в конфиге), т.к. это часто бывает ошибкой в дальнейшем, когда что-то не работает:
mysql> SHOW GLOBAL VARIABLES LIKE 'event_scheduler';
+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| event_scheduler | OFF |
+-----------------+-------+
1 row in set (0.00 sec)
mysql> SET GLOBAL event_scheduler = ON;
Query OK, 0 rows affected (0.00 sec)
Не забыть добавить в конфиг my.cnf:
event_scheduler=ON
Разделение на партиции. Пример для таблиц, в которых уже есть данные
Если разделение таблиц выполняется для базы с уже существующими данными, для каждой таблицы необходимо указывать разделы, начиная с минимального значения поля clock и до текущего месяца включительно. Минимальное значение clock таблицы можно получить так (выполняется достаточно долго):
SELECT FROM_UNIXTIME(MIN(clock)) FROM `history_uint`;
SELECT FROM_UNIXTIME(MIN(clock)) FROM `history`;
... и так далее для всех нужных таблиц.
Например, при необходимости делать партиции по месяцам, если полученные значения FROM_UNIXTIME(MIN(clock)) датируются мартом 2019 года, то это значит, что минимальная партиция будет за март и далее создаются для последующих месяцев:
ALTER TABLE `history` PARTITION BY RANGE (clock)
(PARTITION p2019_03 VALUES LESS THAN (UNIX_TIMESTAMP("2019-04-01 00:00:00")) ENGINE = InnoDB,
PARTITION p2019_04 VALUES LESS THAN (UNIX_TIMESTAMP("2019-05-01 00:00:00")) ENGINE = InnoDB,
PARTITION p2019_05 VALUES LESS THAN (UNIX_TIMESTAMP("2019-06-01 00:00:00")) ENGINE = InnoDB,
PARTITION p2019_06 VALUES LESS THAN (UNIX_TIMESTAMP("2019-07-01 00:00:00")) ENGINE = InnoDB);
...
И так для каждой таблицы в зависимости от того, от какого числа в ней данные.
Иногда может возникать ошибка при создании партиций для таблиц с имеющимися данными в них:
The table '#sql-2f0_99b03' is full
Оно и логично, ведь иногда партиции настраиваются тогда, когда место на диске уже заканчивается. Поэтому в такой ситуации можно будет сделать так:
- остановить zabbix, чтобы в базу ничего не залетало;
- бэкап нужной таблицы с данными (а лучше базы на всякий случай);
- truncate table; (очистка данных с сохранением структуры)
- создание партиций;
- раздамп таблицы с бэкапа.
В результате данные из бэкапа таблицы растекутся по партициям.
Время выполнения вышеописанных SQL-команд достаточно долгое, т.к. происходит копирование сначала во временную таблицу и только потом происходит разбиение. После выполнения, можно увидеть, что появились новые файлы:
Разделение на партиции. Пример для пустых таблиц (новая установка)
Для новой установки Zabbix, где данных ещё нет, всё быстро выполняется следующими командами для всех таблиц. Здесь уже я использовал разбиение по дням, т.к. данный вариант меня абсолютно устраивает:
ALTER TABLE `history_uint` PARTITION BY RANGE (clock)
(PARTITION p2019_10_28 VALUES LESS THAN (UNIX_TIMESTAMP("2019-10-29 00:00:00")) ENGINE = InnoDB);
ALTER TABLE `history` PARTITION BY RANGE (clock)
(PARTITION p2019_10_28 VALUES LESS THAN (UNIX_TIMESTAMP("2019-10-29 00:00:00")) ENGINE = InnoDB);
ALTER TABLE `history_log` PARTITION BY RANGE (clock)
(PARTITION p2019_10_28 VALUES LESS THAN (UNIX_TIMESTAMP("2019-10-29 00:00:00")) ENGINE = InnoDB);
ALTER TABLE `history_str` PARTITION BY RANGE (clock)
(PARTITION p2019_10_28 VALUES LESS THAN (UNIX_TIMESTAMP("2019-10-29 00:00:00")) ENGINE = InnoDB);
ALTER TABLE `history_text` PARTITION BY RANGE (clock)
(PARTITION p2019_10_28 VALUES LESS THAN (UNIX_TIMESTAMP("2019-10-29 00:00:00")) ENGINE = InnoDB);
ALTER TABLE `trends` PARTITION BY RANGE (clock)
(PARTITION p2019_10_28 VALUES LESS THAN (UNIX_TIMESTAMP("2019-10-29 00:00:00")) ENGINE = InnoDB);
ALTER TABLE `trends_uint` PARTITION BY RANGE (clock)
(PARTITION p2019_10_28 VALUES LESS THAN (UNIX_TIMESTAMP("2019-10-29 00:00:00")) ENGINE = InnoDB);
Здесь важный момент: название партиции за один месяц, а значение UNIX_TIMESTAMP на день больше. То есть, имя партиции за сегодняшний день – 28 октября 2019 г., а значение UNIX_TIMESTAMP – следующий, 29 октября 2019 г.
Также ещё не менее важно сделать партицию на день вперёд, чтобы в случае ошибки (например, не запустился event по расписанию или что-то ещё) данные могли записываться в таблицу и была возможность оперативно исправить ошибки. У меня случалось так, что по расписанию партиции создавались с именем следующего дня и нумерация была нарушена.
При возникновении ошибки ERROR 1526 (HY000): Table has no partition for value необходимо проверить, что партиции созданы вплоть до текущего месяца или дня, о чём я написал выше.
После выполнения в директории с БД можно увидеть, что появились физические файлы партиций с нужными префиксами (по дням в данном случае).
Процесс, выполняющий операцию секционирования в таблице, получает блокировку записи в таблицу. Чтения из таких таблиц относительно незатронуты; ожидающие операции INSERT и UPDATE будут выполнены, как только завершится операция разбиения на партиции.
Проверить текущие партиции из MySQL можно командой:
SELECT TABLE_NAME,PARTITION_NAME FROM information_schema.partitions WHERE TABLE_SCHEMA='zabbix' AND TABLE_NAME = 'history';
На этом сам процесс создания партиций закончен. Но после этого возникает нюанс – в случае отсутствия новой партиции на следующий месяц или день, данные не будут записаны. Для решения данного вопроса будут использоваться процедуры БД, которые в автоматическом режиме всё будут делать сами: создавать и удалять партиции.
Процедуры MySQL
Детально описывать назначение процедур не стану, из названий в общем всё и так понятно. Для начала создаются таблицы для хранения информации о текущих партициях и действиях с ними:
USE `zabbix`;
CREATE TABLE IF NOT EXISTS `manage_partitions` (
`tablename` VARCHAR(64) NOT NULL COMMENT 'Table name',
`period` VARCHAR(64) NOT NULL COMMENT 'Period - daily or monthly',
`keep_history` INT(3) UNSIGNED NOT NULL DEFAULT '1' COMMENT 'For how many days or months to keep the partitions',
`last_updated` DATETIME DEFAULT NULL COMMENT 'When a partition was added last time',
`comments` VARCHAR(128) DEFAULT '1' COMMENT 'Comments',
PRIMARY KEY (`tablename`)
) ENGINE=INNODB;
CREATE TABLE IF NOT EXISTS `manage_partitions_history` (
`schema_name` varchar(64) NOT NULL COMMENT 'Zabbix schema name',
`table_name` varchar(64) NOT NULL COMMENT 'Zabbix table name',
`table_partition_name` varchar(64) NOT NULL COMMENT 'Zabbix table partition name',
`partition_action` varchar(64) NOT NULL COMMENT 'Zabbix table partition action',
`partition_action_date` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'When a partition was added or dropped'
) ENGINE=InnoDB;
Если при создании второй таблицы manage_partitions_history возникает ошибка ERROR 1067 (42000): Invalid default value for ‘partition_action_date’ , то вы используете MySQL < 5.6, лучше обновиться на более новую версию (по рекомендациям Zabbix). Более подробно тут.
В таблицу manage_partitions добавляются данные о таблицах с нужным временем хранения в них данных (т.е. партиций с данными за нужный период):
INSERT INTO manage_partitions (tablename, period, keep_history, last_updated, comments) VALUES ('history', 'day', 30, now(), '');
INSERT INTO manage_partitions (tablename, period, keep_history, last_updated, comments) VALUES ('history_uint', 'day', 30, now(), '');
INSERT INTO manage_partitions (tablename, period, keep_history, last_updated, comments) VALUES ('history_str', 'day', 120, now(), '');
INSERT INTO manage_partitions (tablename, period, keep_history, last_updated, comments) VALUES ('history_text', 'day', 120, now(), '');
INSERT INTO manage_partitions (tablename, period, keep_history, last_updated, comments) VALUES ('history_log', 'day', 120, now(), '');
INSERT INTO manage_partitions (tablename, period, keep_history, last_updated, comments) VALUES ('trends', 'day', 180, now(), '');
INSERT INTO manage_partitions (tablename, period, keep_history, last_updated, comments) VALUES ('trends_uint', 'day', 180, now(), '');
А далее создаются процедуры по работе с партициями (создание, удаление и т.д.):
DROP PROCEDURE IF EXISTS `create_next_partitions`;
DROP PROCEDURE IF EXISTS `create_partition_by_day`;
DROP PROCEDURE IF EXISTS `create_partition_by_month`;
DROP PROCEDURE IF EXISTS `drop_partitions`;
DROP PROCEDURE IF EXISTS `drop_old_partition`;
DROP EVENT IF EXISTS `e_zbx_part_mgmt`;
DELIMITER $$
CREATE PROCEDURE `create_next_partitions`(IN_SCHEMANAME VARCHAR(64))
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 = '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 ;
DELIMITER $$
CREATE PROCEDURE `create_partition_by_day`(IN_SCHEMANAME VARCHAR(64), IN_TABLENAME VARCHAR(64))
BEGIN
DECLARE BEGINTIME TIMESTAMP;
DECLARE ENDTIME INT UNSIGNED;
DECLARE PART_ACTION VARCHAR(12);
DECLARE PARTITIONNAME VARCHAR(16);
DECLARE ROWS_CNT INT UNSIGNED;
SET BEGINTIME = DATE(NOW()) + INTERVAL 1 DAY;
SET ENDTIME = UNIX_TIMESTAMP(BEGINTIME + INTERVAL 1 DAY);
SET PART_ACTION = 'ADD';
SET PARTITIONNAME = DATE_FORMAT( BEGINTIME, 'p%Y_%m_%d' );
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('INSERT INTO `manage_partitions_history`(`schema_name`,`table_name`,`table_partition_name`,`partition_action`) VALUES ("', IN_SCHEMANAME,'","', IN_TABLENAME,'","', PARTITIONNAME,'","', PART_ACTION,'");');
PREPARE STMT FROM @SQL;
EXECUTE STMT;
DEALLOCATE PREPARE STMT;
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 ;
DELIMITER $$
CREATE PROCEDURE `create_partition_by_month`(IN_SCHEMANAME VARCHAR(64), IN_TABLENAME VARCHAR(64))
BEGIN
DECLARE BEGINTIME TIMESTAMP;
DECLARE ENDTIME INT UNSIGNED;
DECLARE PART_ACTION VARCHAR(12);
DECLARE PARTITIONNAME VARCHAR(16);
DECLARE ROWS_CNT INT UNSIGNED;
SET BEGINTIME = DATE(NOW() - INTERVAL DAY(NOW()) DAY + INTERVAL 1 DAY + INTERVAL 1 MONTH);
SET ENDTIME = UNIX_TIMESTAMP(BEGINTIME + INTERVAL 1 MONTH);
SET PART_ACTION = 'ADD';
SET PARTITIONNAME = DATE_FORMAT( BEGINTIME, 'p%Y_%m' );
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('INSERT INTO `manage_partitions_history`(`schema_name`,`table_name`,`table_partition_name`,`partition_action`) VALUES ("', IN_SCHEMANAME,'","', IN_TABLENAME,'","', PARTITIONNAME,'","', PART_ACTION,'");');
PREPARE STMT FROM @SQL;
EXECUTE STMT;
DEALLOCATE PREPARE STMT;
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 ;
DELIMITER $$
CREATE PROCEDURE `drop_partitions`(IN_SCHEMANAME VARCHAR(64))
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 ;
DELIMITER $$
CREATE PROCEDURE `drop_old_partition`(IN_SCHEMANAME VARCHAR(64), IN_TABLENAME VARCHAR(64), IN_PARTITIONNAME VARCHAR(64))
BEGIN
DECLARE PART_ACTION VARCHAR(12);
DECLARE PART_ACTION_DATE INT;
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;
SET PART_ACTION = 'DROP';
IF ROWS_CNT = 1 THEN
SET @SQL = CONCAT('INSERT INTO `manage_partitions_history`(`schema_name`,`table_name`,`table_partition_name`,`partition_action`) VALUES ("', IN_SCHEMANAME,'","', IN_TABLENAME,'","', IN_PARTITIONNAME,'","', PART_ACTION,'");');
PREPARE STMT FROM @SQL;
EXECUTE STMT;
DEALLOCATE PREPARE STMT;
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, "` does not exist") AS result;
END IF;
END$$
DELIMITER ;
Перед созданием планировщика проверить, что дата в БД такая же, как и в ОС:
date
mysql> select now();
После создания всех процедур в БД, создается планировщик, который будет выполняться ежедневно, начиная с 04:00:00 2019.10.29 (число удобнее указывать следующего дня от момента настройки партиций):
DELIMITER $$
CREATE EVENT `e_zbx_part_mgmt`
ON SCHEDULE EVERY 1 DAY STARTS '2019-10-29 04:00:00'
ON COMPLETION PRESERVE
ENABLE
COMMENT 'Creating and dropping partitions'
DO BEGIN
CALL zabbix.drop_partitions('zabbix');
CALL zabbix.create_next_partitions('zabbix');
END$$
DELIMITER ;
Для проверки, что планировщик запущен, выполнить:
SHOW EVENTS FROM zabbix;
Изначально у меня была ошибка в планировщике, который выполнялся в полночь уже в следующем месяце, а потому ошибочно создавалась партиция на два месяца вперед. Вручную всё корректно отрабатывало, а при выполнении с планировщика – неверные данные, после которых приходилось править таблицы:
- делать дамп нужных таблиц с кривыми партициями;
- в дампе править параметры создания партиций на текущий месяц;
- вливать дамп таблицы обратно.
Плюс есть ещё високосный год и неизвестно, как себя поведет планировщик, если нужны данные строго и ровно по месяцам. В случае, когда партиции сделаны по дням, планировщик будет работать ежедневно и проблем больше не должно возникнуть.
Также вручную можно вызвать созданные процедуры и убедиться, что они отрабатывают без ошибок:
CALL zabbix.create_next_partitions('zabbix')
А для ручного удаления партиций:
ALTER TABLE history_uint DROP PARTITION p2019_10_29;
Очистка данных (Housekeeper)
И остался последний важный момент. Для таблиц, которые подверглись партиционированию, housekepeer теперь не нужен и его можно (и нужно!) отключить.
В веб-интерфейсе: Администрирование -> Общие -> Очистка истории снять все галки по очистке истории для истории (history) и динамики изменений (trends):
Просто к сведению. Для отключения хаускипера полностью, нужно сменить тип движка у таблицы housekeeper на некий аналог /dev/null:
ALTER TABLE housekeeper ENGINE = BLACKHOLE;
Но лучше так не делать без реальной необходимости.
Помимо процедур и perl-скрипта (на исходном сайте статьи), есть bash-скрипт для создания и удаления партиций, найти можно по ссылке. Его не применял и не проверял, но навскидку посмотрел – по идее, должно работать также, как и процедуры в БД, только используя crontab.
Теперь время подвести итоги. Согласно инструкций выше, можно будет настроить партиционирование таблиц в MySQL для Zabbix, используя процедуры MySQL. Такой подход всегда стоит использовать, когда в базе ожидается большой рост, а когда это случается, то делать партиции уже будет немного сложнее и дольше, а потому я бы рекомендовал делать всё сразу.
Автоматическое создание партиций
Не желая больше вручную создавать партиции, я на коленке накидал bash-скрипт, который генерирует партиции как для таблиц с уже имеющимися данными, так и для чистой установки, в которой данных ещё нет. Подробнее на гитхабе: https://github.com/rmn-lux/mysql-bash-partitioning
Использованные источники
- https://zabbix.org/wiki/Docs/howto/mysql_partitioning#Partitioning_decisions (UPD ссылка на сайте Zabbix изменилась, скачивается лишь документ в формате markdown)
- https://dev.mysql.com/doc/refman/8.0/en/mysqldump-stored-programs.html
- https://blog.zabbix.com/partitioning-a-zabbix-mysql-database-with-perl-or-stored-procedures/13531/?utm_source=Zabbix+email+subscriptions&utm_campaign=3da71c2dc5-Zabbix+Newsletter+February+24%2C+2021_COPY_01&utm_medium=email&utm_term=0_45f3240c47-3da71c2dc5-374469725&mc_cid=3da71c2dc5&mc_eid=8d24acbf7c (UPD новая статья в блоге Zabbix, но по сути тоже самое рассказано, что и в старых статьях)
Спасибо. Статья помогла разобраться в вопросе.