Aller au contenu
Réussir mon BTS SIO

Tape une notion, une commande ou le nom d'une épreuve.

Par exemple

Chapitre 1013 minAvancé

Événement planifié MySQL : CREATE EVENT et event_scheduler

Par Josselyn C., prof de BTS SIO. Mis à jour le .

À la fin de ce chapitre, tu sauras

  • vérifier que le planificateur d'événements tourne ;
  • créer un événement ponctuel ou récurrent ;
  • surveiller, désactiver et supprimer un événement ;
  • choisir entre un événement MySQL et une tâche cron.

4 exercices corrigés

Un événement MySQL est un programme stocké que le serveur exécute tout seul à une date précise ou à intervalle régulier, sans qu'aucun client soit connecté : c'est une tâche planifiée interne à la base, comme une ligne de cron. On le crée avec CREATE EVENT … ON SCHEDULE … DO …, et il est exécuté par le planificateur d'événements (event_scheduler). Ce chapitre l'utilise pour purger les traces anciennes et calculer des statistiques mensuelles sur la base parc.

Le planificateur d'événements

Les événements sont lancés par un processus du serveur, le planificateur, réglé par la variable event_scheduler :

sql
SHOW VARIABLES LIKE 'event_scheduler';   -- ON
ValeurEffet
ONLe planificateur tourne et exécute les événements. Valeur par défaut de MySQL 8.4
OFFArrêté : aucun événement ne s'exécute. Se change à chaud avec SET GLOBAL event_scheduler = ON;
DISABLEDDésactivé au démarrage du serveur : ne peut pas être changé sans redémarrer

Quand il tourne, le planificateur apparaît dans SHOW PROCESSLIST comme un utilisateur event_scheduler, avec l'état Waiting for next activation.

CREATE EVENT

