MySQL 溫故知心(二) 事務的隔離級別

事務的隔離級別mysql

A事務作了操做 沒有提交 對B事務來講 就等於沒作 獲取的都是以前的數據
可是 在A事務中查詢的話 查到的都是操做以後的數據
沒有提交的數據只有本身看獲得,並無update到數據庫sql

查看InnoDB存儲引擎系統級的隔離級別和會話級的隔離級別:數據庫

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

設置innodb的事務級別方法是:set 做用域 transaction isolation level 事務隔離級別,例如~session

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

mysql> set global transaction isolation level read committed; //全局的

mysql> set session transaction isolation level read committed; //當前會話

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

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

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

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

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

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

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

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

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

         在MySQL中,實現了這四種隔離級別,分別有可能產生問題以下所示:

 

事務的併發執行,容易出現的幾個現象
--------------------------
1.髒讀
讀未提交,一個事務讀取了另一個事務改寫尚未提交的數據,若是另一個
事務在稍後的時候回滾。

2.不可重複讀
一個事務進行相同條件查詢連續的兩次或者兩次以上,每次結果都不一樣。
有其餘事務作了update操做。

3.幻讀
和(2)很像,其餘事務作了insert操做.


隔離級別
----------------
爲了不出現哪一種並發現象的。
1 //read uncommitted ,讀未提交
2 //read committed ,讀已提交
4 //repeatable read ,能夠重複讀
8 //serializable ,串行化(悲觀鎖)

 

演示mysql事務隔離級別
------------------------
1.開啓mysql客戶端
mysql>
2.關閉自動提交
mysql>set autocommit 0 ;
3.每次操做數據,都要開啓事務,提交事務。

髒讀現象
----------------
[A]
1)mysql>start transaction ; -- 開始事務
2)msyql>update users set age = age + 1 where id = 1 ; -- 更新數據,沒有提交
6)mysql>rollback ; -- 回滾
7)mysql>select * from users ;

[B]
3)mysql>set session transaction isolation level read uncommitted ; -- 讀未提交
4)msyql>start transaction ; -- 開始事務
5)mysql>select * from users ; -- 13

避免髒讀
----------------
[A]
1)mysql>start transaction ; -- 開始事務
2)msyql>update users set age = age + 1 where id = 1 ; -- 更新數據,沒有提交
6)mysql>rollback ; -- 回滾
7)mysql>select * from users ;

[B]
3)mysql>set session transaction isolation level read committed ; -- 讀已提交
4)msyql>start transaction ; -- 開始事務
5)mysql>select * from users ; -- 13


測試不可重複讀(隔離級別設置爲讀已提交不能避免不可重複讀。)
------------------
[A]
1)mysql>commit ;
2)mysql>set session transaction isolation level read committed ; -- 讀已提交
3)mysql>start transaction ; -- 開始事務
4)mysql>select * from users ; -- 查詢
9)mysql>select * from users ;

[B]
5)mysql>commit;
6)mysql>start transaction ;
7)mysql>update users set age = 15 where id = 1 ; -- 更新
8)mysql>commit;

測試避免不可重複讀(隔離級別設置爲讀已提交不能避免不可重複讀。)
------------------
[A]
1)mysql>commit ;
2)mysql>set session transaction isolation level repeatable read ; -- 能夠重複讀
3)mysql>start transaction ; -- 開始事務
4)mysql>select * from users ; -- 查詢
9)mysql>select * from users ;

[B]
5)mysql>commit;
6)mysql>start transaction ;
7)mysql>update users set age = 15 where id = 1 ; -- 更新
8)mysql>commit;

 

測試幻讀(隔離級別設置爲repeatable)
------------------
[A]
1)mysql>commit ;
2)mysql>set session transaction isolation level serializable; -- 串行化
3)mysql>start transaction ; -- 開始事務
4)mysql>select * from users ; -- 查詢
9)mysql>select * from users ;

[B]
5)mysql>commit;
6)mysql>start transaction ;
7)mysql>insert into users(name,age) values('tomas',13); -- 更新
8)mysql>commit;


ANSI SQL
---------------------
美國國家標準結構SQL組
select * from users for update ;

MySQL
----------------------
1.支持四種隔離級別。
2.默認隔離級別是能夠重複讀。
3.隔離級別是seriable,不支持併發寫。

表級鎖------------------------- LOCK TABLE t WRITE; -- 加鎖(表級鎖,read) UNLOCK TABLES ; -- 解除本身全部的全部表級鎖

相關文章
相關標籤/搜索