Heim  >  Artikel  >  Datenbank  >  Probleme im Zusammenhang mit RR und Phantom-Lesen in MySQL

Probleme im Zusammenhang mit RR und Phantom-Lesen in MySQL

WBOY
WBOYnach vorne
2022-10-11 16:59:021941Durchsuche

Dieser Artikel vermittelt Ihnen relevantes Wissen über MySQL und stellt hauptsächlich relevante Inhalte zu RR und Phantom-Lesen vor, einschließlich des MVCC-Prinzips, der Erzeugung von Phantom-Lesungen durch RR, der Lösung von Phantom-Lesungen durch RR usw. Werfen wir einen Blick darauf: hoffe es hilft allen.

Probleme im Zusammenhang mit RR und Phantom-Lesen in MySQL

Empfohlenes Lernen: MySQL-Video-Tutorial

1. Einführung

Dieser Artikel konzentriert sich auf diese drei Themen. Wie löst RR Phantomlesen?

Probleme im Zusammenhang mit RR und Phantom-Lesen in MySQL

  • MVCC -Prinzip

  • experiment: RR und Phantom Reading

  • case: Deadlock

First, lassen Sie uns die vier Arten von Transaktions -Isolierungen und gleichzeitigen Transaktionen untersuchen, die von InnoDB in MySQL gestützt werden. Einige Probleme :

Probleme im Zusammenhang mit RR und Phantom-Lesen in MySQL

  • Nicht festgeschrieben lesen: Es kann den Zwischenprozess einer Transaktion lesen, was die ACID-Eigenschaften verletzt und das Problem des schmutzigen Lesens aufweist, das grundsätzlich nicht verwendet wird.

  • Commit lesen: Zeigt an, dass Sie es sehen können, wenn andere Transaktionen übermittelt wurden. In Produktionsumgebungen wird es nicht häufig verwendet.

  • Wiederholbares Lesen: Standardstufe, die am häufigsten verwendete. Es verfügt über eine Gap-Sperre.

  • Serialisierbar: Alle Implementierungen werden durch Sperren implementiert.

Die gleichzeitige Transaktionsverarbeitung bringt auch einige Probleme mit sich: Dirty Reads, nicht wiederholbare Reads, Phantom Reads

  • Dirty Reads: Eine Transaktion ändert einen Datensatz, bevor die Transaktion abgeschlossen und übermittelt wird in einem inkonsistenten Zustand.

  • Nicht wiederholbares Lesen: Eine Transaktion wird gemäß den gleichen Abfragebedingungen zweimal gelesen und die gelesenen Daten sind inkonsistent (Änderung, Löschung).

  • Phantomlesung: Fragen Sie Daten gemäß denselben Abfragebedingungen innerhalb einer Transaktion erneut ab, stellen Sie jedoch fest, dass andere Transaktionen neue Daten eingefügt haben, die ihre Abfragebedingungen erfüllen.

Um den Kontext dieses Artikels zusammenzufassen: RR führt MVCC für eine schnellere Parallelität ein, es besteht jedoch die Möglichkeit des Phantomlesens, indem eine Gap-Sperre eingeführt wird, und Gap kann einen Deadlock verursachen.

2. Prinzip von MVCC

MVCC (Multiple Version Control): Bezieht sich auf die Datenbank, um einen hohen gleichzeitigen Datenzugriff und die Verarbeitung mehrerer Versionen von Daten zu erreichen und durch die Sichtbarkeit von Transaktionen sicherzustellen, dass Transaktionen sehen können, was sie tun sollte Datenversion sehen.

Der größte Vorteil von MVCC besteht darin, dass es keine Lesesperre gibt und es keinen Konflikt zwischen Lesen und Schreiben gibt.

Bei OLTP-Anwendungen (On-Line Transaction Processing) ist es wichtig, dass es keinen Konflikt zwischen Lesen und Schreiben gibt. Fast alle RDBMS unterstützen MVCC.

Hinweis: MVCC funktioniert nur unter zwei Isolationsstufen: Read-Commit RC und Repeatable Read RR.

Hinweis: MVCC funktioniert nur unter zwei Isolationsstufen: Read-Commit RC und Repeatable Read RR.

Hinweis: MVCC funktioniert nur unter zwei Isolationsstufen: Read-Commit RC und Repeatable Read RR.

(1) MVCC-Mehrversionsimplementierung

