Heim >Datenbank >MySQL-Tutorial >Beispielanalyse von vier Transaktionsisolationsstufen in MySQL
Um bei Datenbankoperationen die Richtigkeit gleichzeitig gelesener Daten wirksam sicherzustellen, wird die Transaktionsisolationsstufe vorgeschlagen. Es gibt 4 Isolationsstufen für Datenbanktransaktionen. Der SQL-Standard definiert 4 Isolationsstufen, einschließlich einiger spezifischer Regeln, um einzuschränken, welche Änderungen innerhalb und außerhalb der Transaktion sichtbar und welche unsichtbar sind. Der folgende Artikel analysiert die relevanten Informationen zu den vier Transaktionsisolationsstufen in MySQL anhand von Beispielen im Detail.
Vorwort
Im Folgenden gibt es nicht viel zu sagen, werfen wir einen Blick auf die ausführliche Einleitung.
Es gibt vier Isolationsstufen für Datenbanktransaktionen:
Nicht festgeschrieben lesen: Dirty Reads sind zulässig, das heißt, nicht festgeschriebene Transaktionen in anderen Sitzungen können geänderte Daten gelesen werden.
Read Committed: Nur übermittelte Daten können gelesen werden. Die meisten Datenbanken wie Oracle verwenden standardmäßig diese Ebene.
Wiederholtes Lesen: Wiederholbares Lesen. Abfragen innerhalb derselben Transaktion sind zu Beginn der Transaktion konsistent, InnoDB-Standardebene. Im SQL-Standard eliminiert diese Isolationsstufe nicht wiederholbare Lesevorgänge, es gibt jedoch weiterhin Phantom-Lesevorgänge.
Serielles Lesen (serialisierbar): Für jedes Lesen ist eine gemeinsame Sperre auf Tabellenebene erforderlich, und Lesen und Schreiben blockieren sich gegenseitig.
Freunde, die zum ersten Mal mit dem Konzept der Transaktionsisolation konfrontiert werden, könnten durch die obige Lehrbuchdefinition verwirrt sein. Lassen Sie uns die vier Isolationsstufen anhand konkreter Beispiele erklären.
Zuerst erstellen wir eine Benutzertabelle:
CREATE TABLE user ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) NOT NULL, PRIMARY KEY (`id`), UNIQUE `uniq_name` USING BTREE (name) ) ENGINE=`InnoDB` AUTO_INCREMENT=10 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
Nicht festgeschriebene Isolationsstufe lesen
Wir legen zunächst die Isolationsstufe der Transaktion fest, um festgeschrieben zu lesen:
mysql> set session transaction isolation level read uncommitted; Query OK, 0 rows affected (0.00 sec) mysql> select @@session.tx_isolation; +------------------------+ | @@session.tx_isolation | +------------------------+ | READ-UNCOMMITTED | +------------------------+ 1 row in set (0.00 sec)
Nachfolgend haben wir zwei Terminals geöffnet, um Transaktion eins bzw. Transaktion zwei zu simulieren. PS: Operation eins und Operation zwei sollen in chronologischer Reihenfolge ausgeführt werden.
Transaktion 1
mysql> start transaction; # 操作1 Query OK, 0 rows affected (0.00 sec) mysql> insert into user(name) values('ziwenxie'); # 操作3 Query OK, 1 row affected (0.05 sec)
Transaktion 2
mysql> start transaction; # 操作2 Query OK, 0 rows affected (0.00 sec) mysql> select * from user; # 操作4 +----+----------+ | id | name | +----+----------+ | 10 | ziwenxie | +----+----------+ 1 row in set (0.00 sec)
Aus den obigen Ausführungsergebnissen ist deutlich ersichtlich, dass wir uns unter der nicht festgeschriebenen Leseebene in Transaktion eins befinden Es ist möglich, Daten zu lesen, die in Transaktion zwei nicht festgeschrieben wurden, was ein Dirty Read ist.
Festgeschriebene Isolationsstufe lesen
Das oben genannte Dirty-Read-Problem kann gelöst werden, indem die Isolationsstufe auf festgeschrieben gesetzt wird.
mysql> set session transaction isolation level read committed;
Transaktion 1
mysql> start transaction; # 操作一 Query OK, 0 rows affected (0.00 sec) mysql> select * from user; # 操作三 +----+----------+ | id | name | +----+----------+ | 10 | ziwenxie | +----+----------+ 1 row in set (0.00 sec) mysql> select * from user; # 操作五,操作四的修改并没有影响到事务一 +----+----------+ | id | name | +----+----------+ | 10 | ziwenxie | +----+----------+ 1 row in set (0.00 sec) mysql> select * from user; # 操作七 +----+------+ | id | name | +----+------+ | 10 | lisi | +----+------+ 1 row in set (0.00 sec) mysql> commit; # 操作八 Query OK, 0 rows affected (0.00 sec)
Transaktion 2
mysql> start transaction; # 操作二 Query OK, 0 rows affected (0.00 sec) mysql> update user set name='lisi' where id=10; # 操作四 Query OK, 1 row affected (0.06 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> commit; # 操作六 Query OK, 0 rows affected (0.08 sec)
Obwohl das Dirty-Read-Problem gelöst wurde, beachten Sie bitte, dass in Vorgang 7 von Transaktion 1 Transaktion 2. Nach der Festschreibung von Operation 1 liest Transaktion 1 unterschiedliche Daten in derselben Transaktion. Dies ist ein nicht wiederholbares Leseproblem. Durch die Verwendung der dritten Transaktionsisolationsstufe kann dieses Problem gelöst werden.
Repeatable Read Isolation Level
Die Standardtransaktionsisolationsstufe der Innodb-Speicher-Engine von MySQL ist die Repeatable Read Isolationsstufe, sodass wir keine zusätzlichen Einstellungen vornehmen müssen.
Transaktion 1
mysql> start tansactoin; # 操作一 mysql> select * from user; # 操作五 +----+----------+ | id | name | +----+----------+ | 10 | ziwenxie | +----+----------+ 1 row in set (0.00 sec) mysql> commit; # 操作六 Query OK, 0 rows affected (0.00 sec) mysql> select * from user; # 操作七 +----+------+ | id | name | +----+------+ | 10 | lisi | +----+------+ 1 row in set (0.00 sec)
Transaktion 2
mysql> start tansactoin; # 操作二 mysql> update user set name='lisi' where id=10; # 操作三 Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> commit; # 操作四
In Vorgang 5 von Transaktion 1 haben wir die Aktualisierung von Transaktion 2 in Vorgang 3 nicht gelesen. Die aktualisierte Daten können erst nach dem Festschreiben gelesen werden.
Hat Innodb Phantom-Lesevorgänge gelöst?
Tatsächlich können Phantom-Lesevorgänge auf RR-Ebene auftreten. Die InnoDB-Engine gibt offiziell an, die MVCC-Mehrversions-Parallelitätskontrolle zu verwenden, um dieses Problem zu lösen dass Innodb wirklich ist. Wurde die Phantomlesung gelöst?
Zur Vereinfachung der Anzeige habe ich die Benutzertabelle oben geändert:
mysql> alter table user add salary int(11); Query OK, 0 rows affected (0.51 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> delete from user; Query OK, 1 rows affected (0.07 sec) mysql> insert into user(name, salary) value('ziwenxie', 88888888); Query OK, 1 row affected (0.07 sec) mysql> select * from user; +----+----------+----------+ | id | name | salary | +----+----------+----------+ | 10 | ziwenxie | 88888888 | +----+----------+----------+ 1 row in set (0.00 sec)
Transaktion 1
mysql> start transaction; # 操作一 Query OK, 0 rows affected (0.00 sec) mysql> update user set salary='4444'; # 操作六,竟然影响了两行,不是说解决了幻读么? Query OK, 2 rows affected (0.00 sec) Rows matched: 2 Changed: 2 Warnings: 0 mysql> select * from user; # 操作七, Innodb并没有完全解决幻读 +----+----------+--------+ | id | name | salary | +----+----------+--------+ | 10 | ziwenxie | 4444 | | 11 | zhangsan | 4444 | +----+----------+--------+ 2 rows in set (0.00 sec) mysql> commit; # 操作八 Query OK, 0 rows affected (0.04 sec)
Transaktion 2
mysql> start transaction; # 操作二 Query OK, 0 rows affected (0.00 sec) mysql> insert into user(name, salary) value('zhangsan', '666666'); # 操作四 Query OK, 1 row affected (0.00 sec) mysql> commit; # 操作五 Query OK, 0 rows affected (0.04 sec)
Wie aus dem obigen Beispiel ersichtlich ist, löst Innodb das Phantomlesen nicht, wie offiziell angegeben, aber das obige Szenario kommt nicht sehr häufig vor und es besteht kein Grund zur Sorge.
Serialisierungsisolationsstufe
Alle Transaktionen werden seriell ausgeführt. Auf der höchsten Isolationsstufe treten keine Phantomlesevorgänge auf und die Leistung wird in der tatsächlichen Entwicklung selten verwendet.
Verwandte Empfehlungen:
Beispiel-Tutorial zur MySQL-Transaktionsisolationsstufe
Detaillierte Erklärung und Vergleich der vier Transaktionsisolationsstufen von MySQL
Eine kurze Analyse der Auswirkungen der MySQL-Transaktionsisolationsstufe auf ihre Leistung
Das obige ist der detaillierte Inhalt vonBeispielanalyse von vier Transaktionsisolationsstufen in MySQL. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!