首頁  >  文章  >  資料庫  >  什麼是Mysql Innodb事務隔離等級?

什麼是Mysql Innodb事務隔離等級?

青灯夜游
青灯夜游轉載
2019-02-26 11:19:011869瀏覽

本篇文章帶給大家的內容是介紹什麼是Mysql Innodb事務隔離等級?有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。

Mysql的交易隔離等級有四種,如下:

 1、Read Uncommitted:它允許讀取其它交易改變但未提交的髒資料,同樣會導致不可重複讀取幻讀問題。

 2、Read Committed:可避免讀取髒資料,仍會導致無法重複讀取幻讀問題。

 3、REPEATABLE-READ:Mysql預設隔離等級,會導致幻讀.但mysql此等級採用MVCC一致性讀,也不會產生幻讀。

 4、Serializable:最高隔離等級,會避免出現上面的問題.

可用以下方法查看目前系統的隔離等級

mysql> select @@global.tx_isolation,@@tx_isolation;
+-----------------------+-----------------+
| @@global.tx_isolation | @@tx_isolation  |
+-----------------------+-----------------+
| REPEATABLE-READ       | REPEATABLE-READ |
+-----------------------+-----------------+
1 row in set (0.00 sec)

未提交讀取READ-UNCOMMITTED 髒讀、不可重複讀取範例:

#session A
mysql> set session transaction isolation level read uncommitted;   #设置隔离级别为未提交读
Query OK, 0 rows affected (0.00 sec)

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from inno_tbl where id=2;
+----+------+
| id | name |
+----+------+
|  2 | John |
+----+------+
1 row in set (0.00 sec)
#session B
mysql> select @@tx_isolation;
+-----------------+
| @@tx_isolation  |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set (0.00 sec)

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> update inno_tbl set name='Jack Ma' where id=2;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0
#session A
mysql> select * from inno_tbl where id=2;
+----+---------+
| id | name    |
+----+---------+
|  2 | Jack Ma |
+----+---------+
1 row in set (0.00 sec)

此時session A讀取到了session B修改但未提交的數據,若此時session B回滾,則A讀取到的數據便是無效的,這便是“髒數據”,由於A第一次讀取到的數據與第二次讀取到的數據不同,這便是“不可重複讀”;同理,或在B中插入新數據,A中此事務中也會讀取的新的數據行,這便是幻讀。

相同的流程,將A的隔離等級改為read committed,則不會產生“髒讀”,但同樣會產生“不可重複讀”和“幻讀”

默認隔離等級REPEATABLE-READ下:

#session A
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from inno_tbl where id=2;
+----+--------------+
| id | name         |
+----+--------------+
|  2 | John         |
+----+--------------+
1 row in set (0.00 sec)
#session B
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> update inno_tbl set name='Lucy' where id=2; 
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0
mysql> commit;
Query OK, 0 rows affected (0.03 sec)
#session A
mysql> select * from inno_tbl where id=2;
+----+--------------+
| id | name         |
+----+--------------+
|  2 | John         |
+----+--------------+
1 row in set (0.00 sec)
#注意,此时没有产生“不可重复读”问题,但若是为查询加上共享锁:
mysql> select * from inno_tbl1 where id=2 lock in share mode;
+----+---------+
| id | name    |
+----+---------+
|  2 | Lucy    |
+----+---------+
1 row in set (0.00 sec)

說明:

會話A中的交易讀取到id為2的inno_tbl表中的name欄位為John,而如果此時會話B中的交易將inno_tbl中id為2的name改為Lucy並提交,若些時A中的事務再讀取此行資料時,會發現,如果直接使用select方式查詢,讀出的數據依然是舊的數據,而加上共享鎖,會讀出真正的數據。

Why?因為在innodb引擎中,mysql的增刪改查語句可以分為兩種:一種是快照讀#,一種是目前讀。 只有普通的查詢語句為快照讀,而剩餘的增刪改和加上lock in share mode共享鎖或加上for update排它鎖的查詢語句,都屬於當前讀;當時讀讀取的是最新的數據,而快照讀取讀取的不一定是最新的數據。

由此可推出:當在session A中以條件為name=John來更新或刪除時,肯定不會更新或刪除成功,如下所示:

mysql> update inno_tbl set name='张三' where name='John';
Query OK, 0 rows affected (0.00 sec)
Rows matched: 0  Changed: 0  Warnings: 0
mysql> delete from inno_tbl where name='John';
Query OK, 0 rows affected (0.00 sec)

如果把隔離等級改成Read Commited, 則A會話中的查詢語句不用加lock in share mode 或for update便可查詢出B會話中已經更改提交的最新內容. 這種情況叫做不可重複讀。寫到這裡, 我有個小疑問, 是不是不可重複讀幻讀是不是互相矛盾呢? 答:不是, 不可重複讀主要針對修改, 幻讀主要針對插入和刪除。

以上是什麼是Mysql Innodb事務隔離等級?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:segmentfault.com。如有侵權,請聯絡admin@php.cn刪除