Wenn MySQL den MVCC-Mechanismus implementiert, basiert er auf der Undo-Log-Mehrversionskette + ReadView-Mechanismus.

  • Mehrversionskette des Rückgängig-Protokolls: Bei jeder Änderung der Datenbank werden die Transaktionsnummer des aktuellen Änderungsdatensatzes und die Speicheradresse des Datenstatus vor der Änderung (d. h. ROLL_PTR) im Rückgängig-Protokoll aufgezeichnet, sodass dies möglich ist kann bei Bedarf auf eine ältere Datenversion zurückgesetzt werden.

  • ReadView-Mechanismus: Steuern Sie basierend auf der Multiversionskette die Sichtbarkeit des Transaktionslesens. (Der Hauptunterschied ist: RC und RR)

Ich konzentriere mich hier nicht auf die Erkundung der Prinzipien, sondern ich brauche ein allgemeines Konzept: Rückgängigmachen der Protokollkette mit mehreren Versionen und ReadView-Mechanismus.

Für die Rückgängig-Protokoll-Mehrversionskette ist hier ein Beispiel:

  • Eine Lesetransaktion fragt den aktuellen Datensatz ab, aber die letzte Transaktion wurde noch nicht übermittelt.

  • Laut Atomizität können Lesetransaktionen nicht die neuesten Daten sehen, aber sie können ältere Versionen von Daten im Rollback-Segment finden und so mehrere Versionen generieren.

Für den ReadView-Mechanismus: Basierend auf der Implementierung der Rückgängig-Protokoll-Mehrversionskette hat unterschiedliche Transaktionsisolation unterschiedliche Verarbeitung:

  • Transaktionen auf RC-Ebene: Die Sichtbarkeit ist relativ hoch, es können alle Änderungen der übermittelten Transaktionen angezeigt werden.

  • Transaktionen auf RR-Ebene: Bei einer Lesetransaktion ändern sich die Abfragedatenergebnisse nicht, unabhängig davon, welche Änderungen andere Transaktionen an den Daten vornehmen und ob sie übermittelt werden, solange Sie sie nicht übermitteln.

Wie geht das?

RC-Leseübermittlung: Jede Leseoperationsanweisung erhält eine ReadView. Nach jeder Aktualisierung wird der neueste Transaktionsübermittlungsstatus in der Datenbank abgerufen, und Sie können die zuletzt übermittelte Transaktion sehen, dh die Sichtbarkeit jeder Anweisungsausführung wird aktualisiert Sicht.

RR wiederholbares Lesen: ReadView wird nicht abgerufen, wenn eine Transaktion gestartet wird. ReadView wird nur abgerufen, wenn das erste Snapshot-Lesen initiiert wird.

Wenn Sie den aktuellen Read verwenden, erhalten Sie eine neue ReadView und können auch die aktualisierten Daten sehen.

(2) Snapshot-Lesen und aktuelles Lesen

In der MVCC-Parallelitätssteuerung können Lesevorgänge in zwei Kategorien unterteilt werden:

Snapshot-Lesen: Lesen Sie die sichtbare Version des Datensatzes (möglicherweise die historische Version), nein muss gesperrt werden.

Bedienung: Einfache SELECT-Bedienung.

Aktueller Lesevorgang: Die neueste Version des Datensatzes wird gelesen und der vom aktuellen Lesevorgang zurückgegebene Datensatz wird gesperrt, um sicherzustellen, dass dieser Datensatz nicht gleichzeitig von anderen Transaktionen geändert wird.

Vorgänge: spezielle Lesevorgänge, Vorgänge zum Hinzufügen/Aktualisieren/Löschen.

-- 对应 SQL 如下:
-- 1. 特殊读操作
SELECT ... FOR UPDATE
SELECT ... LOCK IN SHARE MODE  -- 共享锁
-- 2. 新增:INSERT 
-- 3. 更新:UPDATE
-- 4. 删除:DELETE

Kombiniert mit dem ReadView-Mechanismus zur Unterscheidung zwischen Snapshot-Lesung und aktuellem Lesevorgang:

Snapshot-Lesung: In einer Transaktion wird ReadView nur abgerufen, wenn der erste Snapshot-Lesevorgang initiiert wird, und bei nachfolgenden Lesevorgängen wird es nicht erneut abgerufen.

Aktueller Lesevorgang: ReadView wird für jeden Lesevorgang abgerufen.

3. Experiment: RR und Phantomlesung

Interviewfrage: Unter der RR-Transaktionsisolationsstufe fragt Transaktion A ein Datenelement ab und Transaktion B fügt ein Datenelement hinzu. Kann Transaktion A die Daten von Transaktion B sehen?

Probleme im Zusammenhang mit RR und Phantom-Lesen in MySQL

