【面試必備】快速理解數據庫事務隔離級別


圖片顯示異常可前往https://juejin.im/post/5d5575dde51d4561a705badd查看

事務簡介

相信用過MySQL的朋友都知道事務,我們也常常通過這個例子來講解事務的作用:A向B轉賬,這里可以分為兩步操作數據庫,A賬戶余額減少,B賬戶余額增加。但是,如果在A賬戶余額減少的時候突然出現了數據庫宕機了等情況,是不是會出現A的余額變少了,但是B的余額卻沒有增加的情況呢?答案是否定的。原因就是數據庫支持事務(常用的關系型數據,如MySQL、Oracle等)。

事務是應用程序中一系列嚴密的操作,所有操作必須成功完成,否則在每個操作中所作的所有更改都會被撤消。也就是事務具有原子性,一個事務中的一系列的操作要么全部成功,要么一個都不做。

事務的結束有兩種,當事務中的所以步驟全部成功執行時,事務提交。如果其中一個步驟失敗,將發生回滾操作,撤消撤消之前到事務開始時的所以操作。

事務的ACID特性

這個是一個老生常談的問題,面試中也經常會問:事務的ACID特性分別是什么?這里的ACID分別代表四個單詞:原子性( Atomicity )、一致性( Consistency )、隔離性( Isolation )和持續性( Durability )。

1 、原子性。事務是數據庫的邏輯工作單位,事務中包含的各操作要么都做,要么都不做

2 、一致性。事 務執行的結果必須是使數據庫從一個一致性狀態變到另一個一致性狀態。因此當數據庫只包含成功事務提交的結果時,就說數據庫處於一致性狀態。如果數據庫系統 運行中發生故障,有些事務尚未完成就被迫中斷,這些未完成事務對數據庫所做的修改有一部分已寫入物理數據庫,這時數據庫就處於一種不正確的狀態,或者說是 不一致的狀態。

3 、隔離性。一個事務的執行不能受其它事務干擾。即一個事務內部的操作及使用的數據對其它並發事務是隔離的,並發執行的各個事務之間不能互相干擾。

4 、持續性。也稱永久性,指一個事務一旦提交,它對數據庫中的數據的改變就應該是永久性的。接下來的其它操作或故障不應該對其執行結果有任何影響。

事務的隔離級別

說事務隔離級別之前,先看看如下問題:

1、臟讀(Dirty Read)

所謂臟讀是指一個事務中訪問到了另外一個事務未提交的數據。如A事務對一條數據進行了修改,但是事務還沒提交,此時B事務讀到了A事務修改了但是未提交的數據,這就是臟讀。

2、不可重復讀(Non-repeatable read)

是指在一個事務內,多次讀同一數據。在這個事務還沒有結束時,另外一個事務也訪問該同一數據。那么,在第一個事務中的兩 次讀數據之間,由於第二個事務的修改,那么第一個事務兩次讀到的的數據可能是不一樣的。這樣就發生了在一個事務內兩次讀到的數據是不一樣的,因此稱為是不 可重復讀。

3、幻讀(Phantom Read)

所謂幻讀是指同一個事務內多次查詢返回的結果集不一樣(比如增加了或者減少了行記錄)。比如同一個事務A內第一次查詢時候有n條記錄,但是第二次同等條件下查詢卻又n+1條記錄,這就好像產生了幻覺,為啥兩次結果不一樣那。其實和不可重復讀一樣,發生幻讀的原因也是另外一個事務新增或者刪除或者修改了第一個事務結果集里面的數據。不同在於不可重復讀是同一個記錄的數據內容被修改了,幻讀是數據行記錄變多了或者少了

了解了如上幾個問題之后,我們再來看看四種事務隔離級別。

1、Read Uncommitted(讀取未提交內容)

在該隔離級別,所有事務都可以看到其他未提交事務的執行結果。本隔離級別很少用於實際應用,因為它的性能也不比其他級別好多少。讀取未提交的數據,也被稱之為臟讀。

2、Read Committed(讀取提交內容)

這是大多數數據庫系統的默認隔離級別(但不是MySQL默認的)。它滿足了隔離的簡單定義:一個事務只能看見已經提交事務所做的改變。這就是所謂的不可重復讀(Non-repeatable read)。

3、Repeatable Read(可重讀)

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

4、Serializable(串行化)

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

四種隔離級別可能出現的問題總結

除了性能最差的Serializable(串行化)隔離級別不會出現臟讀、不可重復讀、幻讀問題之外,其他的隔離級別都存在一個或多個問題。不過MySQL的InnoDB引擎通過MVCC的方式解決了Repeatable Read的幻讀問題。

事務隔離級別

查看隔離級別

# 查看當前連接的隔離級別
SELECT @@session.tx_isolation;
# 查看全局的事務隔離級別
SELECT @@global.tx_isolation;

設置事務隔離級別

1、全局修改

在mysql的配置文件上修改,如windows的mysql.ini,Linux為my.cnf。

#可選參數有:READ-UNCOMMITTED, READ-COMMITTED, REPEATABLE-READ, SERIALIZABLE.
[mysqld]
transaction-isolation = REPEATABLE-READ

2、通過命令對當前連接設置

# 可選參數為:read uncommitted、read committed、repeatable read、serializable
set session transaction isolation level xxx

關注公眾號領資料

搜索公眾號【Happyjava】,回復【電子書】和【視頻】,即可獲取大量優質電子書和大數據、kafka、nginx、MySQL等視頻資料
關注獲取資料


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM