眾所周知MySQL從5.5.8開始,Innodb就是默認的存儲引擎,Innodb最大的特點是:支持事務、支持行級鎖。 既然支持事務,那么就會有處理並發事務帶來的問題:更新丟失、臟讀、不可重復讀、幻讀;相應的為了解決這四個問題, 就產生了事務隔離級別:未提交讀(Read uncommitted),已提交讀(Read committed),可重復讀(Repeatable read),可序列化(Serializable)。
事務的特性:
原子性:指處於同一個事務中的多條語句是不可分割的。即它對數據庫的修改要么全部執行,要么全部不執行
一致性:事務必須使數據庫從一個一致性狀態變換到另外一個一致性狀態。比如轉賬,轉賬前兩個賬戶余額之和為2k,轉賬之后也應該是2K。
隔離性:指多線程環境下,一個線程中的事務不能被其他線程中的事務打擾 持久性:事務一旦提交,就應該被永久保存起來。
持久性:事務一旦提交,就應該被永久保存起來。
1、概念說明:
更新丟失:最后的更新覆蓋了其他事務之前的更新,而事務之間並不知道,發生更新丟失。更新丟失,可以完全避免,應用對訪問的數據加鎖即可。
臟讀(針對未提交的數據):一個事務在更新一條記錄,未提交前,第二個事務讀到了第一個事務更新后的記錄,那么第二個事務就讀到了臟數據,會產生對第一個未提交 數據的依賴。一旦第一個事務回滾,那么第二個事務讀到的數據,將是錯誤的臟數據。
不可重復讀(讀取數據本身的對比):一個事務在讀取某些數據后的一段時間后,再次讀取這個數據,發現其讀取出來的數據內容已經發生了改變,就是不可重復讀。
幻讀(讀取結果集條數的對比):一個事務按相同的查詢條件查詢之前檢索過的數據,確發現檢索出來的結果集條數變多或者減少(由其他事務插入、刪除的),類似產生幻覺。
2、事務隔離級別:
並發處理帶來的問題中,更新丟失可以完全避免,由應用對數據加鎖即可。臟讀、不可重讀度、幻讀,其實都是數據庫的一致性問題,必須由一定的事務隔離機制來解決。 其中一種方法是:不用加鎖,通過一定的機制生成一個數據請求時間點的一致性快照,並用這個快照來提供一個界別的一致性讀取。從用戶的角度看,好像是數據庫提偶拱了 統一數據的多個版本。這種技術叫做:數據庫多版本並發控制,MVCC 多版本數據庫。
事務隔離的本質是使事務在一定程度上串行化執行,顯然和並發機制是矛盾的。數據庫的事務隔離越嚴格,並發負作用越小,代價越高(影響並發訪問了唄)。
為了解決隔離和並大的矛盾,IOS SQL92規定了4個隔離級別。(隔離==串行)
大多數數據庫默認的事務隔離級別是 Read Committed,比如 SQL Server , Oracle。但 MySQL 的默認隔離級別是 Repeatable Read。
舉例1:
臟讀(Read Uncommitted)
通俗的講,一個事務在處理過程中讀取了另外一個事務未提交的數據。(你都還沒提交,我就讀到了你剛操作的數據,萬一你回滾了怎么辦,你說這臟不臟。)
舉例(事務B未提交,事務A卻讀到了事務B未提交的數據):
3.2 不可重復讀(Non-repeatable Read)
通俗的講,一個事務范圍內,多次查詢某個數據,卻得到不同的結果。
與臟讀的區別:臟讀是讀到未提交的數據,而不可重復讀讀到的卻是已經提交的數據,但實際上是違反了事務的一致性原則。
舉例(事務B提交后,事務A卻讀到了事務B已提交的數據,導致事務A兩次讀到地數據不一致):
3.3 幻讀
在Repeatable Read隔離級別下,一個事務可能會遇到幻讀(Phantom Read)的問題。
事務A讀取與搜索條件相匹配的若干行。事務B以插入或刪除行等方式來修改事務A的結果集,然后再提交。
舉例(id主鍵唯一,事務A搜索id=10的數據,事務A搜索不到id=10的數據,然后事務B新增id=10的數據並提交,事務A更新id=10的數據卻成功,插入id=10卻失敗,現在搜索id=10也有記錄):
舉例2:
1. 臟讀的情況:對於兩個事務T1與T2,T1讀取了已經被T2更新但是還沒有提交的字段之后,若此時T2回滾,T1讀取的內容就是臨時並且無效的
開啟兩個mysql客戶端,並創建一張測試表transaction
更改默認隔離級別REPEATABLE READ為READ UNCOMMITTED,用於測試
SELECT @@tx_isolation; #查詢隔離級別 SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; # 更改隔離級別
兩個客戶端同時開啟事務,其中一個事務做UPDATE操作,另一個事務做SELECT
若此時黑色背景的客戶端進行回滾,則白色背景的客戶端讀取的數據就是臨時並且無效的。即臟讀。
2. 不可重復讀: 對於兩個事務T1和T2,T1讀取了一個字段,然后T2更新了該字段並提交之后,T1再次提取同一個字段,值便不相等了。
重復讀取的結果不一致的情況發生。
3. 幻讀: 對於兩個事務T1、T2,T1從表中讀取數據,然后T2進行了INSERT操作並提交,當T1'再次讀取的時候,結果不一致的情況發生。