Diese Frage ist relativ vage, aber wir wissen, dass der allgemeine Inspektionspunkt RR und Phantomlesung ist. Die Frage kann in zwei Kategorien unterteilt werden:

Unter welchen Umständen führt RR zu Phantomlesung? (Kann die Daten sehen)

Antwort: Aktueller Lesevorgang (AUSWÄHLEN.. FÜR UDPDATE, AUSWÄHLEN... IM TEILUNGSMODUS SPERREN)

Unter welchen Umständen löst RR Phantom-Lesevorgänge? (Daten können nicht angezeigt werden)

Antwort: Sperren, Snapshot-Lesen

Hinweis: Nicht wiederholbares Lesen konzentriert sich auf UPDATA und DELETE, während Phantom-Lesen sich auf INSERT konzentriert.

Der größte Unterschied zwischen ihnen besteht darin, wie die von ihnen verursachten Probleme durch den Sperrmechanismus gelöst werden.

Das hier erwähnte Schloss verwendet nur den pessimistischen Schließmechanismus.

Lassen Sie uns noch einmal einen Blick darauf werfen: Phantomlesung

-- 举个栗子:有这样一个查询 SQL
SELECT * FROM user WHERE id < 10;

Unter derselben Transaktion werden 4 Datenelemente bei T1 und 8 Datenelemente bei T2 abgefragt. Dadurch entsteht Phantomlesung.

Unter derselben Transaktion werden zum Zeitpunkt T1 8 Datenelemente und zum Zeitpunkt T2 4 Datenelemente abgefragt. Dadurch entsteht Phantomlesung.

Die Vorbereitung des Experiments ist wie folgt: Praktische Übung

