Sind InnoDB Deadlocks exklusiv für INSERT / UPDATE / DELETE?

8

Ich arbeite um den MySQL-Fehler "Deadlock gefunden, wenn versucht wird, die Sperre zu erhalten; versuchen Sie, die Transaktion neu zu starten" .

Ich muss ein Programm aktualisieren, um Deadlocks zuzulassen. Ist es möglich, dass diese SELECTAnweisung Deadlock-Fehler erzeugt? Ich weiß, dass es sich nur um eine Lesesperre handelt INSERT, sodass Mehrfachauswahl kein Problem darstellt. Was ist jedoch, wenn eine Anweisung UPDATEoder (mit Unterabfragen mit Joins möglich) und eine Anweisung (mit Joins oder Unterabfragen möglich) vorhanden sind ?DELETESELECT

Ist es möglich , dass der Fehler auf die geworfen werden , SELECTanstatt das INSERT, UPDATEoder DELETE.

Die Geschichte ist hier, wenn Sie neugierig sind.

Bryan Field
quelle
+1 für diese Frage ist eine gute Frage, da sie eine InnoDB-Eigenart ans Licht bringt, die den meisten Menschen in Verbindung mit SELECTs gegen InnoDB-Tabellen nicht bekannt ist.
RolandoMySQLDBA

Antworten:

5

Die direkte Antwort auf den Titel Ihrer Frage lautet Nein.

SELECT-Abfragen können Sperren für den gen_clust_index ausführen , auch bekannt als Clustered Index.

Hier sind drei Fragen zum DBA- Stapelaustausch , die ich mit @RedBlueThing , der Person, die diese Fragen gestellt hat, aggressiv durchgesehen habe . @RedBlueThing hat Workarounds für seine Fragen gefunden.

Nur um Ihre Frage im Blick zu behalten: Wenn Sie sich diese Antworten ansehen (schauen Sie nicht zu tief, auch wenn mir meine eigenen verschlungenen Antworten schwindelig werden), sollte schnell klar sein, dass SELECT-Abfragen Daten sperren können.

Sie haben auch spezielle Fälle von SELECT, in denen Sie bestimmte Zeilen bei Bedarf sperren können .

UPDATE 2011-08-08 16:49 EDT

Sie haben die Variationsfrage gestellt: "Werden InnoDB-Deadlock-Ausnahmen möglicherweise von SELECT ausgelöst?" Die Antwort darauf kann unter bestimmten Bedingungen Ja sein. Was ist das für ein Zustand? Wenn nur eine einzelne SQL-Anweisung aufgrund eines Fehlers zurückgesetzt wird, bleiben möglicherweise einige der von der Anweisung festgelegten Sperren erhalten. Dies liegt daran, dass InnoDB Zeilensperren in einem Format speichert, dass es nicht wissen kann, welche Sperre von welcher Anweisung gesetzt wurde .

Basierend auf dieser Aussage könnten die Ereignissequenzen, die dies verursachen, theoretisch wie folgt sein:

  • Ihr SQL-UPDATE erstellt eine einzelne Zeile, generiert jedoch einen Fehler
  • Das UPDATE bewirkt ein Rollback der einen Zeile
  • Die Reihe hat ein verweilendes Schloss

Persönlich macht mir diese letzte Aussage Angst. Es wäre schön für MySQL gewesen, alle über diese Eigenart zu informieren. Diese Aussage stammt jedoch aus der MySQL-Dokumentation. (Oh ja, Oracle besitzt InnoDB)

UPDATE 2015-09-22 18:40 EST

Anfang des Jahres erfuhr ich, dass Percona einen coolen Nagios-Check hat , um diese lästigen Schlösser zu finden, die sich hinter schlafenden Verbindungen verstecken. Jetzt müssen Sie nur noch den Code über diesen Link ausführen:

SELECT COALESCE(MAX(IF(p.command = 'Sleep', p.time, 0)), 0) AS idle_in_trx
FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS AS w
INNER JOIN INFORMATION_SCHEMA.INNODB_TRX        AS b ON  b.trx_id = w.blocking_trx_id
INNER JOIN INFORMATION_SCHEMA.INNODB_TRX        AS r ON  r.trx_id = w.requesting_trx_id
LEFT JOIN  INFORMATION_SCHEMA.PROCESSLIST       AS p ON  p.id     = b.trx_mysql_thread_id;

Dies funktioniert nur für MySQL 5.5+. Wenn Sie MySQL 5.1 oder eine frühere Version haben, müssen Sie alle schlafenden Verbindungen beenden, um die Sperren aufzuheben.

RolandoMySQLDBA
quelle
@ Rolando - stimmt das nicht mit InnoDBs MVCC, das liest, blockiert nie (außer wenn Sie for updatenatürlich verwenden)?
Jack sagt, versuchen Sie es mit topanswers.xyz
@ Jack - Wenn Sie die Links in den ersten drei Aufzählungspunkten lesen, werden Sie feststellen, dass MVCC nicht in Frage kommt. Es ist ein tiefer Deadlock im Clustered-Index, den nicht einmal MVCC abmildern kann.
RolandoMySQLDBA
@ Rolando - Ich habe die Links etwas genauer gelesen und sehe immer noch keinen Hinweis darauf, dass ein Normaler selectZeilen sperren oder in irgendeiner Weise von DML in einer anderen Transaktion blockiert werden kann. Das gilt sicherlich für Oracle und soweit ich das beurteilen kann, auch für InnoDB? Mit Ausnahme des Falls, in dem die selectAnweisung tatsächlich DML über eine Funktion oder eine andere Umlaufroute ausführt .
Jack sagt, versuchen Sie topanswers.xyz
@ Jack - Wenn SELECTs einen Index blockieren können, wie viel mehr ein UPDATE, wie meine ersten 3 Links zeigen.
RolandoMySQLDBA