Beziehung der Transaktionsisolationsstufen zu Sperren in der Tabelle

105

Ich habe über 4 Isolationsstufen gelesen:

Isolation Level       Dirty Read    Nonrepeatable Read  Phantom Read  
READ UNCOMMITTED      Permitted       Permitted           Permitted
READ COMMITTED              --        Permitted           Permitted
REPEATABLE READ             --             --             Permitted
SERIALIZABLE                --             --              --

Ich möchte die Sperre verstehen, die jede Transaktionsisolation für die Tabelle übernimmt

READ UNCOMMITTED - no lock on table
READ COMMITTED - lock on committed data
REPEATABLE READ - lock on block of sql(which is selected by using select query)
SERIALIZABLE - lock on full table(on which Select query is fired)

Im Folgenden sind die drei Phänomene aufgeführt, die bei der Transaktionsisolation auftreten können.
Dirty Read - keine Sperre
Nonrepeatable Read - kein Dirty Read als Sperre für festgeschriebene Daten
Phantom Read - Sperre für einen SQL-Block (der mithilfe der Auswahlabfrage ausgewählt wird)

Ich möchte verstehen, wo wir diese Isolationsstufen definieren: nur auf jdbc / hibernate-Ebene oder auch in DB

PS: Ich habe die Links in den Isolationsstufen in Oracle durchgesehen , aber sie sehen ungeschickt aus und sprechen datenbankspezifisch

Lerner
quelle
3
Dies hängt vollständig von der Datenbank ab. Unterschiedliche Datenbanken können unterschiedliche Algorithmen für Isolationsstufen verwenden. Einige verwenden möglicherweise MVCC (keine Sperren für ausgewählte Abfragen), andere verwenden eine strikte 2-Phasen-Sperre (gemeinsam genutzte und exklusive Sperren).
Brb Tee

Antworten:

157

Ich möchte die Sperre verstehen, die jede Transaktionsisolation für die Tabelle übernimmt

Sie haben beispielsweise drei gleichzeitige Prozesse A, B und C. A startet eine Transaktion, schreibt Daten und schreibt fest / rollt (abhängig von den Ergebnissen). B führt nur eine SELECTAnweisung aus, um Daten zu lesen. C liest und aktualisiert Daten. Alle diese Prozesse arbeiten an derselben Tabelle T.

  • LESEN SIE UNVERPFLICHTET - keine Sperre auf dem Tisch. Sie können Daten in der Tabelle lesen, während Sie darauf schreiben. Dies bedeutet, dass A Daten schreibt (nicht festgeschrieben) und B diese nicht festgeschriebenen Daten lesen und verwenden kann (für jeden Zweck). Wenn A einen Rollback ausführt, hat B die Daten noch gelesen und verwendet. Dies ist die schnellste, aber unsicherste Art, mit Daten zu arbeiten, da dies zu Datenlücken in nicht physisch verwandten Tabellen führen kann (ja, zwei Tabellen können in realen Apps logisch, aber nicht physisch verwandt sein = \).
  • COMMITTED LESEN - Festgeschriebene Daten sperren. Sie können die Daten lesen, die nur festgeschrieben wurden. Dies bedeutet, dass A Daten schreibt und B die von A gespeicherten Daten erst lesen kann, wenn A ein Commit ausführt. Das Problem hierbei ist, dass C Daten aktualisieren kann, die auf dem B- und B-Client gelesen und verwendet wurden und nicht über die aktualisierten Daten verfügen.
  • REPEATABLE READ - Sperren eines SQL-Blocks (der mithilfe der Auswahlabfrage ausgewählt wird). Dies bedeutet, dass B die Daten unter bestimmten Bedingungen liest, dh WHERE aField > 10 AND aField < 20A fügt Daten ein, bei denen der aFieldWert zwischen 10 und 20 liegt, dann liest B die Daten erneut und erhält ein anderes Ergebnis.
  • SERIALIZABLE - Sperren einer vollständigen Tabelle (für die die Select-Abfrage ausgelöst wird). Dies bedeutet, dass B die Daten liest und keine andere Transaktion die Daten in der Tabelle ändern kann . Dies ist die sicherste, aber langsamste Art, mit Daten zu arbeiten. Da eine einfache Leseoperation die Tabelle sperrt , kann dies zu schwerwiegenden Produktionsproblemen führen: Stellen Sie sich vor, die T-Tabelle ist eine Rechnungstabelle, Benutzer X möchte die Rechnungen des Tages kennen und Benutzer Y möchte eine neue Rechnung erstellen Während X das Lesen der Rechnungen ausführt, kann Y keine neue Rechnung hinzufügen (und wenn es um Geld geht, werden die Leute wirklich wütend, besonders die Chefs).