sql
CREATE EVENT [IF NOT EXISTS] nom_evenement
  ON SCHEDULE { AT horodatage | EVERY intervalle [STARTS horodatage] [ENDS horodatage] }
  [ON COMPLETION [NOT] PRESERVE]
  [ENABLE | DISABLE | DISABLE ON REPLICA]
  [COMMENT 'texte']
  DO instruction;   -- ou un bloc BEGIN … END
  • AT : une seule exécution, à la date donnée. AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR : dans une heure.
  • EVERY : une exécution récurrente, EVERY 1 DAY, EVERY 1 MONTH, EVERY 15 MINUTE… STARTS fixe la première exécution (donc l'heure des suivantes), ENDS la dernière possible.
  • ON COMPLETION NOT PRESERVE (par défaut) : un événement terminé (le AT passé, ou le ENDS atteint) est supprimé automatiquement. PRESERVE le garde, désactivé, pour garder la trace de sa définition.
  • DISABLE ON REPLICA : sur un serveur répliqué, l'événement ne s'exécute que sur le serveur source, pas sur les copies, qui reçoivent déjà ses effets par la réplication.

Créer un événement demande le privilège EVENT sur la base. Comme un trigger, un événement s'exécute avec les droits de son propriétaire (DEFINER), dans une connexion qui lui est propre : les variables de session d'un client n'y existent pas.

Purger les traces anciennes

Les tables d'audit du chapitre 9 grandissent sans fin, et elles contiennent des données personnelles : le RGPD impose une durée de conservation, que Sorbier Logistique fixe à un an. Chaque nuit à 3 heures, un événement supprime les traces plus anciennes :

sql
DELIMITER //
CREATE EVENT ev_purge_audit
  ON SCHEDULE EVERY 1 DAY STARTS '2026-11-09 03:00:00'
  COMMENT 'Durée de conservation des traces : 1 an'
  DO
  BEGIN
    DELETE FROM audit_ticket           WHERE modifie_le < NOW() - INTERVAL 1 YEAR;
    DELETE FROM historique_affectation WHERE modifie_le < NOW() - INTERVAL 1 YEAR;
  END //
DELIMITER ;

Le corps d'un événement suit les règles d'une procédure : BEGIN … END, variables, conditions, gestionnaires d'erreurs, et donc DELIMITER dans le client mysql. La durée de conservation choisie se documente dans le registre des traitements : c'est elle qu'un contrôle de la CNIL demanderait.

Calculer des statistiques chaque mois

Le responsable veut, chaque mois, le nombre de tickets ouverts, de tickets résolus et le temps passé du mois précédent. Le calcul va dans une procédure, que l'événement appelle : la procédure se teste et se rejoue à la main, l'événement ne fait que la planifier. Les chiffres affichés supposent la base remise à zéro au début du chapitre (voir L'essentiel) : une intervention ajoutée en essayant les exemples d'un chapitre précédent les change.

sql
DELIMITER //
CREATE PROCEDURE calculer_stat_mois(IN p_debut DATE)
BEGIN
  DECLARE v_fin DATE DEFAULT p_debut + INTERVAL 1 MONTH;

  REPLACE INTO stat_mensuelle (mois, nb_ouverts, nb_resolus, minutes_passees, calcule_le)
  SELECT DATE_FORMAT(p_debut, '%Y-%m'),
         (SELECT COUNT(*) FROM ticket
           WHERE date_ouverture >= p_debut AND date_ouverture < v_fin),
         (SELECT COUNT(*) FROM ticket
           WHERE date_cloture >= p_debut AND date_cloture < v_fin),
         (SELECT COALESCE(SUM(duree_min), 0) FROM intervention
           WHERE date_intervention >= p_debut AND date_intervention < v_fin),
         NOW();
END //
DELIMITER ;

CALL calculer_stat_mois('2026-09-01');
CALL calculer_stat_mois('2026-10-01');
SELECT mois, nb_ouverts, nb_resolus, minutes_passees FROM stat_mensuelle ORDER BY mois;
moisnb_ouvertsnb_resolusminutes_passees
2026-0964370
2026-1073825

REPLACE INTO remplace la ligne du mois si elle existe déjà (même clé primaire) : rejouer le calcul ne crée pas de doublon. Les bornes >= début et < fin comptent chaque date une fois, quelle que soit l'heure. L'événement, le 1er de chaque mois à 1 heure :

sql
CREATE EVENT ev_stat_mensuelle
  ON SCHEDULE EVERY 1 MONTH STARTS '2026-12-01 01:00:00'
  COMMENT 'Indicateurs du mois précédent'
  DO CALL calculer_stat_mois(DATE_FORMAT(CURDATE() - INTERVAL 1 MONTH, '%Y-%m-01'));

Le 1er décembre 2026, CURDATE() - INTERVAL 1 MONTH donne le 1er novembre, et DATE_FORMAT(…, '%Y-%m-01') le premier jour de ce mois : la procédure calcule novembre. Un corps d'une seule instruction n'a pas besoin de DELIMITER.

Un événement ponctuel, pour finir : relever la priorité du ticket 14 dans une heure s'il n'est toujours pas traité.

sql
CREATE EVENT ev_rappel_ticket_14
  ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR
  DO UPDATE ticket SET priorite = 'haute' WHERE id_ticket = 14 AND statut = 'ouvert';

Après son exécution, il disparaît (ON COMPLETION NOT PRESERVE).

Surveiller, modifier, supprimer

sql
SHOW EVENTS FROM parc;

SELECT event_name, status, event_type, interval_value, interval_field, starts, last_executed
FROM information_schema.events
WHERE event_schema = 'parc'
ORDER BY event_name;
EVENT_NAMESTATUSEVENT_TYPEINTERVAL_VALUEINTERVAL_FIELDSTARTSLAST_EXECUTED
ev_purge_auditENABLEDRECURRING1DAY2026-11-09 03:00:00NULL
ev_rappel_ticket_14ENABLEDONE TIMENULLNULLNULLNULL
ev_stat_mensuelleENABLEDRECURRING1MONTH2026-12-01 01:00:00NULL

LAST_EXECUTED vaut NULL tant que l'événement n'a jamais tourné : c'est la colonne à surveiller. Pour modifier un événement, ALTER EVENT accepte toutes les clauses de CREATE EVENT :

sql
ALTER EVENT ev_purge_audit DISABLE;                                    -- suspendre
ALTER EVENT ev_purge_audit ENABLE;                                     -- reprendre
ALTER EVENT ev_purge_audit ON SCHEDULE EVERY 1 DAY STARTS '2026-11-09 04:00:00';
DROP EVENT IF EXISTS ev_rappel_ticket_14;

Événement MySQL ou tâche cron ?

Événement MySQLTâche cron (ou Planificateur de tâches Windows)
Où vit la tâcheDans la base : sauvegardée et restaurée avec elleSur un serveur, dans la table crontab d'un compte
Ce qu'elle peut faireDu SQL seulementN'importe quel programme : script, sauvegarde, envoi de courriel
AccèsAucun mot de passe à stockerUn compte MySQL et son mot de passe dans un fichier de configuration
Suivi des erreursJournal d'erreurs du serveur MySQLSortie du script, courriel de cron, journaux système

Un événement convient à une tâche purement SQL sur la base : purge, statistiques, archivage d'une table dans une autre. Une sauvegarde avec mysqldump, un export de fichier ou une tâche qui touche d'autres serveurs reste une tâche cron (automatiser les sauvegardes ; planifier une tâche sous Linux).

Exercices

Exercice 1 sur 4 Purger le journal des erreurs Réussi À revoir

Écris un événement ev_purge_erreurs qui supprime chaque dimanche à 2 heures les lignes de journal_erreur de plus de 90 jours, à partir du dimanche 15 novembre 2026. Comment vérifies-tu ensuite qu'il est bien planifié ?

Voir la réponseMasquer la réponse de l'exercice 1
sql
CREATE EVENT ev_purge_erreurs
  ON SCHEDULE EVERY 1 WEEK STARTS '2026-11-15 02:00:00'
  COMMENT 'Conservation des erreurs : 90 jours'
  DO DELETE FROM journal_erreur WHERE survenue_le < NOW() - INTERVAL 90 DAY;

EVERY 1 WEEK à partir d'un dimanche à 2 heures donne tous les dimanches à 2 heures. Pour vérifier : SHOW VARIABLES LIKE 'event_scheduler'; doit répondre ON, et SELECT status, starts FROM information_schema.events WHERE event_name = 'ev_purge_erreurs'; doit montrer ENABLED et la bonne date. Après le premier dimanche, last_executed doit être renseigné.

Tu avais trouvé ?

Exercice 2 sur 4 Relancer chaque lundi Réussi À revoir

Planifie la procédure relancer_tickets du chapitre 5 pour qu'elle s'exécute chaque lundi à 7 heures, sur les tickets ouverts depuis plus de 14 jours, à partir du lundi 9 novembre 2026. La procédure a un paramètre OUT : comment l'appeler dans un événement ?

Voir la réponseMasquer la réponse de l'exercice 2
sql
CREATE EVENT ev_relance_hebdo
  ON SCHEDULE EVERY 1 WEEK STARTS '2026-11-09 07:00:00'
  DO CALL relancer_tickets(NOW(), 14, @nb_relances);

Un paramètre OUT demande une variable : une variable de session @nb_relances convient. Elle appartient à la connexion de l'événement et disparaît avec elle, ce qui est sans conséquence ici. Pour garder le nombre de relances, la procédure (ou un bloc BEGIN … END dans l'événement) l'écrirait dans une table.

Tu avais trouvé ?

Exercice 3 sur 4 L'événement qui ne fait rien Réussi À revoir

Un stagiaire a créé cet événement sur un serveur MariaDB 11.4 le 10 novembre 2026 à 14 heures. Le lendemain, rien ne s'est passé et l'événement a disparu. Donne deux causes possibles.

sql
CREATE EVENT ev_archive
  ON SCHEDULE AT '2026-11-10 13:00:00'
  DO INSERT INTO ticket_archive SELECT * FROM ticket WHERE statut = 'resolu';
Voir la réponseMasquer la réponse de l'exercice 3
  1. La date est déjà passée au moment de la création (13 h, alors qu'il est 14 h). Le serveur accepte l'instruction avec une simple note (1588, Event execution time is in the past and ON COMPLETION NOT PRESERVE is set. The event was dropped immediately after creation.) : l'événement est supprimé aussitôt, sans s'exécuter. C'est pourquoi il a « disparu ».
  2. Le planificateur est arrêté : sur MariaDB, event_scheduler vaut OFF par défaut. Même avec une date future, l'événement ne se serait pas exécuté.

On peut ajouter que la table ticket_archive doit exister et avoir les mêmes colonnes que ticket, et qu'un archivage digne de ce nom supprimerait ensuite les tickets copiés, dans une transaction, ce qui demande une procédure.

Tu avais trouvé ?

Exercice 4 sur 4 Événement ou cron ? Réussi À revoir

Pour chaque tâche, choisis un événement MySQL ou une tâche cron, et justifie en une phrase : (1) une sauvegarde quotidienne de la base parc copiée sur le NAS ; (2) la clôture automatique des tickets résolus depuis plus de 30 jours ; (3) l'envoi par courriel du rapport mensuel ; (4) la mise à jour chaque heure d'une table de synthèse des licences.

Voir la réponseMasquer la réponse de l'exercice 4
  1. cron : mysqldump est un programme externe, et la copie vers le NAS touche un autre serveur.
  2. Événement : une requête SQL sur la base, sans rien d'extérieur. (Dans parc, un ticket résolu est déjà clos : la tâche serait plutôt l'archivage des tickets résolus.)
  3. cron : MySQL ne sait pas envoyer de courriel. Le script lit les chiffres, éventuellement calculés par un événement dans stat_mensuelle, et envoie le message.
  4. Événement : du SQL pur, qui vit avec la base.

Tu avais trouvé ?

Chapitre terminé !

Fais les 4 exercices avant de passer à la suite : c'est en t'entraînant que tout se fixe.

chapitres
–
de série
–
du cours
–
Chapitre suivant : Sécurité : DEFINER, INVOKER, droit EXECUTE et SQL dynamiqueRevoir le sommaire du cours