事務的四大特性
一般來說,事務是必須滿足4個條件(ACID)::原子性(Atomicity,或稱不可分割性)、一致性(Consistency)、隔離性(Isolation,又稱獨立性)、永續性(Durability)。
原子性: 一個事務(transaction)中的所有操作,要麼全部完成,要麼全部不完成,不會結束在中間某個環節。事務在執行過程中發生錯誤,會被回滾(Rollback)到事務開始前的狀態,就像這個事務從來沒有執行過一樣。
一致性:在事務開始之前和事務結束以後,資料庫的完整性沒有被破壞。這表示寫入的資料必須完全符合所有的預設規則,這包含資料的精確度、串聯性以及後續資料庫可以自發性地完成預定的工作。
隔離性:資料庫允許多個併發事務同時對其資料進行讀寫和修改的能力,隔離性可以防止多個事務併發執行時由於交叉執行而導致資料的不一致。事務隔離分為不同級別,包括讀未提交(Read uncommitted)、讀提交(read committed)、可重複讀(repeatable read)和序列化(Serializable)。
永續性: 事務處理結束後,對資料的修改就是永久的,即便系統故障也不會丟失。
事務的隔離級別
事務隔離分為不同級別,包括讀未提交(Read uncommitted)、讀提交(read committed)、可重複讀(repeatable read)和序列化(Serializable)。
隔離級別 | 髒讀 | 不可重複讀 | 幻讀 |
---|---|---|---|
未提交(Read uncommitted) | 是 | 是 | 是 |
不可重複讀(read-committed) | 否 | 是 | 是 |
可重複讀(repeatable-read) | 否 | 否 | 是 |
序列化(serializable) | 否 | 否 | 否 |
下面通過例項來說明這幾種的區別
讀未提交
進入mysql,並設定當前事務模式為read uncommitted(未提交讀)set session transaction isolation level read uncommitted;
檢視錶user的初始值
開啟客戶端B,開啟事務,更新
user
表的age
欄位,然後在客戶端A中查詢資料此時會發現雖然客戶端B的事務沒有提交,但是A卻能讀到B更新後的的資料,一旦客戶端B的資料因為某種原因回滾的話,那麼A讀到的其實就是髒資料。
- 在客戶端執行
update user set age = age - 5 where id = 1;
發現zhangsan
的年齡並沒有變成想象中的 15-5 = 10,居然是5,是不是很奇怪,資料不一致啊,如果你這麼想就太天真 了,在應用程式中,我們會用15-5=10,並不知道其他會話回滾了,要想解決這個問題可以採用讀已提交(read committed)的隔離級別。
- 讀已提交
- 開啟客戶端A,設定當前事務模式為
read committed
(讀已提交)查詢表user
的資料;
- 在客戶端A提交之前開啟客戶端B並更新資料;
- 此時客戶端B的事務還沒提交,客戶端A並不能查詢到客戶端B更新的內容,這解決了髒讀的問題;
- 然後我們提交客戶端B的事務;
- 客戶端A執行相同的查詢,但是結果卻不一致,這就產生了不可重複讀的問題
- 可重複讀
- 開啟客戶端A,設定當前事務模式為
repeatable read
(重複讀)查詢表user
的資料;
- 在客戶端A的事務提交之前開啟客戶端B更新表
user
的值並提交;
- 在客戶端A中查詢
user
表的資料,發現與之前查詢的相同,沒有出現不可重複讀的問題。當我們將當前會話的隔離級別設定為可重複讀的時候,當前會話可以重複讀,就是每次讀取的結果 集都相同,而不管其他事務有沒有提交
- 在客戶端執行
update user set age = age - 10 where id = 1 ;
這個時候我們發現age
欄位並沒有 變成 30-10 = 20 ,而是按照客戶端B裡面的 50-10 = 40 來計算的 ,資料的一致性倒是沒有被破壞。可重複讀的隔離級別下使用了MVCC機制,select操作不會更新版本號,是快照讀(歷史版本);insert、update和delete會更新版本號,是當前讀(當前版本)。
- 開啟客戶端B插入一條資料,然後提交。
- 在客戶端A中查詢所有的記錄,發現並沒有出現新增的資料。
- 序列化
- 開啟一個客戶端A,並設定當前事務模式為serializable(序列化),開啟事務,並查詢
user
表資料
- 在客戶端B中插入一條資料,可以發現並不能立即插入,可以看出,如果一個事務,使用了SERIALIZABLE——可序列化隔離級別時,在這個事務沒有被提交之前其他的執行緒,只能等到當前操作完成之後,才能進行操作,這樣會非常耗時,而且,影響資料庫的效能,通常情況下,不會使用這種隔離級別
本作品採用《CC 協議》,轉載必須註明作者和本文連結