Ich möchte verstehen, wo wir diese Isolationsstufen definieren: nur auf JDBC- / Ruhezustandsebene oder auch in DB

Mit JDBC definieren Sie es mit Connection#setTransactionIsolation.

Verwenden des Ruhezustands:

<property name="hibernate.connection.isolation">2</property>

Wo

  • 1: LESEN SIE UNVERPFLICHTET
  • 2: LESEN SIE VERPFLICHTET
  • 4: WIEDERHOLBARES LESEN
  • 8: SERIALISIERBAR

Die Konfiguration für den Ruhezustand wird von hier aus übernommen (Entschuldigung, es ist auf Spanisch).

Übrigens können Sie die Isolationsstufe auch für RDBMS festlegen:

und weiter und weiter...

Luiggi Mendoza
quelle
docs.oracle.com/cd/B12037_01/server.101/b10743/consist.htm Nur zum Hinzufügen für Oracle: Sie können die Isolationsstufe einer Transaktion mithilfe einer der folgenden Anweisungen zu Beginn einer Transaktion festlegen: SET TRANSACTION ISOLATION LEVEL READ COMMITTED; SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; SET TRANSACTION NUR LESEN;
Lerner
2
Um die Netzwerk- und Verarbeitungskosten für den Beginn jeder Transaktion mit einer SET TRANSACTION-Anweisung zu sparen, können Sie mit der ALTER SESSION-Anweisung die Transaktionsisolationsstufe für alle nachfolgenden Transaktionen festlegen: ALTER SESSION SET ISOLATION_LEVEL SERIALIZABLE; ALTER SESSION SET ISOLATION_LEVEL READ COMMITTED;
Lerner
12
In Bezug auf REPEATABLE READ - Ich denke, ein besseres Beispiel, um dies zu demonstrieren, ist wie folgt: B startet eine Transaktion, liest Daten auf dem SQL-Block WHERE aField> 10 UND aField <20, diese Daten sind gesperrt, bis die Transaktion endet. A versucht, diese Daten zu aktualisieren, wartet jedoch aufgrund der Sperre. Wenn B diese Daten nun in derselben Transaktion erneut liest, werden garantiert dieselben Daten gelesen, da sie gesperrt sind. Korrigiere mich, wenn ich falsch liege.
BornToCode
1
@LuiggiMendoza Als allgemeines Konzept handelt es sich bei den Isolationsstufen nur um Dirty Read , Non-Repeatable Read und Phantom Rows . Locks (S2PL) oder MVCC sind Implementierungen für verschiedene Anbieter.
Brb Tee
4
@LuiggiMendoza - Ich war nicht genau, es sollte so sein - die Daten, die B liest, werden nicht geändert, aber konsequente Auswahlen von B könnten mehr Zeilen zurückgeben. Dies liegt daran, dass A Zeilen, die B bereits gelesen hat , erst ändern kann , wenn A sie freigibt. A kann jedoch neue Zeilen einfügen, die die where-Bedingung qualifizieren (und daher erhält A beim nächsten Ausführen einer Auswahl ein anderes Ergebnis mit mehr Zeilen - ein Phantom-Lesevorgang).
BornToCode
9

Wie brb tea sagt, hängt dies von der Datenbankimplementierung und dem verwendeten Algorithmus ab: MVCC oder Two Phase Locking.

CUBRID (Open Source RDBMS) erklärt die Idee dieser beiden Algorithmen:

  • Zweiphasenverriegelung (2PL)

