mysql 4種事務隔離級別

SQL標準定義了4類隔離級別,包括了一些具體規則,用來限定事務內外的哪些改變是可見的,哪些是不可見的。低級別的隔離級通常支持更高的併發處理,並擁有更低的系統開銷。
Read Uncommitted(讀取未提交內容)
mysql

       在該隔離級別,全部事務均可以看到其餘未提交事務的執行結果。本隔離級別不多用於實際應用,由於它的性能也不比其餘級別好多少。讀取未提交的數據,也被稱之爲髒讀(Dirty Read)。
Read Committed(讀取提交內容)
web

       這是大多數數據庫系統的默認隔離級別(但不是MySQL默認的)。它知足了隔離的簡單定義:一個事務只能看見已經提交事務所作的改變。這種隔離級別 也支持所謂的不可重複讀(Nonrepeatable Read),由於同一事務的其餘實例在該實例處理其間可能會有新的commit,因此同一select可能返回不一樣結果。
Repeatable Read(可重讀)
sql

       這是MySQL的默認事務隔離級別,它確保同一事務的多個實例在併發讀取數據時,會看到一樣的數據行。不過理論上,這會致使另外一個棘手的問題:幻讀 (Phantom Read)。簡單的說,幻讀指當用戶讀取某一範圍的數據行時,另外一個事務又在該範圍內插入了新行,當用戶再讀取該範圍的數據行時,會發現有新的「幻影」 行。InnoDB和Falcon存儲引擎經過多版本併發控制(MVCC,Multiversion Concurrency Control)機制解決了該問題。數據庫

Serializable(可串行化) 
       這是最高的隔離級別,它經過強制事務排序,使之不可能相互衝突,從而解決幻讀問題。簡言之,它是在每一個讀的數據行上加上共享鎖。在這個級別,可能致使大量的超時現象和鎖競爭。
session

         這四種隔離級別採起不一樣的鎖類型來實現,若讀取的是同一個數據的話,就容易發生問題。例如:併發

         髒讀(Drity Read):某個事務已更新一份數據,另外一個事務在此時讀取了同一份數據,因爲某些緣由,前一個RollBack了操做,則後一個事務所讀取的數據就會是不正確的。性能

         不可重複讀(Non-repeatable read):在一個事務的兩次查詢之中數據不一致,這多是兩次查詢過程當中間插入了一個事務更新的原有的數據。spa

         幻讀(Phantom Read):在一個事務的兩次查詢中數據筆數不一致,例若有一個事務查詢了幾列(Row)數據,而另外一個事務卻在此時插入了新的幾列數據,先前的事務在接下來的查詢中,就會發現有幾列數據是它先前所沒有的。code

 

 mysql修改事務隔離級別orm

 

用戶能夠用SET TRANSACTION語句改變單個會話或者全部新進鏈接的隔離級別。它的語法以下:

SET [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE}

注意:默認的行爲(不帶session和global)是爲下一個(未開始)事務設置隔離級別。若是你使用GLOBAL關鍵字,語句在全局對從那點開始建立的全部新鏈接(除了不存在的鏈接)設置默認事務級別。你須要SUPER權限來作這個。使用SESSION 關鍵字爲未來在當前鏈接上執行的事務設置默認事務級別。 任何客戶端都能自由改變會話隔離級別(甚至在事務的中間),或者爲下一個事務設置隔離級別。 

你能夠用下列語句查詢全局和會話事務隔離級別:

SELECT @@global.tx_isolation;
SELECT @@session.tx_isolation;
SELECT @@tx_isolation;

 

示例:

 

 Repeatable Read

 

