Використання MySQL events для запуску SQL-процедур за розкладом

Ви можете запускати деякі дії в MySQL за розкладом. Головна перевага порівняно з можливостями фреймворку полягає в тому, що ви не будете обмежені лімітами PHP.

Розглянемо приклад. Ми будемо використовувати MySQL для архівування замовлень, виконаних більше місяця тому.

Існують таблиці, пов’язані як many-to-many:

  • orders
  • products
  • order_product (the pivot table)

Також є табліця «payments».

Архівувати записи ми будемо у таблиці

  • archive_orders
  • archive_order_product
  • archive_payments

Спочатку ми створюємо процедуру move_orders_to_archive:

CREATE PROCEDURE IF NOT EXISTS move_orders_to_archive()
BEGIN
DECLARE n int default 0;

UPDATE `orders` SET `status`='archived' WHERE `status`='completed' 
AND `updated_at` <= DATE_ADD(Now(), INTERVAL -1 MONTH);

SET n = ROW_COUNT();
IF n > 0 THEN
   INSERT IGNORE INTO `archive_orders` SELECT * FROM `orders` 
   WHERE `status`='archived';

   INSERT IGNORE INTO `archive_order_product` 
   SELECT `order_product`.* 
     FROM `order_product`
     INNER JOIN `orders` on (`order_product`.`order_id`=`orders`.`id`)
   WHERE `orders`.`status`='archived';

   INSERT IGNORE INTO `archive_payments` 
   SELECT `payments`.* 
     FROM `payments`
     INNER JOIN orders on (`payments`.`order_id`=`orders`.`id`)
   WHERE `orders`.`status`='archived';

   DELETE `payments`.* FROM `payments`
     INNER JOIN `orders` on (`payments`.`order_id`=`orders`.`id`)
   WHERE orders.status='archived';

   DELETE `order_product`.* FROM `order_product`
     INNER JOIN `orders` on (`order_product`.`order_id`=`orders`.`id`)
   WHERE `orders`.`status`='archived';

   DELETE FROM `orders`
   WHERE `status`='archived';
END IF; 
END

Зверніть увагу: потенційно довгі запити йдуть один за одним. PHP був би змушений чекати і, можливо, не отримав би відповідь на запит.

Ми мусимо увімкнути MySQL Scheduler:

SET GLOBAL event_scheduler = ON

Тепер ми можемо створювати event:

CREATE EVENT archiving
ON SCHEDULE
EVERY 1 DAY STARTS '2026–07–26 01:00:00'
    COMMENT 'Archive orders completed more than a month ago'
    DO CALL move_orders_to_archive();

Ось і все! Тепер щодня о 1 годині ночі замовлення будуть архівуватися.

Підписуйтеся на Telegram-канал «DOU #tech», щоб не пропустити нові технічні статті

👍ПодобаєтьсяСподобалось1
До обраногоВ обраному1
LinkedIn
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

Читав про це у книжці, ніколи не бачив на практиці, дякую, цікаво

Краще так не робити, у вас має бути сепарація консернів. В даному випадку ви робите базу single point of failure

==В даному випадку ви робите базу single point of failure==

Навіть якщо в цій простій процедурі щось піде не так — хіба це позначиться якось на роботі системи?