2 Stimmen

Wie kann ich in dieser Situation eine Totalsperre erreichen?

In meiner Client-Anwendung habe ich eine Methode wie diese (in der Praxis ist es komplexer, aber ich habe den wichtigsten Teil gelassen):

public void btnUpdate_Click(...)
{
  ...
  dataAdapter.Update(...);
  ...
  dataAdapter.Fill(...); // here I got exception one time
}

Die Ausnahme, die ich in den Protokollen gefunden habe, lautet "Deadlock found when trying to get lock; try restarting transaction". Ich traf diese Ausnahme nur einmal, also wurde sie nicht wiederholt.
So wie ich es verstehe, führt die Methode DataAdapter.Fill() nur die Select-Abfrage aus. Ich mache keine explizite Transaktion und habe autocommit aktiviert.
Also, wie kann ich tote Sperre auf eine einfache Abfrage auswählen, die nicht ein Teil der größeren Transaktion ist?
So wie ich es verstehe, sollten zwei Transaktionen aufeinander warten, um einen Deadlock zu erhalten. Wie ist das mit einem einzelnen Select möglich, der nicht innerhalb einer Transaktion stattfindet? Vielleicht ist es ein Fehler in MySql?

Ich danke Ihnen im Voraus.

1voto

Charles Bretana Punkte 137391

Sie haben Recht, dass zwei Transaktionen erforderlich sind, um eine Sackgasse zu verursachen. Das heißt, keine Anweisung oder Anweisungen innerhalb einer einzelnen Transaktion können mit anderen Anweisungen innerhalb der Transaktion in eine Sackgasse geraten. gleiche Transaktion .

Aber es genügt eine einzige Transaktion, um eine Meldung über eine Blockierung zu erhalten. Woher wissen Sie, dass die Transaktion, bei der Sie die Blockierung feststellen, die einzige Transaktion ist, die in der Datenbank ausgeführt wird? Gibt es nicht noch andere Aktivitäten in dieser Datenbank?

Auch Ihre Aussage " Ich mache keine explizite Transaktion " und " ... die nicht Teil einer größeren Transaktion ist " bedeutet, dass Sie nicht verstehen, dass jede ausgeführte SQL-Anweisung immer in einer impliziten Transaktion ist, auch wenn Sie nicht explizit eine starten.

Die meisten Datenbanken verfügen über Berichterstattungsmechanismen, die speziell für die Verfolgung, Meldung und/oder Protokollierung von Deadlocks zu Diagnosezwecken entwickelt wurden. In SQL Server gibt es ein Trace-Flag, das einen Protokolleintrag mit vielen Details über jeden auftretenden Deadlock verursacht, einschließlich Details über jede der beiden beteiligten Transaktionen, z. B. welche SQL-Anweisungen ausgeführt wurden, welche Objekte in der Datenbank gesperrt waren und warum die Sperre nicht erhalten werden konnte. Ich nehme an, dass mySQL über ein ähnliches Diagnosewerkzeug verfügt. Finden Sie heraus, was es ist, und aktivieren Sie es, damit Sie beim nächsten Mal, wenn so etwas passiert, nachsehen und herausfinden können, was genau passiert ist.

0voto

Remus Rusanu Punkte 280155

Sie können ein einfaches SELECT gegen andere Anweisungen, wie ein UPDATE. In meinem Blog habe ich ein Beispiel, das einen Deadlock zwischen zwei gut getunnelten Anweisungen erklärt: Lese-/Schreibblockade . Das Beispiel ist zwar SQL Server-spezifisch, aber das Prinzip ist allgemein gültig. Ich kenne MySQL nicht gut genug, um sagen zu können, ob dies notwendigerweise der Fall ist oder nicht, insbesondere angesichts der verschiedenen Engines, die MySQL einsetzen kann, aber nichtsdestotrotz kann ein einfaches SELECT Opfer eines Deadlocks werden.

0voto

Guffa Punkte 663241

Ich habe nicht untersucht, wie MySQL-Transaktionen funktionieren, aber dies ist auf der Grundlage, wie MSSQL-Transaktionen funktionieren:

Wenn Sie keine Transaktion verwenden, hat jede Abfrage eine eigene Transaktion. Andernfalls würden Sie jedes Mal ein Chaos bekommen, wenn eine Aktualisierung in der Mitte fehlschlägt.

Der Grund für die Blockade könnte die Eskalation von Sperren sein. Die Datenbank versucht, bei jeder Abfrage so wenig wie möglich zu sperren, weshalb sie zunächst nur die einzelnen betroffenen Zeilen sperrt. Wenn die meisten Zeilen einer Seite durch die Abfrage gesperrt sind, kann sie entscheiden, dass es besser wäre, die Sperre zu erweitern und die gesamte Seite zu sperren, was den Nebeneffekt haben kann, dass einige Zeilen gesperrt werden, die nicht von der Abfrage betroffen sind.

Wenn ein select Abfrage und eine update Abfrage versuchen, Sperren auf dieselbe Tabelle zu erweitern, können sie einen Deadlock verursachen, obwohl nur eine einzige Tabelle betroffen ist.

0voto

Chris Travers Punkte 23990

Ich stimme zu, dass dies in diesem speziellen Fall wahrscheinlich nicht das Problem ist, aber dies ist eine Ergänzung zu den anderen Antworten in Bezug auf die Begrenzung ihres Anwendungsbereichs, die für die Nachwelt festgehalten wird, falls jemand sie nützlich findet.

MySQL kann in seltenen Fällen einzelne Anweisungen periodisch gegen sich selbst blockieren. Das scheint vor allem bei Masseneinfügungen zu passieren, und die Probleme sind mit ziemlicher Sicherheit ein Deadlock zwischen verschiedenen Threads, die sich auf die Operation beziehen. Ich würde erwarten, dass bei Bulk-Updates das gleiche Problem auftritt. Wenn ich in der Vergangenheit mit dieser Art von Problemen konfrontiert war, habe ich im Allgemeinen einfach die Anzahl der Zeilen, die in einer einzelnen Anweisung eingefügt (oder aktualisiert) werden, verringert. Beim Versuch, die Sperre in diesem Fall zu erhalten, kommt es normalerweise nicht zu einem Deadlock, sondern zu anderen Meldungen.

Ein Kollege von mir und ich diskutierten über ähnliche Probleme in MS SQL Server (das Problem ist also nicht auf MySQL beschränkt!), und er wies darauf hin, daß die Lösung dort darin besteht, dem Server mitzuteilen, daß er das Einfügen oder Aktualisieren nicht parallelisieren soll. Bei den Problemen handelt es sich um spinlock-bedingte Deadlocks, nicht um Deadlocks durch logische Sperren im RDBMS.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X