mysql> describe tb;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int(10)     | YES  |     | NULL    |       |
| name  | varchar(10) | YES  |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
mysql> select * from tb;
+------+------+
| id   | name |
+------+------+
|    1 | ddd  |
+------+------+
A B
mysql> SELECT @@session.tx_isolation;
+------------------------+
| @@session.tx_isolation |
+------------------------+
| REPEATABLE-READ        |
+------------------------+
mysql> start transaction;
mysql> select * from tb;
+------+------+
| id   | name |
+------+------+
|    1 | ddd  |
+------+------+
mysql> select @@session. tx_isolation;
+-------------------------+
| @@session. tx_isolation |
+-------------------------+
| REPEATABLE-READ         |
+-------------------------+
mysql> start transaction;
mysql> select * from tb;
+------+------+
| id   | name |
+------+------+
|    1 | ddd  |
+------+------+
mysql> insert into tb (id,name)values('12','323');
mysql> select * from tb;
+------+------+
| id   | name |
+------+------+
|    1 | ddd  |
|   12 | 323  |
+------+------+
mysql> select * from tb;
+------+------+
| id   | name |
+------+------+
|    1 | ddd  |
+------+------+
mysql> commit;
mysql> select * from tb;
+------+------+
| id   | name |
+------+------+
|    1 | ddd  |
|   12 | 323  |
+------+------+
mysql> select * from tb;
+------+------+
| id   | name |
+------+------+
|    1 | ddd  |
+------+------+
mysql> commit;
mysql> select * from tb;
+------+------+
| id   | name |
+------+------+
|    1 | ddd  |
|   12 | 323  |
READ UNCOMMITTED 讀取未提交內容
mysql> set session transaction isolation level READ UNCOMMITTED;
mysql> select @@session. tx_isolation;
+-------------------------+
| @@session. tx_isolation |
+-------------------------+
| READ-UNCOMMITTED        |
+-------------------------+
mysql> start transaction;
mysql> select * from tb;
+------+------+
| id   | name |
+------+------+
|    1 | ddd  |
|   12 | 323  |
+------+------+
mysql> select @@session. tx_isolation;
+-------------------------+
| @@session. tx_isolation |
+-------------------------+
| REPEATABLE-READ         |
+-------------------------+
mysql> start transaction;
mysql> update tb set name='aaa' where id='1';
mysql> select * from tb;
+------+------+
| id   | name |
+------+------+
|    1 | aaa  |
|   12 | 323  |
+------+------+
mysql> select * from tb;髒讀B還未提交
+------+------+
| id   | name |
+------+------+
|    1 | aaa  |
|   12 | 323  |
+------+------+
mysql> rollback;
mysql> select * from tb;
+------+------+
| id   | name |
+------+------+
|    1 | ddd  |
|   12 | 323  |
+------+------+
mysql> select * from tb;
+------+------+
| id   | name |
+------+------+
|    1 | ddd  |
|   12 | 323  |
+------+------+
mysql> commit;
Read Committed(讀取提交內容)
mysql> set session transaction isolation level read committed;
mysql> select @@session. tx_isolation;
+-------------------------+
| @@session. tx_isolation |
+-------------------------+
| READ-COMMITTED          |
+-------------------------+
mysql> start transaction;
mysql> select * from tb;
+------+------+
| id   | name |
+------+------+
|    1 | ddd  |
|   12 | 323  |
+------+------+
mysql> start transaction;
mysql> update tb set name='aaa' where id='1';
mysql> select * from tb;
+------+------+
| id   | name |
+------+------+
|    1 | ddd  |
|   12 | 323  |
+------+------+
mysql> commit;
mysql> select * from tb;
+------+------+
| id   | name |
+------+------+
|    1 | aaa  |
|   12 | 323  |
+------+------+
mysql> commit;
Serializable(可串行化)
mysql> set session transaction isolation level serializable;
mysql> select @@session. tx_isolation;
+-------------------------+
| @@session. tx_isolation |
+-------------------------+
| SERIALIZABLE            |
+-------------------------+
mysql> select @@session. tx_isolation;
+-------------------------+
| @@session. tx_isolation |
+-------------------------+
| REPEATABLE-READ         |
+-------------------------+
mysql> start transaction;
mysql> select * from tb;
+------+------+
| id   | name |
+------+------+
|    1 | aaa  |
|   12 | 323  |
+------+------+
mysql> start transaction;
mysql> update tb set name='bbb' where id='1';
沒有結果,須要等A事務提交或回滾
mysql> commit;
mysql> start transaction;
mysql> update tb set name='bbb' where id='1';
這裏成功,沒有鎖tb
mysql> select * from tb;
+------+------+
| id   | name |
+------+------+
|    1 | bbb  |
|   12 | 323  |
+------+------+
mysql> update tb set name='ccccc' where id='1';
又被鎖了,B不在事務狀態下
mysql> commit;
mysql> start transaction;
mysql> select * from tb where id='12';
+------+------+
| id   | name |
+------+------+
|   12 | 323  |
+------+------+
mysql> update tb set name='ddddd' where id='1';
表被鎖,不是行被鎖
相關文章
相關標籤/搜索