MySQL verfügt über vier Stufen der Transaktionsisolation. Jede Stufe hat ein Zeichen oder eine numerische Zahl
LESEN -UNCOMMITTEDEs gibt Probleme mit Dirty Reads, nicht wiederholbaren Reads und Phantom Reads Problem mit nicht wiederholbaren Lesevorgängen und Phantom-Lesevorgängen Verwenden Sie den MMVC-Mechanismus, um wiederholbare Lesevorgänge zu implementieren Wir können den folgenden Befehl verwenden, um die Transaktionsisolationsstufe von Global/Session anzuzeigen/einzustellen Ich habe das Gefühl, dass Sie es herausfinden können, wenn Sie sorgfältig darüber nachdenken. Ein Beispiel für das Umkippen ist der Blog-Beitrag, der nicht blockierendes E/A mit asynchronem E/A gleichsetzt, und viele Artikel haben es tatsächlich ausgeliehen sind völlig anders. Nicht blockierendes IO ist ein Modus des synchronen IO, nicht des asynchronen IO. Die Missverständnisse der Öffentlichkeit wurden „korrigiert“, also kehren wir zum Thema zurück. Phantom-Lesevorgänge werden auf der RU-/RC-/RR-Ebene angezeigt. SERIALIZABLE eliminiert Phantom-Lesevorgänge und nicht wiederholbare Lesevorgänge unter RU/RC. Daher werden wir Phantom-Lesevorgänge auf der RR-Ebene untersuchen und andere ausschließen . Einmischung.Hinweis: Es besteht die Möglichkeit einer Phantomlesung auf RR-Ebene. Sie können jedoch auch die Methode des manuellen Hinzufügens einer X-Sperre zum Datensatz verwenden, um eine Phantomlesung zu verhindern. SERIALIZABLE verhindert Phantom-Lesevorgänge, indem es allen Transaktionen X-Sperren hinzufügt. In vielen Szenarien besteht in unserem Geschäfts-SQL jedoch nicht das Risiko von Phantom-Lesevorgängen. Obwohl die Verwendung von SERIALIZABLE die absolute Sicherheit von Transaktionen gewährleisten kann, führt sie zu vielen unnötigen Leistungseinbußen. Daher können Sie entsprechend den Geschäftsanforderungen entscheiden, ob das Risiko eines Phantomlesens besteht. Wenn dies nicht der Fall ist, wird dies sowohl für die Transaktionssicherheit als auch für die Leistung gelten Aus diesem Grund ist RR als Standardisolationsstufe von MySQL eine Transaktionsisolationsstufe und daher erforderlich. Korrektes Verständnis des Phantomlesens. Verstehen von Phantom-Lesefehlern: Es wird gesagt, dass Phantom-Lesen vorliegt, wenn Transaktion A zwei Auswahlvorgänge ausführt, um unterschiedliche Datensätze zu erhalten, dh Auswahl 1 erhält 10 Datensätze und Auswahl 2 erhält 11 Datensätze. Dies ist eigentlich kein Phantom-Lesevorgang. Dies ist eine Art nicht wiederholbarer Lesevorgang, der nur auf der R-U-R-C-Ebene, jedoch nicht auf der Standard-RR-Isolationsebene von MySQL erfolgt. Hier ist mein umgangssprachlicheres Verständnis des Phantomlesens: Phantomlesen bedeutet nicht, dass die durch zwei Lesevorgänge erhaltenen Ergebnismengen unterschiedlich sind. Der Fokus des Phantomlesens wird durch das Ergebnis einer bestimmten Auswahloperation dargestellt unterstützen den späteren Geschäftsbetrieb. Genauer gesagt: Wählen Sie aus, ob ein bestimmter Datensatz vorhanden ist, und bereiten Sie das Einfügen des Datensatzes vor. Bei der Ausführung wird jedoch festgestellt, dass der Datensatz bereits vorhanden ist und nicht eingefügt werden kann auftritt. Hier ist ein anschaulicheres Szenario des MySQL-Phantomlesens (aus meiner Antwort auf Zhihu entlehnt): mysql> SELECT @@global.tx_isolation, @@tx_isolation; +-----------------------+------------------+ | @@global.tx_isolation | @@tx_isolation | +-----------------------+------------------+ | REPEATABLE-READ | READ-UNCOMMITTED | +-----------------------+------------------+ 1 row in set (0.00 sec) # 设定全局的隔离级别 设定会话 global 替换为 session 即可 把set语法温习一下 # SET [GLOABL] config_name = 'foobar'; # SET @@[session.|global.]config_name = 'foobar'; # SELECT @@[global.]config_name; SET @@gloabl.tx_isolation = 0; SET @@gloabl.tx_isolation = 'READ-UNCOMMITTED'; SET @@gloabl.tx_isolation = 1; SET @@gloabl.tx_isolation = 'READ-COMMITTED'; SET @@gloabl.tx_isolation = 2; SET @@gloabl.tx_isolation = 'REPEATABLE-READ'; SET @@gloabl.tx_isolation = 3; SET @@gloabl.tx_isolation = 'SERIALIZABLE';
Nach dem Login kopieren
Transaktion T1 Transaktion T2 step2 T2: INSERT INTO `users` VALUES (1, 'big cat');step3 T1: INSERT INTO `users' VALUES (1, 'big cat'); step4 T1: SELECT * FROM `users` WHERE `id` = 1;
Unter der RR-Isolationsstufe werden Schritt 1 und Schritt 2 normal ausgeführt, aber Schritt 3 meldet einen Primärschlüsselkonfliktfehler. Für das Geschäft von T1 schlägt die Ausführung fehl, da sich T1 in Schritt 1 befindet Der Status der gelesenen Daten kann nachfolgende Geschäftsvorgänge nicht unterstützen. „Verdammt, das Ergebnis, das ich gerade gelesen habe, sollte meinen Vorgang auf diese Weise unterstützen können. Warum ist das jetzt nicht möglich?“ T1 konnte es nicht glauben und führte Schritt 4 erneut aus und stellte fest, dass das von setp1 gelesene Ergebnis dasselbe war (MMVC-Mechanismus unter RR). An diesem Punkt ist zweifellos ein Phantom-Lesen aufgetreten, egal wie oft T1 ihn liest, es kann den Datensatz mit der ID = 1 nicht finden, aber es kann diesen Datensatz nicht einfügen, von dem es beim Lesen festgestellt hat, dass er nicht existiert (diese Daten wurden von eingefügt). T2), für T1 lautet es Phantom. Tatsächlich kann RR auch Phantomlesevorgänge vermeiden, indem eine Zeile manuell hinzugefügt wird. Selbst wenn der aktuelle Datensatz nicht vorhanden ist, z. B. id=1 nicht vorhanden ist, erhält die aktuelle Transaktion eine Datensatzsperre (da die Zeilensperre von InnoDB den Index sperrt). Es spielt keine Rolle, ob die Datensatzentität vorhanden ist oder nicht. Wenn sie vorhanden ist, fügen Sie eine Zeilen-X-Sperre hinzu. Wenn sie nicht vorhanden ist, fügen Sie eine X-Sperre für die nächste Schlüsselsperre hinzu. Andere Transaktionen können keine Datensätze in diesen Index einfügen, daher Phantom Lesevorgänge werden eliminiert. Unter der Isolationsstufe SERIALIZABLE werden Zeilensperren (X)/Lückensperren (X) implizit hinzugefügt, wenn Schritt1 ausgeführt wird, sodass Schritt2 blockiert wird, Schritt3 normal ausgeführt wird und T2 nach der Übermittlung von T1 weiterhin ausgeführt werden kann. (Die Ausführung des Primärschlüsselkonflikts ist fehlgeschlagen.) Die erfolgreiche Blockierung hat das Geschäft von T1 gestört. 所以 mysql 的幻读并非什么读取两次返回结果集不同,而是事务在插入事先检测不存在的记录时,惊奇的发现这些数据已经存在了,之前的检测读获取到的数据如同鬼影一般。 这里要灵活的理解读取的意思,第一次select是读取,第二次的 insert 其实也属于隐式的读取,只不过是在 mysql 的机制中读取的,插入数据也是要先读取一下有没有主键冲突才能决定是否执行插入。 不可重复读侧重表达 读-读,幻读则是说 读-写,用写来证实读的是鬼影。 RR级别下防止幻读RR级别下只要对 SELECT 操作也手动加行(X)锁即可类似 SERIALIZABLE 级别(它会对 SELECT 隐式加锁),即大家熟知的: # 这里需要用 X锁, 用 LOCK IN SHARE MODE 拿到 S锁 后我们没办法做 写操作 SELECT `id` FROM `users` WHERE `id` = 1 FOR UPDATE;
Nach dem Login kopieren
如果 id = 1 的记录存在则会被加行(X)锁,如果不存在,则会加 next-lock key / gap 锁(范围行锁),即记录存在与否,mysql 都会对记录应该对应的索引加锁,其他事务是无法再获得做操作的。 这里我们就展示下 id = 1 的记录不存在的场景,FOR UPDATE 也会对此 “记录” 加锁,要明白,InnoDB 的行锁(gap锁是范围行锁,一样的)锁定的是记录所对应的索引,且聚簇索引同记录是直接关系在一起的。 id = 1 的记录不存在,开始执行事务: T1事务符合业务需求成功执行,T2干扰T1失败。 SERIALIZABLE级别杜绝幻读在这个层面上,我们不必对 SELECT 操作进行显式加锁,因为InnoDB会自动加锁以确保事务的安全性,但是这会导致性能较低 step1: T1 查询 id = 2 的记录,InnoDB 会隐式的对齐加 X锁 T1事务符合业务需求成功执行,T2干扰T1失败。 |
---|
Das obige ist der detaillierte Inhalt vonSo lösen Sie das MySQL-Phantom-Lesen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!