MySQL verhalten bei Verbindungsabbruch

  • Guten Morgen,

    Seit einigen Tagen bastle ich an einen Skript, welches mir aus einer MySQL Datenbank werte ausliest, entsprechend einen GPIO-Pin schaltet und Zustandsänderungen in die Datenbank schreibt.

    kurz zum Ablauf:

    In der Tabelle 1 sind drei werte. wenn diese drei werte gleich sind soll eine LED leichten. Immer wenn die LED an oder aus geht, soll das in Tabelle2 geschrieben werden.

    Zudem ist ein Schalter am Raspberry. Wenn dieser an ist, soll nichts passieren und die LED dauerhaft aus sein. Bei aktivem Schalter soll alle 10 Sekunden ein Eintrag in Tabelle2 geschrieben werden


    Nach ewigem Gefummel funktioniert das jetzt ganz zuverlässig.

    Jetzt suche ich nur noch nach einer Möglichkeit, dass bei einem Verbindungsabbruch nur eine Sekunde gewartet wird und das Skript dann einfach weiter abgearbeitet wird.

    Leider konnte ich bisher noch keine Lösung für mich finden. Oder ich bin zu dämlich das Gefundene richtig in meinen Code zu übertragen :conf: Vielleicht könnt ihr mit ja helfen :)


    :danke_ATDE:

  • Hallo,


    ich verstehe deinen Datenbankentwurf nicht... Warum benutzt du überhaupt ein RDBMS? Für die paar Werte kannst du auch einen einfachen Key-Value Store nehmen, ohne den Overhead von MySQL. Oder du hälst du Daten einfach im Speicher.

    Warum speicherst du, wann ein Taster gedrückt wurde ohne Zeitstempel? Oder wird der automatisch eingefügt? Sonst sind die Werte ja relativ witzlos.


    Zum Code:

    • Eingerückt wird mit 4 Leerzeichen. Immer. Außerdem hast du Einrückungen, wo keine nötig sind.
    • Das neuere, schönere, bessere gpiozero Modul verwenden statt das alte / veraltete RPi.GPIO.
    • Sinnvolle Variablennamen verwenden, auch in der DB. `wert1`, `wert2` etc. sind völlige aussagelos.
    • `SELECT`braucht kein `commit`.
    • wert1, wert2, wert3 kannst du in einem auslesen, drei Queries sind zwei zu viel.
    • Warum definierst du wert 1, 2 und 3 am Ende der Schleife? Diese Werte werden nie benutzt, sondern vom nächsten DB-Query wieder überschrieben.
    • Python kennt den Datentyp `Bool`. Das ist besser als mit 0 und 1 rumzufummeln.
    • Die Datenbankverbindung wird nie geschlossen. Kann ein Problem werden, muss aber nicht.
    • Kommentare sollen _zusätzlich_ Infos zum Quellcode liefern, nichtdas beschreiben, was so wie so offentsichtlich ist. Letzteres ist bei dir der Fall.
    Quote

    Jetzt suche ich nur noch nach einer Möglichkeit, dass bei einem Verbindungsabbruch nur eine Sekunde gewartet wird und das Skript dann einfach weiter abgearbeitet wird.

    Das macht IMHO keine Sinn, weil dein Skript ohne Ergebnisse aus der DB nicht wirklich arbeiten kann.


    Ansonsten wäre das Vorgehen:

    • DB Abfrage in eine Funktion auslagern
    • timeout auf 1 Sekunde setzen
    • Die Funktion in Abhängigkeit vom timeout die DB-Werte oder andere Werte (was auch immer du brauchst) liefern lassen.

    Gruß, noisefloor

  • Quote

    Eingerückt wird mit 4 Leerzeichen. Immer. Außerdem hast du Einrückungen, wo keine nötig sind.

    Danke. In meinen alten Handbüchern habe ich das bisher mit Tab gelernt.


    Quote

    Sinnvolle Variablennamen verwenden, auch in der DB. `wert1`, `wert2` etc. sind völlige aussagelos.

    Ich habe es für das Forum "vereinfacht". Die Tabellen heißen nicht 1,2,3,4. Die Variablen und Spalten auch nicht Wer 1,2,3,4.


    Quote

    wert1, wert2, wert3 kannst du in einem auslesen, drei Queries sind zwei zu viel.

    Das habe ich mit meinem Anfängerwissen versucht, aber nicht hinbekommen. Daher versuche ich es erstmal auf diese Weise.


    Quote

    Warum definierst du wert 1, 2 und 3 am Ende der Schleife? Diese Werte werden nie benutzt, sondern vom nächsten DB-Query wieder überschrieben.

    damit die LED aus geht wen die Verbindung wegbricht. Dann ergibt mein Vorhaben wieder Sinn, dass das Skript dann einfach weiter läuft.


    Quote

    Kommentare sollen _zusätzlich_ Infos zum Quellcode liefern, nichtdas beschreiben, was so wie so offentsichtlich ist. Letzteres ist bei dir der Fall.

    Die Kommentare sollen auch mir selbst helfen. Für einen Programmierer ist der Quellcode vielleicht offensichtlich und mein Kommentar überflüssig. Für mich jedoch nicht.

    Quote

    Die Datenbankverbindung wird nie geschlossen. Kann ein Problem werden, muss aber nicht.

    Vielen Dank für den Hinweis. Darum kann ich mich danach dann noch kümmern :)



    Ich bin kein Programmierer ;). Ich bastle gerne und probiere rum. Für einen gelernten Programmiere ist das wahrscheinlich Säure in den Augen. Es gibt garantiert bessere Möglichkeiten. Die sich mir nur meist zu hoch :(



    Quote

    timeout auf 1 Sekunde setzen

    Genau. Aber wie? Den Satz habe ich in vielen Foren gelesen. Aber ich weiß nicht wie das im Code umgesetzt wird.;(

  • Hallo,


    Quote

    Genau. Aber wie? Den Satz habe ich in vielen Foren gelesen.

    Du musst in der Doku des mysql.connector Moduls halt mal suchen / lesen, ob es ein `timeout`Parameter gibt. Sollte eigentlich.


    Warum benutzt du eigentlich MySQL? Läuft die DB auf einem Server außerhalb des Pis? Brauchst du Netzwerkfähigkeit? Wenn nein -> nimm' SQLite.


    Quote

    Ich bin kein Programmierer

    Ich auch nicht. Abgesehen davon ist das mehr eine Frage des Anspruchs als der Berufs. Zumal es auch berufliche Programmierer gibt, die "suboptimal" programieren.


    Gruß, noisefloor

  • Ja, ich brauche die Netzwerkfähigkeit. Die Datenbank läuft auf einem externen Server. Dieser befindet sich auch nicht im selben Netzwerk wie der Raspberry.

  • in vielen Foren habe ich was über Connection_timeout, read_timeout und write_timeout gelesen. nur leider nirgends wie ich das unterbringe.

    Ich habe es aktuell bei der Connection zu stehen. Am Verständlichsten fand ich diese Seite:

    https://pymysql.readthedocs.io…/modules/connections.html


    Code
    connection = pymysql.connect(
        host='****',
        user='****',
        password='****',
        db='****',
        read_timeout=100,
        write_timeout=100
        )

    Ich bekomme so entweder Syntaxfehler oder es hat einfach keinen Effekt. Ich habe die unterschiedlichsten Schreibweisen probiert.

    Code
    read_timeout=100,
    read_timeout='100',
    read_timeout="100",
    read_timeout=`100`,

    Da ich auch nicht herausbekommen habe, ob der Wert in Sekunden oder Millisekunden definiert ist habe ich von 1 - 1000 alles ausprobiert.

    Die Bibliothek habe ich auch gewechselt von mysql.connector zu PyMySQL. Und auch mit Python3 habe ich es versucht. Ohne Erfolg.

  • Hallo,


    Quote

    Ich habe die unterschiedlichsten Schreibweisen probiert.

    Programmieren ist halt nicht raten.


    Quote

    Da ich auch nicht herausbekommen habe, ob der Wert in Sekunden oder Millisekunden definiert

    Es steht wörtlich in der von dir verlinkten Doku, dass es Sekunden sind.


    Quote


    Die Bibliothek habe ich auch gewechselt von mysql.connector zu PyMySQL.

    Dir ist klar, dass das 2 Paar Schuhe, also 2 verschiedene Module sind? Wenn du versuchst, du Parameter von PyMySQL bei mysql.connector anzuwenden, ist die Chance auf einen Fehler hoch, weil mysql.connector ziemlich sicher andere Parameter kennt.


    Bei PyMySQL musst du den `connect_timeout`setzen, nicht die `read_timeout`oder `write_timeout`. Du wolltest ja auch drauf reagieren, wenn die _Verbindung_ nicht zustande kommt - und nicht, wenn du verbunden ist, aber Daten nicht gelegen oder geschrieben werden.

    `connect_timeout`wirft dann eine Exception, die du abfangen und entsprechend reagieren kannst. Ist auch in der von dir verlinkten Doku erklärt.


    Gruß, noisefloor

  • Code
    Dir ist klar, dass das 2 Paar Schuhe, also 2 verschiedene Module sind? Wenn du versuchst, du Parameter von PyMySQL bei mysql.connector anzuwenden, ist die Chance auf einen Fehler hoch, weil mysql.connector ziemlich sicher andere Parameter kennt.

    Ja. Darum habe ich gestern auch den ganzen Tag damit verbracht es umzuschreiben.


    Code
    Es steht wörtlich in der von dir verlinkten Doku, dass es Sekunden sind.

    Ist richtig, auf anderen Seiten stand aber wieder Millisekunden.


    Code
    Programmieren ist halt nicht raten.

    Zum Lernen muss ich aber probieren ;) Einfach machen und schauen was passiert, in der Hoffnung, dass etwas passiert.


    Code
    Bei PyMySQL musst du den `connect_timeout`setzen, nicht die `read_timeout`oder `write_timeout`. Du wolltest ja auch drauf reagieren, wenn die _Verbindung_ nicht zustande kommt - und nicht, wenn du verbunden ist, aber Daten nicht gelegen oder geschrieben werden.

    Doch, beides :) Du hast ja am Anfang schon festgestellt, dass die Verbindung in meinem Fall nicht geschlossen wird. Sie wird bei Programmstart einmal aufgebaut und bleibt bestehen. Wenn dann im laufenden Betrieb die Verbindung wegbricht bringt mir doch der Connection_timeout nicht viel, oder sehe ich das falsch? Der kommt doch nur am Anfang einmal zum Einsatz.

  • Hallo,


    Quote

    Wenn dann im laufenden Betrieb die Verbindung wegbricht bringt mir doch der Connection_timeout nicht viel, oder sehe ich das falsch?

    Wenn die Verbdindung weg ist weil abgebrochen bringt dir mit Sicherheit ein read/write timeout nichts, weil du ohne Connection auch nicht Schreiben und Lesen kannst :)


    In dem Fall musst du halt mal Testen, welche Exception Python wirft, wenn die Connection nicht mehr da ist. Also Connection herstellen, Pi vom Netz nehmen und versuchen, auf die Instanz der Connection zuzugreifen. Dann siehst du die Exception und kannst das bestehende Exception-Handling einbauen.


    Lt. Python DB API 2.0 sollte das eigentlich ein `OperationalError` sein.


    Gruß, noisefloor