Der erste ist, wenn die T2-Transaktion versucht, den A-Datensatz zu ändern, sie weiß, dass die T1-Transaktion den A-Datensatz bereits geändert hat, und wartet, bis die T1-Transaktion abgeschlossen ist, da die T2-Transaktion nicht wissen kann, ob die T1-Transaktion festgeschrieben oder gerollt wird zurück. Diese Methode wird als Zwei-Phasen-Verriegelung (2PL) bezeichnet.

  • Parallelitätskontrolle für mehrere Versionen (MVCC)

Die andere besteht darin, jeder von ihnen, T1- und T2-Transaktionen, zu erlauben, ihre eigenen geänderten Versionen zu haben. Selbst wenn die T1-Transaktion den A-Datensatz von 1 auf 2 geändert hat, lässt die T1-Transaktion den ursprünglichen Wert 1 unverändert und schreibt, dass die T1-Transaktionsversion des A-Datensatzes 2 ist. Dann ändert die folgende T2-Transaktion den A-Datensatz von 1 bis 3, nicht von 2 bis 4, und schreibt, dass die T2-Transaktionsversion des A-Datensatzes 3 ist.

Wenn die T1-Transaktion zurückgesetzt wird, spielt es keine Rolle, ob die 2, die T1-Transaktionsversion, nicht auf den A-Datensatz angewendet wird. Wenn danach die T2-Transaktion festgeschrieben wird, wird die 3, die T2-Transaktionsversion, auf den A-Datensatz angewendet. Wenn die T1-Transaktion vor der T2-Transaktion festgeschrieben wird, wird der A-Datensatz zum Zeitpunkt der Festschreibung der T2-Transaktion in 2 und dann in 3 geändert. Der endgültige Datenbankstatus ist identisch mit dem Status der unabhängigen Ausführung jeder Transaktion, ohne dass dies Auswirkungen auf andere Transaktionen hat. Daher erfüllt es die ACID-Eigenschaft. Diese Methode wird als MVCC (Multi-Version Concurrency Control) bezeichnet.

Das MVCC ermöglicht gleichzeitige Änderungen auf Kosten eines erhöhten Speicheraufwands (da unterschiedliche Versionen derselben Daten verwaltet werden müssen) und einer Berechnung (auf der Ebene REPETEABLE_READ können Sie keine Updates verlieren, sodass die Versionen der Daten wie Hiberate überprüft werden müssen macht mit Optimistick Locking ).

In 2PL Transaktionsisolationsstufen steuern Sie Folgendes :

  • Ob beim Lesen von Daten Sperren genommen werden und welche Art von Sperren angefordert werden.

  • Wie lange die Lesesperren gehalten werden.

  • Ob eine Leseoperation, die auf Zeilen verweist, die von einer anderen Transaktion geändert wurden:

    • Blockieren, bis die exklusive Sperre für die Zeile freigegeben ist.

    • Rufen Sie die festgeschriebene Version der Zeile ab, die zum Zeitpunkt des Starts der Anweisung oder Transaktion vorhanden war.

    • Lesen Sie die nicht festgeschriebene Datenänderung.

Die Auswahl einer Transaktionsisolationsstufe wirkt sich nicht auf die Sperren aus, die zum Schutz von Datenänderungen erworben wurden. Eine Transaktion erhält immer eine exklusive Sperre für alle Daten, die sie ändert, und hält diese Sperre, bis die Transaktion abgeschlossen ist, unabhängig von der für diese Transaktion festgelegten Isolationsstufe. Bei Lesevorgängen definieren Transaktionsisolationsstufen in erster Linie die Schutzstufe vor den Auswirkungen von Änderungen, die durch andere Transaktionen vorgenommen werden.

Eine niedrigere Isolationsstufe erhöht die Fähigkeit vieler Benutzer, gleichzeitig auf Daten zuzugreifen, erhöht jedoch die Anzahl der Parallelitätseffekte , wie z. B. Dirty Reads oder verlorene Updates, auf die Benutzer möglicherweise stoßen.

