數據庫事務的隔離級別有4個,由低到高依次為
- Read uncommitted:允許臟讀。
- Read committed: 防止臟讀,最常用的隔離級別,并且是大多數數據庫的默認隔離級別。
- Repeatable read:可以防止臟讀和不可重復讀。
- Serializable:可以防止臟讀,不可重復讀取和幻讀,(事務串行化)會降低數據庫的效率。
這四個級別可以逐個解決臟讀 、不可重復讀 、幻讀 這幾類問題。
√: 可能出現 ×: 不會出現
事務級別 | 臟讀 | 不可重復讀 | 幻讀 |
---|---|---|---|
Read uncommitted | √ | √ | √ |
Read committed | × | √ | √ |
Repeatable read | × | × | √ |
Serializable | × | × | × |
注意:我們討論隔離級別的場景,主要是在多個事務并發的情況下。
臟讀、幻讀、不可重復讀
臟讀:
臟讀就是指當一個事務正在訪問數據,并且對數據進行了修改,而這種修改還沒有提交到數據庫中,這時,另外一個事務也訪問這個數據,然后使用了這個數據。
不可重復讀:
是指在一個事務內,多次讀同一數據。在這個事務還沒有結束時,另外一個事務也訪問該同一數據。那么,在第一個事務中的兩次讀數據之間,由于第二個事務的修改,那么第一個事務兩次讀到的的數據可能是不一樣的。這樣就發生了在一個事務內兩次讀到的數據是不一樣的,因此稱為是不可重復讀。(即不能讀到相同的數據內容)
幻讀:
是指當事務不是獨立執行時發生的一種現象,例如第一個事務對一個表中的數據進行了修改,這種修改涉及到表中的全部數據行。同時,第二個事務也修改這個表中的數據,這種修改是向表中插入一行新數據。那么,以后就會發生操作第一個事務的用戶發現表中還有沒有修改的數據行,就好象發生了幻覺一樣。
example:
表:
1
2
3
4
5
6
7
|
CREATE TABLE `cc_wsyw126_user_test_isolation_copy` ( `id` int (11) NOT NULL AUTO_INCREMENT, ` password ` varchar (64) NOT NULL , `age` int (11) NOT NULL , PRIMARY KEY (`id`), KEY `ix_age` (`age`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; |
模擬數據:
1
2
3
4
5
6
|
INSERT INTO `cc_wsyw126_user_test_isolation_copy` (` password `, `age`) VALUES ( '1' , 1), ( '2' , 2), ( '3' , 3), ( '4' , 4); |
第一個事務A:
1
2
3
|
start transaction insert into cc_wsyw126_user_test_isolation_copy ( password , age) values ( '5' ,5) commit |
第二個事務B:
1
2
3
4
|
start transaction update cc_wsyw126_user_test_isolation_copy set age = 2 where password >= '2' select * from cc_wsyw126_user_test_isolation_copy where password >= '2' ; commit |
重現步驟:
只要A事務的insert語句,在B事務select之前和update之后即可。
MySQL InnoDB存儲引擎,實現的是基于多版本的并發控制協議——MVCC (Multi-Version Concurrency Control) 加上間隙鎖(next-key locking)策略在Repeatable Read (RR)隔離級別下不存在幻讀。如果測試幻讀,在MyISAM下實驗。
在聚集索引(主鍵索引)中,如果有唯一性約束,InnoDB會將默認的next-key lock降級為record lock。
感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!
原文鏈接:http://blog.csdn.net/wsyw126/article/details/61429459