數據庫事務
數據庫事務(transaction)是訪問並可能操作各種數據項的一個數據庫操作序列,這些操作要麼全部執行,要麼全部不執行,是一個不可分割的工作單位。事務由事務開始與事務結束之間執行的全部數據庫操作組成。
性質
- 原子性:事務中的所有操作要麼全部提交成功,要麼全部失敗回滾。
- 一致性:幾個並行執行的事務,其執行結果必須與按某一順序 串行執行的結果相一致。
- 隔離性:一個事務所做的修改在提交之前對其它事務是不可見的。兩個以上的事務不會出現交錯執行的狀態,因爲這樣可能會導致數據不一致。
- 持久性:一旦事務提交,其所做的修改便會永久保存在數據庫中。
事務的併發問題
- 髒讀:事務A讀取了事務B更新的數據,然後B回滾操作,那麼A讀取到的數據是髒數據
- 不可重複讀:同一個事務內,多次相同的查詢返回了不同的結果。如,事務A第一次讀取一數據後,事務B對這條數據更新並提交事務[記住是
更新
操作],此時事務A再次讀取相同數據時,發現與之前讀取的數據不一致。 - 幻讀:在一個事務的兩次查詢中數據的記錄數不一致。如,事務A第一次讀取多條數據後,事務B插入或刪除數據[僅僅是
插入
和刪除
,不是修改數據],此時事務A再次讀取,發現讀取的記錄數量前後不一致
事務的隔離級別
- Read Uncommitted(讀取未提交內容):在該隔離級別,所有事務都可以看到其他未提交事務的執行結果。本隔離級別很少用於實際應用,因爲它的性能也不比其他級別好多少。讀取未提交的數據,也被稱之爲髒讀(Dirty Read)。
- Read Committed(讀取提交內容):這是大多數數據庫系統的默認隔離級別(但不是MySQL默認的)。它滿足了隔離的簡單定義:一個事務只能看見已經提交事務所做的改變。這種隔離級別 也支持所謂的不可重複讀(Nonrepeatable Read),因爲同一事務的其他實例在該實例處理其間可能會有新的commit,所以同一select可能返回不同結果。
- Repeatable Read(可重讀):這是MySQL的默認事務隔離級別,它確保同一事務的多次讀取數據時,會看到同樣的數據行。不過理論上,這會導致另一個棘手的問題:幻讀 (Phantom Read)。
- SERIALIZABLE(串行化):只有一個事務提交之後纔會執行另一個事務。在這個級別,可能導致大量的超時現象和鎖競爭。
事務隔離級別 | 髒讀 | 不可重複讀 | 幻讀 |
---|---|---|---|
讀未提交(read-uncommitted) | 是 | 是 | 是 |
不可重複讀(read-committed) | 否 | 是 | 是 |
可重複讀(repeatable-read) | 否 | 否 | 是 |
串行化(serializable) | 否 | 否 | 否 |
mysql事務隔離級別測試
表爲tx
表結構:
字段 | 類型 |
---|---|
id | int |
num | int |
兩個命令行客戶端分別爲A,B;不斷改變A的隔離級別,在B端修改數據。
##(一)、將A的隔離級別設置爲read uncommitted(未提交讀)
在B未更新數據之前:
客戶端A:
B更新數據:
客戶端B:
客戶端A:
經過上面的實驗可以得出結論,事務B更新了一條記錄,但是沒有提交,此時事務A可以查詢出未提交記錄。造成髒讀現象。未提交讀是最低的隔離級別。
##(二)、將客戶端A的事務隔離級別設置爲read committed(已提交讀)
在B未更新數據之前:
客戶端A:
B更新數據:
客戶端B:
客戶端A:
經過上面的實驗可以得出結論,已提交讀隔離級別解決了髒讀的問題,但是出現了不可重複讀的問題,即事務A在兩次查詢的數據不一致,因爲在兩次查詢之間事務B更新了一條數據。已提交讀只允許讀取已提交的記錄,但不要求可重複讀。
(三)、將A的隔離級別設置爲repeatable read(可重複讀)
在B未更新數據之前:
客戶端A:
B更新數據:
客戶端B:
B更新數據:
客戶端B:
客戶端A:
B插入數據:
客戶端B:
客戶端A:
由以上的實驗可以得出結論,可重複讀隔離級別只允許讀取已提交記錄,而且在一個事務兩次讀取一個記錄期間,其他事務部的更新該記錄。但該事務不要求與其他事務可串行化。例如,當一個事務可以找到由一個已提交事務更新的記錄,但是可能產生幻讀問題(注意是可能,因爲數據庫對隔離級別的實現有所差別)。像以上的實驗,就沒有出現數據幻讀的問題。
(四)、將A的隔離級別設置爲 可串行化 (Serializable)
A端打開事務,B端插入一條記錄
事務A端:
事務B端:
因爲此時事務A的隔離級別設置爲serializable,開始事務後,並沒有提交,所以事務B只能等待。
事務A提交事務:
事務A端
事務B端
serializable完全鎖定字段,若一個事務來查詢同一份數據就必須等待,直到前一個事務完成並解除鎖定爲止 。是完整的隔離級別,會鎖定對應的數據表格,因而會有效率的問題。
文章參考:
https://www.iteye.com/blog/xm-king-770721
https://www.cnblogs.com/xiaohanlin/p/8644749.html