Konkrete Beispiele für die Beziehung zwischen Sperren und Isolationsstufen in SQL Server (verwenden Sie 2PL außer bei READ_COMMITED mit READ_COMMITTED_SNAPSHOT = ON).

  • READ_UNCOMMITED: Geben Sie keine gemeinsam genutzten Sperren aus, um zu verhindern, dass andere Transaktionen die von der aktuellen Transaktion gelesenen Daten ändern. READ UNCOMMITTED-Transaktionen werden auch nicht durch exklusive Sperren blockiert, die verhindern würden, dass die aktuelle Transaktion Zeilen liest, die geändert, aber nicht von anderen Transaktionen festgeschrieben wurden. [...]

  • READ_COMMITED:

    • Wenn READ_COMMITTED_SNAPSHOT auf OFF gesetzt ist (Standardeinstellung): Verwendet gemeinsam genutzte Sperren, um zu verhindern, dass andere Transaktionen Zeilen ändern, während die aktuelle Transaktion einen Lesevorgang ausführt. Die gemeinsam genutzten Sperren blockieren auch das Lesen von Zeilen, die von anderen Transaktionen geändert wurden, bis die andere Transaktion abgeschlossen ist. [...] Zeilensperren werden aufgehoben, bevor die nächste Zeile verarbeitet wird. [...]
    • Wenn READ_COMMITTED_SNAPSHOT auf ON gesetzt ist, verwendet das Datenbankmodul die Zeilenversionierung, um jeder Anweisung einen transaktionskonsistenten Snapshot der Daten zu präsentieren, wie sie zu Beginn der Anweisung vorhanden waren. Sperren werden nicht verwendet, um die Daten vor Aktualisierungen durch andere Transaktionen zu schützen.
  • REPETEABLE_READ: Gemeinsame Sperren für alle Daten, die von jeder Anweisung in der Transaktion gelesen werden, werden gehalten, bis die Transaktion abgeschlossen ist.

  • SERIALIZABLE: Bereichssperren werden in den Bereich der Schlüsselwerte eingefügt, die den Suchbedingungen jeder in einer Transaktion ausgeführten Anweisung entsprechen. [...] Die Bereichssperren werden gehalten, bis die Transaktion abgeschlossen ist.

gabrielgiussi
quelle
5

Die Sperren werden immer auf DB-Ebene genommen: -

Offizielles Oracle-Dokument: - Um Konflikte während einer Transaktion zu vermeiden, verwendet ein DBMS Sperren, Mechanismen, um den Zugriff anderer auf die Daten zu blockieren, auf die die Transaktion zugreift. (Beachten Sie, dass im Auto-Commit-Modus, in dem jede Anweisung eine Transaktion ist, Sperren nur für eine Anweisung gehalten werden.) Nachdem eine Sperre gesetzt wurde, bleibt sie in Kraft, bis die Transaktion festgeschrieben oder zurückgesetzt wird. Beispielsweise könnte ein DBMS eine Zeile einer Tabelle sperren, bis Aktualisierungen festgeschrieben wurden. Die Wirkung dieser Sperre besteht darin, zu verhindern, dass ein Benutzer einen fehlerhaften Lesevorgang erhält, dh einen Wert liest, bevor er dauerhaft gemacht wird. (Der Zugriff auf einen aktualisierten Wert, der nicht festgeschrieben wurde, wird als fehlerhafter Lesevorgang angesehen, da dieser Wert möglicherweise auf den vorherigen Wert zurückgesetzt werden kann. Wenn Sie einen Wert lesen, der später zurückgesetzt wird, haben Sie einen ungültigen Wert gelesen. )

Wie Sperren gesetzt werden, hängt von der sogenannten Transaktionsisolationsstufe ab, die von der Nichtunterstützung von Transaktionen bis zur Unterstützung von Transaktionen reichen kann, die sehr strenge Zugriffsregeln erzwingen.

Ein Beispiel für eine Transaktionsisolationsstufe ist TRANSACTION_READ_COMMITTED, mit der erst nach dem Festschreiben auf einen Wert zugegriffen werden kann. Mit anderen Worten, wenn die Transaktionsisolationsstufe auf TRANSACTION_READ_COMMITTED festgelegt ist, lässt das DBMS keine schmutzigen Lesevorgänge zu. Die Schnittstellenverbindung enthält fünf Werte, die die Transaktionsisolationsstufen darstellen, die Sie in JDBC verwenden können.

Goyal Vicky
quelle