norbert: mysql show processlist

Hallo,

in den letzten Tagen habe ich immer wieder Probleme, dass sich eine bestimmte Datenbaktabelle festfährt. SHOW PROCESSLIST zeigt mir die Tabelle und die Anweisung (es immer ein UPDATE...). Da diese Anweisung in mehreren Scripten vorkommt, wäre jetzt noch gut zu wissen welches Script da amok läuft.

  1. in den letzten Tagen habe ich immer wieder Probleme, dass sich eine bestimmte Datenbaktabelle festfährt. SHOW PROCESSLIST zeigt mir die Tabelle und die Anweisung (es immer ein UPDATE...). Da diese Anweisung in mehreren Scripten vorkommt, wäre jetzt noch gut zu wissen welches Script da amok läuft.

    Dabei wird dir SHOW PROCESSLIST (besser SHOW FULL PROCESSLIST) zunächst nicht weiterhelfen können.

    Idee: Du könntest dem UPDATE ein vermeintlich unsinniges Fragment anhängen, womit Du dann in der Prozessliste Rückschlüsse auf das Script ziehen kannst:

    AND 97 = 97 für Script A

    AND 99 = 99 für Script B

    usw.

  2. Moin,

    in den letzten Tagen habe ich immer wieder Probleme, dass sich eine bestimmte Datenbaktabelle festfährt. SHOW PROCESSLIST zeigt mir die Tabelle und die Anweisung (es immer ein UPDATE...).

    also ein SQL-Query, das die Datenbank immens beschäftigt?

    Da diese Anweisung in mehreren Scripten vorkommt, wäre jetzt noch gut zu wissen welches Script da amok läuft.

    Betreibe Debugging. Du sagst nichts über die verwendete Scriptsprache; ich gehe aber wegen der Popularität mal von PHP aus. Fürs Prinzip ist das aber auch egal. Ich würde eine Logdatei führen und da vor jeder verdächtigen Anweisung einen eindeutigen Eintrag reinschreiben. So kannst du erkennen, wo das Script hängt (mit tail sogar live).

    Andererseits kann das Script vielleicht gar nichts dafür, sondern dein SQL-Statement ist prinzipiell so ... ungünstig gebaut, dass es den DB-Server über Gebühr strapaziert. Ursache ist auch oft ein ungünstiges Datenmodell.

    Live long and pros healthy,
     Martin

    --
    Ich stamme aus Ironien, einem Land am sarkastischen Ozean.
    1. Hallo Martin,

      ja, sorry es geht um php scripte.

      Andererseits kann das Script vielleicht gar nichts dafür, sondern dein SQL-Statement ist prinzipiell so ... ungünstig gebaut, dass es den DB-Server über Gebühr strapaziert. Ursache ist auch oft ein ungünstiges Datenmodell.

      Das ist das komplizierteste SQL Statement:

      UPDATE lieferschein 
        SET termin = '$termin',
            anSchgl = 'j',
            bemerkung = '$text',
            anSchgl_gesendet = 'j',
            anSchgl_gesendet_datum = '$datum'
      WHERE ls_num = '$id'
      

      Da kann ich mir nicht vorstellen, dass es daran liegt.

      Edit Rolf B: SQL formatiert

      1. Hallo norbert,

        das Statement sieht harmlos aus, aber:

        • ist es InnoDB?
        • wieviel Rows hat die Table?
        • ist ls_num eine Indexierte Spalte?
        • gibt es Trigger, die ggf. Folgeaktivitäten auslösen können?
        • Sind die geänderten Spalten ggf. foreign Keys, die mit Update Cascade definiert sind?

        Wieviel Last ist auf der Webseite? Viele User gleichzeitig? Wenn es dann Transaktionen gibt, können zwei Requeste, die zuerst Sätze lesen und dann einen Updaten, sich gegenseitig festfressen. Voraussetzung sind Isolation Levels in den Transaktionen, die Lesesperren hervorrufen. Zum Beispiel Repeatable Read.

        Request 1: Liest Sätze 1-10 und setzt für sie einen s-lock (Shared Lock) Request 2: Liest Sätze 1-10 und setzt ebenfalls einen s-lock

        Zwei s-locks auf einen Satz sind erlaubt. Alles prima.

        Request 1: Möchte Satz 4 Updaten und bestellt bei MySQL einen Upgrade des s-lock von Satz 4 auf einen x-lock (Exclusive lock). Diese Bestellung geht in die Warteschlange, weil Request 2 ebenfalls einen s-lock hält. Ein x-lock will allein sein.

        Request 2: Möchte Satz 7 Updaten und bestellt bei MySQL einen Upgrade seines s-lock auf Satz 7 auf einen x-lock. Aber Request 1 hält bereits einen s-lock, darum geht auch diese Bestellung in die Warteschlange.

        Dum di dum di dum...

        Irgendwann gibt's einen Deadlock-Timeout.

        In einer Transaktion erst zu lesen und dann zu schreiben ist bei Multiuserbetrieb kritisch. Hier gibt's eine Abhandlung zum Thema.

        Statt vorab zu sperren (pessimistic locking) gibt's auch die Möglichkeit, gar nicht zu sperren und beim Schreiben zu prüfen, ob das immer noch der Satz ist den man gelesen hat (optimistic locking). Dazu braucht es einen Update-Timestamp oder einen Updatecounter pro Row, der man bei jedem Update ändert. Das ist natürlich Programmierarbeit.

        Rolf

        --
        sumpsi - posui - obstruxi
      2. Das ist das komplizierteste SQL Statement:

        UPDATE lieferschein 
          SET termin = '$termin',
              anSchgl = 'j',
              bemerkung = '$text',
              anSchgl_gesendet = 'j',
              anSchgl_gesendet_datum = '$datum'
        WHERE ls_num = '$id'
        

        Da kann ich mir nicht vorstellen, dass es daran liegt.

        Die Komplexität des Statements ist nicht entscheidend. Du kannst je nach Konstellation mit noch einfacheren Statements die DB quälen.

        Wie die anderen schon sagten, hier fehlt noch input. Ein Dump der Tabellenstruktur wäre schon einmal hilfreich sowie die Anzahl der Records der Tabelle.

        Allerdings fällt mit bei Deinem SQL eine Sache schonmal auf: "ls_num = '$id'". Das impliziert, ls_num könnte ein Zahlenfeld sein, richtig? Dann kannst Du Dir mit den unscheinbar wirkenden "'" um "$id" schon heftig ins Knie schießen, weil Mysql je nach Version darauf sehr allergisch reagiert. Die Bedingung wird zwar umgesetzt, aber ein etwaiger Index dabei missachtet.

        1. Hallo Mitleser,

          die Frage, ob der Kontextwechsel beachtet wurde, müsste man auch stellen...

          Rolf

          --
          sumpsi - posui - obstruxi
          1. Hallo,

            die Frage, ob der Kontextwechsel beachtet wurde, müsste man auch stellen...

            ja, unbedingt. Das wäre dann aber eine separate Baustelle, die mit den Performance-Problemen bzw. dem Hängenbleiben eher wenig zu tun hat.

            Live long and pros healthy,
             Martin

            --
            Ich stamme aus Ironien, einem Land am sarkastischen Ozean.
      3. Es besteht auch die Vermutung, dass diese SQL-Anweisung sehr viel öfter als vorgesehen ausgeführt wird.

        z.B. in einer While-Schleife, deren Abbruchbedingung nicht erfüllt wird.

        Dann wäre der Fehler bzw. nicht bei mysql sondern der konsumierenden Anwendung zu suchen.

        Den wertvollen Hinweis, die abgehenden SQL-Abfragen zu loggen (PHP: error_log($sql) ) und mit tail -f error_log während der Laufzeit zu beschauen, hast Du schon von Martin bekommen…

  3. Hallo norbert,

    (Edit: Das kommt davon wenn man Antworten erst anderthalb Stunden später verschickt...)

    Es muss nicht unbedingt ein Langläufer sein, es gibt auch Deadlocks. Verwendest Du Transaktionen?

    (Rest gelöscht, obsolet)

    Rolf

    --
    sumpsi - posui - obstruxi
    1. Hello,

      Hallo norbert,

      (Edit: Das kommt davon wenn man Antworten erst anderthalb Stunden später verschickt...)

      Es muss nicht unbedingt ein Langläufer sein, es gibt auch Deadlocks. Verwendest Du Transaktionen?

      (Rest gelöscht, obsolet)

      Dafür wäre es zusätzlich hilfreich, vom OP den verwendeten EngineType (MyISAM, InnoDB)zu erfahren und das Createstatement der betroffenen Tabelle. Und was versteht er unter "fährt sich fest"?

      Glück Auf
      Tom vom Berg

      --
      Es gibt nichts Gutes, außer man tut es!
      Das Leben selbst ist der Sinn.