2015-05-30 10 views
6

In PostgreSQL, der MVCC concurrency control Mechanismus sagt, dass:Warum MVCC für DML-Anweisungen Sperren erfordert

MVCC Schlösser zum Abfragen (Lesen) erfassten Daten nicht in Konflikt mit Sperren zum Schreiben von Daten erworben, und das Lesen so nie Blöcke und Schreiben nie blockiert Lesen

werden die aktuell betroffenen Zeilen, so dass keine andere Transaktion kann sie ändern, bis die aktuelle Transaktion festgeschrieben oder zurückgesetzt so even for READ_COMMITTED, eine Anweisung UPDATE Schreiben sperren.

Wenn eine gleichzeitige Transaktion ein UPDATE für die gesperrten Zeilen ausgibt, wird die zweite Transaktion blockiert, bis die erste ihre Sperren freigibt.

  1. Ist dieses Verhalten trying to prevent the write-write conflicts?

  2. Verlorene Aktualisierungen können weiterhin in READ_COMMITTED auftreten, da nach der ersten Transaktion die zweite Zeile überschrieben wird (auch wenn die Datenbank zwischen dem Start der UPDATE-Abfrage und dem Ende der Abfrage geändert wurde). Wenn also verlorene Updates noch möglich sind, warum muss die zweite Transaktion warten? Können die Snapshots auf Zeilenebene nicht zum Speichern der nicht festgeschriebenen Transaktionsänderungen verwendet werden, um zu vermeiden, dass Transaktionen auf die Freigabe von Schreibsperren warten müssen?

Antwort

3

Die Antwort auf die erste Frage ist Ja. Kein DBMS kann schmutzige Schreibvorgänge unterstützen; Wenn zwei Transaktionen T1 und T2 gleichzeitig ausgeführt werden und T2 eine Aktualisierung von T1 überschreibt, kann das System den Fall nicht behandeln, in dem T1 anschließend ein ROLLBACK ausgibt, da die Aktualisierung von T2 bereits erfolgt ist.

Um unkorrekte Schreibvorgänge zu vermeiden, war die ursprüngliche Definition für die Snapshot-Isolation "First Committer Wins" - das heißt, widersprüchliche Schreibvorgänge wären zulässig, aber nur die erste Transaktion, die ein COMMIT ausgeben konnte - alle anderen Konflikte Transaktionen müssten ROLLBACK werden. Aber dieses Programmiermodell ist etwas problematisch, wenn nicht verschwenderisch, da eine Transaktion möglicherweise einen wesentlichen Teil der Datenbank aktualisiert, nur um am Ende die Möglichkeit zum COMMIT zu verweigern. Anstelle von "First Committer Wins" implementieren die meisten DBMS-Systeme, die MVCC unterstützen, "First Updater Wins", indem sie das traditionelle zweiphasige Locking verwenden.

+0

Aber schmutzige Lesevorgänge können nicht passieren, da wir auf READ_COMMITTED sind. Ich frage mich, warum nicht isoliert Kopien aktualisieren und nur zur Commit-Zeit zu löschen. In PostgreSQL überschreibt der zweite TX einfach den ersten, aber es gibt auch eine Blockierung. Verwenden Sie auf dieser Isolationsstufe nicht nur sessionspezifische Snapshots und keine Blockierung. –

+0

Ich denke, was Sie mit "update isolierte Kopien" meinen, entspricht "First Committer gewinnt". Und ein System könnte das implementieren - aber das Programmiermodell ist ungerade, weil jede Transaktion auf den Fall vorbereitet sein muss, in dem jede Änderung "funktioniert" (dh es wurde abgeschlossen und kein Fehler zurückgegeben), aber die Transaktion nicht festgeschrieben werden kann . –

+0

Ich nehme an, dass das Sperrmodell einfacher zu übernehmen ist, da jede Datenbank bereits eine Sperrhierarchie hat. Wie Sie bereits erwähnt haben, sind es nicht nur die Zeilendaten, sondern auch alle Indizes. –