Comment exécuter des tâches récurrentes sur Postgresql sans outil externe semblable à Cron?

41

Je voudrais appeler une procédure stockée sur une base régulière. Sur Oracle, je créerais un travail pour cela. J'ai trouvé que Postgresql pouvait bien imiter cela en utilisant un outil externe (cron, etc.) et PgAgent.

Connaissez-vous une alternative "interne" qui n’impliquerait pas l’outil externe?

  • Je souhaite éviter les problèmes de sécurité liés au mot de passe stocké sur la ligne de commande de pgAgent.
  • Je veux éviter toute configuration système supplémentaire pour cacher le mot de passe ( ~/.pgpass).

Postgresql 8.3
Linux RedHat 64bit

Stephan
la source
Pouvez-vous ajouter pourquoi vous ne pouvez pas utiliser pgAgent ou crontab? spécifiquement quelles sont les fonctionnalités manquantes ..
WrinkleFree
@ Rohan j'ai mis à jour ma question
Stephan
Le message semble avoir été copié et collé sur stackoverflow.com/q/16958625/398670
Craig Ringer le

Réponses:

30

Même si vous utilisiez PostgreSQL 10 ou PostgreSQL 9.6 (qui étaient en train d’être publiés), il n’existait pas encore de planificateur de tâches intégré.

Quelque chose comme PgAgent ou des tâches externes cron est requis, il n’existe pas de solution de rechange pratique.

La fonctionnalité travailleurs d'arrière-plan introduite dans la version 9.3 devrait permettre, espérons-le, de transférer un outil tel que PgAgent dans le noyau de PostgreSQL dans une version ultérieure, mais cela n'a pas encore été fait. Même sur la version 9.3, vous devez toujours exécuter cron ou pgagent.

Quelques personnes travaillent sur des ordonnanceurs basés sur des travailleurs d'arrière-plan, et certains correctifs à venir devraient fournir des installations pour vous aider. Mais depuis PostgreSQL 10, il n’existe toujours pas de planificateur de bonne qualité, largement adopté, et la plupart des gens utilisent le planificateur de tâches cron / ms / etc.

S'il vous plaît jeter un oeil à la politique de version , aussi; vous utilisez une version obsolète et non prise en charge.

Craig Ringer
la source
Please take a look at the version policy, mettre à niveau Postgresql n’est pas une option.
Stephan
3
@ Alex Vous devrez mettre à niveau à un moment donné, et cela ne fera que devenir plus difficile. Au fait, quelle version de 8.3 points? Combien de corrections de bogues importantes vous manque-t-il? Ou êtes-vous au moins sur 8.3.23? Cela dit, comme je l’ai expliqué, la fonctionnalité que vous souhaitez n’existe pas, même dans la version 9.3 à venir, bien que les bases nécessaires pour permettre son ajout aient été ajoutées.
Craig Ringer
Je vais avoir une conversation avec mon patron :)
Stephan
1
@ Alex Bonne idée :-). Au minimum, effectuez une mise à jour urgente vers la version 8.3.23, puis commencez à travailler sur les plans de mise à niveau vers une version plus récente. Cela ne résoudra pas le problème, mais c’est une très bonne idée de sauver la douleur future. Le nombre de clients que je supporte et qui ont des problèmes qu’ils n’auraient jamais rencontrés s’ils restaient au courant est incroyable. Nous ne publions pas de nouvelles versions juste pour le plaisir ;-). Lisez les notes de publication de chaque version .0 pour obtenir des conseils sur les problèmes à résoudre, ainsi que le manuel de mise à niveau. Vos seuls points de douleur probables sont standard_conforming_stringset bytea_output.
Craig Ringer
Craig, que penses-tu de pg_cron?
mehmet
21

A partir de PostgreSQL 9.5, vous pouvez utiliser l' extension pg_cron , chargée en tant que bibliothèque partagée dans PostgreSQL.

Après l’avoir configuré, créer un travail est assez simple:

SELECT cron.schedule('30 3 * * 6', $$DELETE FROM events WHERE event_time < now() - interval '1 week'$$);

Cela exécutera la commande delete en fonction de la planification cron spécifiée. Vous pouvez également utiliser @rebootpour planifier un travail lorsque le serveur redémarre, et pg_cron commencera automatiquement à exécuter les travaux si vous promouvez une mise en veille automatique.

Au lieu d'utiliser .pgpass, vous pouvez fournir un accès localhost à l'utilisateur cron dans pg_hba.conf.

Marco Slot
la source
-1

Vous ne voulez vraiment pas vraiment faire ça. Postgres n'est pas un système d'exploitation, c'est un serveur de base de données. Même si la base de données prend en charge l'exécution de tâches planifiées, ce n'est pas vraiment une bonne idée d'abuser de la base de données.

Si votre préoccupation est que vous ne voulez pas configurer de mot de passe et de contenu, c'est facile à résoudre. Configurez une connexion de socket Unix locale en utilisant plutôt une authentification trust ou ident , exécutez votre travail cron en tant qu'utilisateur.

Dans sa configuration prête postgresà l'emploi , postgres configure généralement l'utilisateur système pour qu'il exécute le serveur de base de données. Cet utilisateur système est généralement déjà préconfiguré afin de pouvoir se connecter au serveur local à l'aide d'une authentification sécurisée lors d'une connexion via un socket Unix local. Vous pouvez exécuter votre cronjob en tant qu'utilisateur système postgres, vous connecter au socket local, puis changer de rôle si vous ne souhaitez pas que votre procédure stockée s'exécute avec le privilège de superutilisateur.

Dans la configuration par défaut, vous pouvez simplement faire ceci:

$ sudo -u postgres crontab -e

Dans l'éditeur, ajoutez à l'entrée de la crontab comme suit:

0    0    *     *    * bash /path/to/run_stored_procedure.sh

et dans votre fichier /path/to/run_stored_procedure.sh, il vous suffit d'utiliser psql pour appeler la procédure de votre magasin.

#!/usr/bin/env bash
psql my_db_name <<END
    SET ROLE limited_user;
    SELECT my_stored_proc();
    SELECT 1 FROM my_stored_proc();
END
Lie Ryan
la source
1
"Ce n'est pas vraiment une bonne idée d'abuser de la base de données de la sorte" Pourquoi pensez-vous qu'il s'agit d'abus? Les différents SGBDR traditionnels ont généralement des approches similaires, et je ne pense pas que ce soit si terrible. De plus, si vous n'avez pas accès au système d'exploitation, crontab vous manque.
dezso