Triggers & scheduled events
BEFORE/AFTER triggers with NEW and OLD, audit logs, SIGNAL, and the event scheduler.
Procedures and functions run when you call them. Two other kinds of stored program run automatically:
- Triggers fire when rows are inserted, updated or deleted in a table.
- Events fire on a schedule, like a cron job inside MySQL.
Sample tables#
Trigger anatomy#
- Timing:
BEFOREtriggers run before the row is written, so they can validate or change it.AFTERtriggers run once the row has been written, which makes them good for logging and keeping other tables in sync. - Event:
INSERT,UPDATEorDELETE(includingLOAD DATAandREPLACE, which insert and delete rows). FOR EACH ROW: the body runs once per affected row. AnUPDATEtouching 1,000 rows fires 1,000 times.NEW.colis the new row (INSERT, UPDATE) andOLD.colis the old row (UPDATE, DELETE).
BEFORE triggers: fix up and validate data#
SET NEW.slug = ... changed the row before it was stored, and SIGNAL rejected the invalid one. For simple rules like "price > 0", a CHECK constraint is clearer. Use triggers for logic that constraints can't express.
AFTER triggers: an audit log#
Record every price change, including who made it:
<=> is the null-safe comparison, so the check also works when a price is NULL. FROM DUAL is a dummy table that lets the INSERT ... SELECT carry a WHERE.
Keeping a summary in sync#
Triggers can maintain denormalised data, such as a running count:
A trigger runs inside the same transaction as the statement that fired it. If the trigger fails, the whole statement fails and, on InnoDB, its changes are rolled back, so the count can't drift out of sync.
Managing triggers#
Since MySQL 5.7 you can have several triggers for the same timing and event. Order them with FOLLOWS other_trigger or PRECEDES other_trigger.
Trigger cautions
- Invisible logic. Developers reading
INSERT INTO reviewswon't know it also updatesproducts. Document triggers and keep them small. - Performance. Per-row execution slows down bulk operations.
- Restrictions. A trigger can't modify the table it's defined on (use
SET NEW.colin aBEFOREtrigger instead), can'tCOMMIT/ROLLBACK, and can't return result sets. - Foreign-key cascades don't fire triggers on the child table.
Events: scheduled jobs#
The event scheduler runs SQL at fixed times or intervals. It's ON by default in MySQL 8:
(Turn it on with SET GLOBAL event_scheduler = ON; or event_scheduler=ON in my.cnf.)
A recurring event purges old log rows every night:
A one-off event runs once and is then dropped (unless you add ON COMPLETION PRESERVE):
Events can call procedures and use BEGIN ... END bodies (with DELIMITER) for several statements. A typical pattern is rebuilding a reporting table every hour:
Manage events with:
Event tips
- Events run as their definer, in the server's time zone. Check
@@global.time_zonewhen pickingSTARTStimes. - Errors are written to the server error log, not to any client, so log progress to a table if a job matters.
- Big deletes should run in batches (
DELETE ... LIMIT 10000in a loop) to avoid long locks and replication lag. - On replicas, replicated events are disabled (status
REPLICA_SIDE_DISABLED, orSLAVESIDE_DISABLEDon older versions) so they don't run twice. - Events vs cron: events need no extra infrastructure and are backed up with the database. For jobs that span systems or need alerting, an external scheduler (cron, systemd timers, your job runner) is usually better.
What's next#
Your database now does real work on its own. Time to lock it down: users, privileges and security.
Check your understanding
Quick quiz
1.Inside an UPDATE trigger, how do you refer to a column's value before and after the change?
2.You want to reject an invalid row with a custom error message from a trigger. What do you use?
3.What must be ON for scheduled events to run?
Finished reading?
Mark this lesson complete to track your progress.