Auf Datenbankveränderungen reagieren

Heute ist Stammtischzeit:
Jeden Donnerstag 20:30 Uhr hier im Chat.
Wer Lust hat, kann sich gerne beteiligen. ;)
  • Hallo,
    ich würde gern auf meinem Pi ein Script ausführen, welches bei Hinzufügung einer Zeile in eine Tabelle meiner Datenbank ein anderes Script ausführt.

    Da ich leider noch keine Erfahrungen in Sachen Programmierung auf dem Pi gesammelt habe würde ich gern mal wissen, wie man so etwas in Angriff nimmt.

    Hoffe ihr könnt mich da ein wenig unterstützen :D

    • Offizieller Beitrag

    Hi,

    welche Datenbank benutzt du denn?

    Theoretisch reicht es wenn du dir ein kleines Bash Script erstellst, wo du einfach nur einen Select auf deiner Tabelle ausführst (SELECT count(IRGENDEINESPALTE) FROM TABELLE; )
    Dadurch wird jeder eintrag gezählt und diesen könntest du dann wegspeichern (zbs in eine eigene Datei)
    und danach kannst du jederzeit die beiben Zahlen vergleichen und ggf etwas machen wenn eine differenz vorhanden ist ;)

    liebe Grüße
    Turael

    Ich bin ein gefallener Engel namens Turael.

    Einst vor langer Zeit rebelierte ich im Himmel bis Gott mich auf die Erde verbannte.

    Doch meine taten werden kein ende finden....

    Einmal editiert, zuletzt von Turael (16. November 2013 um 22:11)


  • ... einer Zeile in eine Tabelle meiner Datenbank ein anderes Script ausführt.


    Evtl. kannst Du das mit iwatch machen.

    The most popular websites without IPv6 in Germany.  IPv6-Ausreden

    Meine PIs

    PI4B/8GB (border device) OpenBSD 7.4 (64bit): SSH-Server, WireGuard-Server, ircd-hybrid-Server, stunnel-Proxy, Mumble-Server

    PI3B+ FreeBSD 14.0-R-p3 (arm64): SSH-Serv., WireGuard-Serv., ircd-hybrid-Serv., stunnel-Proxy, Mumble-Serv., ddclient

    PI4B/4GB Bullseye-lite (64bit; modifiziert): SSH-Server, WireGuard-Server, ircd-hybrid-Server, stunnel-Proxy, Mumble-Server, botamusique, ample

    Einmal editiert, zuletzt von rpi444 (16. November 2013 um 22:14)


  • ...
    ich würde gern auf meinem Pi ein Script ausführen, welches bei Hinzufügung einer Zeile in eine Tabelle meiner Datenbank ein anderes Script ausführt.

    Da ich leider noch keine Erfahrungen in Sachen Programmierung auf dem Pi gesammelt habe ...


    Hallo auch,

    zunächst mal ist das sicherlich keine Pi-spezifische Sache sondern wenn, dann eine DB-spezifische.

    Und da fehlen einige Infos:

    Wo läuft die DB ?
    Kann man vom RPi darauf zugreifen ?
    Was ist das für eine Datenbank (Oracle, MySQL, Postgres ...) ?

    salü,
    -ds-

  • Okay, danke erstmal. Wie führe ich denn über einen Trigger ein anderes Script aus? Ich möchte dann mit "python yowsup-cli -c config.example -s 49123456789 'Test'" eine Nachricht mit dem Inhalt der neuen Zeile per Whatsapp an mich senden. Das Pythonscript funktioniert aktuell einwandfrei.

    EDIT:
    Aktueller Quelltext des Triggers:

    Code
    CREATE TRIGGER WhatsApp AFTER INSERT ON kennungen
    FOR EACH ROW
    BEGIN
     IF NEW.kennung == 66395 OR 66392 THEN

    Einmal editiert, zuletzt von Keano (16. November 2013 um 23:37)

  • Hi,

    ne, da kannst Du keinen script aufrufen. Aber Du kannst einen Eintrag in eine eigene Tabelle machen, das nur ein Timestamp-Feld der letzten Änderung enthält. Jetzt brauchst Du nur noch - per PHP oder Python oder whatever zyklisch dieses Feld abfragen und nachschauen ob sich der Wert verändert hat.

    cheers,
    -ds-


  • ne, da kannst Du keinen script aufrufen. Aber Du kannst einen Eintrag in eine eigene Tabelle machen, das nur ein Timestamp-Feld der letzten Änderung enthält. Jetzt brauchst Du nur noch - per PHP oder Python oder whatever zyklisch dieses Feld abfragen und nachschauen ob sich der Wert verändert hat.

    Genau, so ähnlich würde ich das auch machen...

    Du fügst deinem Datensatz eine Spalte time mit TIMESTAMP hinzu und lässt dann ein anderes Script über crontab jede Minute ausführen was dann prüft ob der UNIX_TIMESTAMP nicht älter als zB 60 Sekunden ist...
    Zum Beispiel:

    SQL
    SELECT * FROM tabelle WHERE time > UNIX_TIMESTAMP()-60;

    Unixtime beziffert die Millisekunden die seit dem 1.1.1970 vergangen sind (globaler Standard)
    In PHP liefert das:

    PHP
    time();[/php] oder in SQL:
    [code]NOW()
  • Ok, ich habe dann mal eine Tabelle namens "KennungTimeStamp" die eine Zeile mit id=1, in der der neue Timestamp geschrieben wird und eine id=2 in der der vorherige Timestamp geschrieben wurde. Ich habe dann mal das Script mit PHP angefangen:

    Wie kann ich das Script außerhalb einer Website überhaupt starten? Und wie kann ich einen zyklischen Neustart des Scripts realisieren?

    Einmal editiert, zuletzt von Keano (17. November 2013 um 00:09)


  • Wie kann ich das Script außerhalb einer Website überhaupt starten? Und wie kann ich einen zyklischen Neustart des Scripts realisieren?

    Wenn das Paket php-cli installiert ist kannst du php über die Konsole ausführen..

    2 Möglichkeiten:

    • minimal jede Minute über crontab
    • Über ein bash Script welches sich durch eine while Schleife auch im 0.1 Sekunden Takt im Kreis drehen kann..


    Zu 1.: Siehe crontab .. entsprechender Befehl den du über Crontab ausführst wäre php -f /path/to/script.php

    Zu 2.:

    Bash
    #!/bin/bash
    while :; do
      php -f /path/to/script.php
      sleep 0.5
    done


    Das würde sich alle 500 millisekunden (0.5 Sekunden) wiederholen..
    Allerdings müsst du das bash Script in einem screen laufen lassen damit es permanent weiter läuft - das setzt das Paket screen vorraus und führst es am besten dann so aus:

    Code
    screen -dmS test /path/to/script.sh


    ..das würde eine screen Session namens "test" starten und dadrin läuft das bash Script.. In die Session kommst du nachträglich über den Befehl screen -r test

  • Ok, das werde ich heute mal ausprobieren. Ich habe aber aktuell ein Problem beim Anlegen des Triggers.

    Code
    CREATE TRIGGER WhatsApp AFTER INSERT ON kennungen
    FOR EACH ROW
    BEGIN
     IF NEW.kennung == 66392 THEN
     UPDATE KennungTimeStamp SET uhrzeit = UNIX_TIMESTAMP() WHERE id =1;
     END IF;
    END;

    Fehlermeldung:

    Code
    #1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '== 66392 THEN
            UPDATE KennungTimeStamp SET uhrzeit = UNIX_TIMESTAMP() WHERE id' at line 4
  • Den Trigger brauchst du nicht da dein Vorhaben in eine andere Richtung geht, was aber vorher nicht beachtet wurde ;)


    Aber nebenbei ' == ' ist falsch, änder das in ein einfaches ' = '

  • Okay, aber ich hätte das jetzt so umgesetzt:
    1.Änderung in der Datenbank
    2.Trigger setzt bei bestimmten Änderungen neuen Timestamp
    3.PHP-Script prüft zyklisch, ob eine Änderung des Timestamps vorliegt
    4. Wenn ja, dann führe Script aus

    Das dürfte so doch auch funktionieren, oder?

  • Auch wenn schon eine Lösung gefunden wurde und kurz vor der Vollendung steht, erlaube ich mir trotzdem einen anderen Vorschlag zu machen.

    An der Lösung stören mich die vielen Datenbankzugriffe. Der maximale Vorschlag war alle 0,5 Sekunden. Das sind 172800 Zugriffe am Tag, 63 Millionen im Jahr.
    Auch jede Minute wäre mir für den Pi zu viel. Seine Ressourcen sollten sparsam eingesetzt werden.

    Mein Vorschlag ist einen Trigger zu erstellen, der eine Textdatei erzeugt und in ein Verzeichnis ablegt. Per Cronjob wird dann nachgeschaut, ob dort eine Datei existiert. Die wird dann per Mail verschickt wird oder was weiß ich.
    Für die Überprüfung findet somit überhaupt kein Datenbankzugriff statt und sie wird mit Abschluss der Transaktion erzeugt. Zeitnäher geht es nicht.

    Die Syntax ist hier.

    Die Aufgabenstellung hatten schon viele, daher kann man auch [url=http://forums.mysql.com/read.php?99,33635,170562#msg-170562]Beispiele[/url] finden.

    Keep it simple [,&] stupid

    Einmal editiert, zuletzt von kungel (17. November 2013 um 11:59)

  • Ok, das wäre auch eine Möglichkeit.

    Aber ich habe immer noch Probleme mit dem Trigger:

    Code
    CREATE TRIGGER `WhatsApp` BEFORE UPDATE ON `kennungen`
     FOR EACH ROW BEGIN
       IF (NEW.kennung = '66392') THEN
         UPDATE kennungtimestamp SET uhrzeit = UNIX_TIMESTAMP() WHERE id =1;  
      END IF;
    END

    Fehlermeldung:

    Code
    #1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 4

  • Auch wenn schon eine Lösung gefunden wurde und kurz vor der Vollendung steht, erlaube ich mir trotzdem einen anderen Vorschlag zu machen.

    An der Lösung stören mich die vielen Datenbankzugriffe. Der maximale Vorschlag war alle 0,5 Sekunden. Das sind 172800 Zugriffe am Tag, 63 Millionen im Jahr.
    Auch jede Minute wäre mir für den Pi zu viel. Seine Ressourcen sollten sparsam eingesetzt werden.

    Mein Vorschlag ist einen Trigger zu erstellen, der eine Textdatei erzeugt und in ein Verzeichnis ablegt. Per Cronjob wird dann nachgeschaut, ob dort eine Datei existiert.

    Ob man jetzt auf eine Datenbank zugreift oder auf eine Datei - was davon erzeugt wohl mehr I/O Zugriffe oder verursacht mehr Last :huh:

    Um so niedriger der Timer is um so schneller wird man informiert - i.d.R. reicht aber jede Minute

    Da ich meinen Vorschlag selber laufen habe kann ich den zumindest ein bisschen einschätzen: Ich prüfe jede Minute ob es neue Beiträge/Threads in meinem Forum gibt und wenn ja werden mir entsprechende Informationen im IRC mitgeteilt... Das läuft schon seit mehreren Jahren so - zwar nicht über einen RPI aber ich behaupte mal dass das kaum einen Unterschied macht und nicht als wörtliche "Belastung" wahrgenommen werden werden kann..


    Keano: Vergiss das mit dem Trigger - dazu wurde geraten bevor beachtet wurde das du ein externes Script aufrufen möchtest

    Ich weiss zwar nicht um was für eine Datenbank es sich dabei überhaupt handelt und worüber du über WhatsApp informiert werden willst - aber wie ich bereits erwähnte brauchst du deiner bereits vorhandenen Tabelle nur eine Spalte hinzufügen und dort einfach jedem weiteren Eintrag den unixtimestamp eintragen lassen...

    Das mit dem trigger usw ist in diesem Fall viel zu kompliziert und erzeugt mehr Last als meine Lösung ;) Vorallem aber brauchst du auch keine weitere Tabelle um dort nochmals irgendwas rein zu schreiben, das is eigentlich ebenfals "zu viel"

  • Hi,

    na wenn das mit dem Trigger nix ist, dann nimm eine Stored Procedure.
    Postgre bietet da sogar den Aufruf externer Programm oder Zugriffe auf der Filesystem an.
    Die wird halt dann aus dem Trigger aufgerufen :) ...

    Allerdings weiss ich jetzt nicht, ober das mit MySQL ganeau so funktioniert wie mit Postgre.

    bye,
    -ds-

Jetzt mitmachen!

Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!