2016-05-30 5 views
1

Ich habe einige InnoDB-Tabellen und ein Skript, das eine Transaktion startet. Innerhalb dieser Transaktion werden verschiedene Zeilen einer Tabelle aktualisiert, andere Zeilen werden in eine andere Tabelle eingefügt und viele Auswahlvorgänge werden ausgeführt. Dies muss zuverlässig passieren, daher verwende ich eine Standardtransaktion mit REPEATABLE READ als Isolationsstufe. Diese Transaktion kann einige Zeit dauern.Wie kann ich das Blockieren von Selects verhindern, wenn eine Transaktion läuft?

Jetzt, wenn andere Skripts (Webseitenanforderungen) zur gleichen Zeit ausgeführt werden, werden einige Selects in der Datenbank ausgeführt. Leider warten diese Selects, bis die Transaktion beendet ist, da sie aus den gleichen Tabellen gelesen haben. Die ausgewählten Daten können die aktualisierten Daten der Transaktion sein, können aber auch andere Daten sein.

Diese Blockierung ist, was ich vermeiden möchte. Ich möchte die Webseite dem Benutzer sofort zeigen und kann nicht auf die Transaktion warten (ein oder zwei Sekunden wären akzeptabel, aber die Transaktion ist manchmal viel länger).

Also wie kann ich wählen? Ich schätze, dass die Daten dann möglicherweise nicht immer genau sind. Aber das ist besser, dann lassen Sie den Benutzer 20 Sekunden warten.

Soll ich

  • Verwendung 'FOR UPDATE' oder 'LOCK IN SHARE MODE' mit dem wählt in der Transaktion?
  • eine andere Isolationsstufe verwenden?
  • setzen die Leseauswahl auch in eine Transaktion?
  • etwas anderes tun?

Ich denke, das ist eine sehr häufige Anforderung, aber ich konnte noch keine einfache Antwort finden.

Hinweis: Die nächste Sache wäre, gleichzeitige Schreibtransaktionen zu sichern. Aber jetzt möchte ich nur sicherstellen, dass zumindest parallele Lesevorgänge während der Transaktion nicht blockiert werden.

+0

@iLikeMySql Was meinst du? Ich sehe nur, dass Selects außerhalb der Transaktion warten, bis die Transaktion abgeschlossen ist. Die Transaktion verwendet UPDATE-, INSERT- und SELECT-Anweisungen. – robsch

Antwort

0

Okay, das keine wirkliche Antwort ist, aber ich dachte, soll ich sagen, was ich herausgefunden haben:

Es ist nicht etwas mit den MySQL-Aktionen zu tun hat, denke ich. Es hingen tatsächlich PHP-Anfragen. Das heißt, als der erste PHP-Aufruf die lang andauernde Transaktion startete, wurden weitere PHP-Aufrufe an andere Seiten gehängt. Und der Grund, warum sie gehängt wurden, war, dass die Sitzung von der ersten Anfrage gesperrt wurde! session_start() hat nicht mehr funktioniert. Gerade wenn die erste Anfrage abgeschlossen wurde (oder abgelaufen ist), würden weitere Anfragen wieder funktionieren.

Da der PHP-Aufruf mit langer Transaktion nichts in die Sitzung schreiben musste, schließe ich einfach die Sitzung mit session_write_close() in diesem Aufruf. Jetzt hängen weitere Anfragen nicht mehr.

This war der Hinweis für mich.

Fazit: Die Datenbankauswahl wurde nicht blockiert.