show variables like &#39;transaction_isolation&#39;; -- 事务隔离级别 RR
select version();                            -- 版本 8.0.16
show variables like &#39;%storage_engine%&#39;;      -- 引擎 InnoDB
-- 1. 手动开启事务提交
begin;  -- 开始事务
commit; -- 提交事务
-- 2. 创建表
CREATE TABLE IF NOT EXISTS `student` (
`id` INT NOT NULL COMMENT &#39;主键 id&#39;,
`name` VARCHAR(50) NOT NULL COMMENT &#39;名字&#39;,
`age` TINYINT NOT NULL COMMENT &#39;年龄&#39;,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT &#39;学生表&#39;;
-- 3. 新增数据用于实验
INSERT INTO student (id, name, age) VALUES (5, &#39;kunkun&#39;, 14);
INSERT INTO student (id, name, age) VALUES (30, &#39;ikun&#39;, 18);

(1) RR erzeugt Phantomablesung

Das Experiment ist wie folgt: Testen Sie die aktuelle Lesung

Experiment 1: Zuerst AUSWÄHLEN, dann AUSWÄHLEN. .. FÜR UPDATE

Experiment 2: Zuerst AUSWÄHLEN, dann UPDATE (es erfolgt keine Phantomablesung)

Experiment 1: Zuerst AUSWÄHLEN, dann AUSWÄHLEN... FÜR UPDATE

-- 事务A:
BEGIN;
SELECT * FROM student WHERE id < 30;
SELECT * FROM student WHERE id < 30 FOR UPDATE;  -- 等待事务B commit 后再执行
-- SELECT * FROM student WHERE id < 30 LOCK IN SHARE MODE;
COMMIT;
-- 事务B:
BEGIN;
INSERT INTO student (id, name, age) VALUES (20, &#39;wulikun&#39;, 16);
COMMIT;

Was passiert ist, ist wie im Bild unten dargestellt:

Probleme im Zusammenhang mit RR und Phantom-Lesen in MySQL

Die Experimentaufzeichnung ist wie im Bild unten dargestellt:

Probleme im Zusammenhang mit RR und Phantom-Lesen in MySQL

Fazit des Phänomens: Bei Verwendung des aktuellen Lesevorgangs (AUSWÄHLEN ... FÜR AKTUALISIERUNG) kommt es zu Phantom-Lesevorgängen.

Ähnlich führt die Verwendung von SELECT ... LOCK IN SHARE MODE zu Phantom-Lesevorgängen.

Probleme im Zusammenhang mit RR und Phantom-Lesen in MySQL

Experiment 2: Zuerst auswählen, dann update

rrree

What ist wie im Bild unten gezeigt:

Probleme im Zusammenhang mit RR und Phantom-Lesen in MySQL

Die Experiment -Datensatz ist wie im Bild unten gezeigt:

Probleme im Zusammenhang mit RR und Phantom-Lesen in MySQL

Schlussfolgerung des Phänomens: Der aktuelle Messwert (UPDATE) generiert keine Phantom-Lesevorgänge. Weder INSERT noch DELETE bewirken dasselbe. (2) RR löst Phantomlesung ing-Aufzeichnungen)

Probleme im Zusammenhang mit RR und Phantom-Lesen in MySQL

Experiment 3: Sperren (AUSWÄHLEN... FÜR UPDATE)

Experiment 1: Snapshot-Lesung, gewöhnliches SELECT

-- 事务A:
BEGIN;
SELECT * FROM student WHERE id < 30;
UPDATE student SET name = &#39;zhiyin&#39; WHERE id = 5;  -- 等待事务B commit 后再执行
SELECT * FROM student WHERE id < 30;
COMMIT;
-- 事务B:
BEGIN;
INSERT INTO student (id, name, age) VALUES (20, &#39;wulikun&#39;, 16);
COMMIT;

Was passiert, ist wie unten gezeigt:
  • Die Experimentaufzeichnung ist wie unten gezeigt :
  • Fazit zum Phänomen: Unter der RR-Transaktionsisolationsstufe führen nur Snapshot-Lesevorgänge (SELECT) nicht zu Phantom-Lesevorgängen. Es liegt keine aktuelle Lesung vor.

  • Experiment 2: Sperren (Aktualisieren nicht vorhandener Datensätze)

Unter der RR-Isolationsstufe verwendet Transaktion A UPDATE zum Sperren, Transaktion B kann dazwischen keine neuen Daten einfügen, sodass Transaktion A vor und nach UPDATE die Daten liest bleibt konsistent und Phantom-Reads werden vermieden.

-- 事务A:
BEGIN;
SELECT * FROM student;
SELECT * FROM student;  -- 等待事务B commit 后再执行
COMMIT;
-- 事务B:
BEGIN;
INSERT INTO student (id, name, age) VALUES (20, &#39;wulikun&#39;, 16);
COMMIT;

Was passiert ist, ist im Bild unten zu sehen:

Probleme im Zusammenhang mit RR und Phantom-Lesen in MySQL

实验记录如下图所示:

Probleme im Zusammenhang mit RR und Phantom-Lesen in MySQL

现象结论:

一开始先加 临键锁Next-key lock,锁范围为 (5,30]。

因为是唯一索引,且更新的记录不存在,临键锁退化成 间隙锁Gap,最终锁范围为 (5,30)。其余的记录不受影响。

实验三:加锁(SELECT ... FOR UPDATE)

-- 事务A:
BEGIN;
SELECT * FROM student;
SELECT * FROM student WHERE id < 5 FOR UPDATE;
COMMIT;
-- 事务B:
BEGIN;
INSERT INTO student (id, name, age) VALUES (4, &#39;zhiyin&#39;, 4); -- 需要等待事务A结束。
COMMIT;
-- 事务C:
BEGIN;
INSERT INTO student (id, name, age) VALUES (5, &#39;zhiyin你太美&#39;, 32); -- 插入成功
COMMIT;
-- 查询数据库中当前有哪些锁
SELECT INDEX_NAME,LOCK_TYPE,LOCK_MODE,LOCK_STATUS,LOCK_DATA FROM performance_schema.data_locks;

发生情况如下图所示:

Probleme im Zusammenhang mit RR und Phantom-Lesen in MySQL

实验记录如下图所示:

Probleme im Zusammenhang mit RR und Phantom-Lesen in MySQL

现象结论:

先加 临键锁Next-key lock,锁范围为 (-∞,5]。

所以,id

拓展:Gap 锁(间隙锁)

根据 官方文档 可知:

  • 锁是加在索引上的。

  • 记录锁: 行锁,只会锁定一条记录。

  • 间隙锁 :是在索引记录之间的间隙上的锁,区间为前开后开 (,)。

  • 临键锁(Next-Key Lock): 由 记录锁 和 间隙锁Gap 组合起来。

  • 加锁的基本单位是 临键锁,其加锁区间为前开后闭 (,]。

  • 索引上的等值查询,给唯一索引加锁的时候,如果满足条件,临键锁 退化为 行锁。

  • 索引上的等值查询,给唯一索引加锁的时候,如果不满足条件,临键锁 退化为 间隙锁。注意,非等值查询是不会优化的。

推荐学习:mysql视频教程

Das obige ist der detaillierte Inhalt vonProbleme im Zusammenhang mit RR und Phantom-Lesen in MySQL. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:juejin.im. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen