Тригер - SQL-код, який MySQL виконує автоматично до чи після INSERT, UPDATE або DELETE для кожного рядка.
DELIMITER //
CREATE TRIGGER orders_audit
AFTER UPDATE ON orders
FOR EACH ROW
BEGIN
IF NOT (OLD.status <=> NEW.status) THEN
INSERT INTO order_status_log (order_id, old_status, new_status, changed_at)
VALUES (NEW.id, OLD.status, NEW.status, NOW());
END IF;
END //
DELIMITER ;
OLD- рядок до зміни (уUPDATEіDELETE),NEW- після (уINSERTіUPDATE);- у тригері
BEFOREможна змінити значення:SET NEW.slug = LOWER(NEW.slug); SIGNAL SQLSTATE '45000'уBEFORE-тригері скасовує операцію з помилкою.
Обмеження MySQL, які варто знати:
- лише рядкові тригери (
FOR EACH ROW) - тригерів рівня оператора, як у PostgreSQL, немає. МасовийUPDATEмільйона рядків - мільйон викликів; - не можна змінювати ту саму таблицю, на яку спрацював тригер (і будь-яку таблицю, яку вже читає оператор, що його викликав) - помилка
Can't update table ... in stored function/trigger; - тригери не спрацьовують на дії зовнішніх ключів:
ON DELETE CASCADEвидалить дочірні рядки без їхніх тригерів; - кілька тригерів на одну подію дозволені, порядок задають
FOLLOWS/PRECEDES; - реплікація: з рядковим форматом бінарного журналу (за замовчуванням) на репліці тригери не виконуються - туди приходять уже готові зміни рядків, включно з тими, що зробив тригер на джерелі. Зі
STATEMENT-форматом тригери виконуються на репліці знову.
Тригер чи подія Eloquent:
| Тригер | Подія моделі Eloquent | |
|---|---|---|
спрацьовує при масовому update(), сирому SQL, зміні з іншого сервісу |
так | ні |
| видно в коді застосунку | ні | так |
| тестування | на справжній базі | звичайними тестами |
| може надіслати лист, поставити завдання в чергу | ні | так |
Підводні камені: невидима логіка (розробник не знає, що UPDATE змінює ще одну таблицю), складність налагодження, додаткові блокування в довгих транзакціях. Тригери мають бути задокументовані, мати зрозумілі назви й створюватися в міграціях (DB::unprepared()), а тести - запускатися на MySQL, а не SQLite.
Правило: у тригерах - інваріанти й аудит, які мають працювати незалежно від того, хто пише в базу; побічні ефекти - у застосунку.