1.1 原子性(Atomicity)
第一個原子性,這個是最簡單的。說的是一個事物內所有操作共同組成一個原子包,要么全部成功,要么全部失敗。這是最基本的特性,保證了因為一些其他因素導致數據庫異常,或者宕機。
1.2 一致性(Consistency)
第二一致性,這個是大家誤解最深的,很多博客都喜歡用銀行轉賬的例子來講一直性,所謂的一致性是基於原子性。
原子性只保證了一個事物內的所有操作同一性,大家同生死,不會出現你死了,我還活着。但是,原子性並沒有保證大家同一時刻一起生,一起死。計算機指令是有先后順序的,這樣就決定了一個事物的提交,會經歷一個時間過程,那么如果事物提交進行到了一半,我讀取了數據庫,會不會讀到中間結果?
為了防止這樣的情況,數據庫事物的一致性就規定了事物提交前后,永遠只可能存在事物提交前的狀態和事物提交后的狀態,從一個一致性的狀態到另一個一致性狀態,而不可能出現中間的過程態。也就是說事物的執行結果是量子化狀態,而不是線性狀態。
數據庫提交事物會有一個過程,如果提交的時候,存在一個時間差,在提交的第一秒,一個刪除過程還沒完成到了第三秒才完成,會不會第一秒訪問的人和第三秒訪問的人得到不同的結果?出現不一致,狀態的混沌?這就是一致性得保證的只會有前狀態和后狀態,絕不會出現中間態。
1.3 隔離性(Isolation)
事物的隔離性,基於原子性和一致性,因為事物是原子化,量子化的,所以,事物可以有多個原子包的形式並發執行,但是,每個事物互不干擾。
但是,由於多個事物可能操作同一個資源,不同的事物為了保證隔離性,會有很多鎖方案,當然這是數據庫的實現,他們怎么實現的,我們不必深究。
1.4持久性(Durability)
持久性,當一個事物提交之后,數據庫狀態永遠的發生了改變,這個事物只要提交了,哪怕提交后宕機,他也確確實實的提交了,不會出現因為
剛剛宕機了而讓提交不生效,是要事物提交,他就像洗不掉的紋身,永遠的固化了,除非你毀了硬盤。
2.不考慮隔離性可能產生的問題
現在重點說明下事務的隔離性,當多個線程(或多個客戶端)都開啟事務操作數據庫中的數據時,數據庫系統要能進行隔離操作,以保證各個線程獲取數據的准確性。
如果不考慮事務的隔離性,會發生的幾種問題:
2.1 臟讀
臟讀是指在一個事務處理過程中讀取了另一個未提交的事務中的數據。
2.2 不可重復讀
不可重復讀是指對於數據庫中的某個數據,一個事務內多次查詢卻返回了不同的數據值,這是由於在事務執行過程中,數據被另一個事務修改並提交了。
2.3 幻讀
幻讀是事務非獨立執行時發生的一種現象。例如,事務T1對一個表中所有的行的某個字段做了從“1”修改為“2”的操作,這時事務T2又插入了一條新的記錄,而該字段的值為“1”並且提交給數據庫。這時,操作事務T1的用戶如果再查看剛剛修改的數據,會發現還有一行沒有修改,其實這行是從事務T2中添加的,就好像產生幻覺一樣,這就是產生了幻讀。
幻讀和不可重復讀都是讀取了另一條已經提交的事務,所不同的是不可重復讀查詢的都是同一個數據項,而幻讀針對的是一批數據(比如數據的個數)。
3.事務的隔離級別
3.1 read uncommitted : 讀取尚未提交的數據 :哪個問題都不能解決
3.2 read committed:讀取已經提交的數據 :可以解決臟讀 ---- oracle、sql server、postgresql 默認的
3.3 repeatable read:重讀讀取:可以解決臟讀 和 不可重復讀 ---mysql默認的
3.4 serializable:串行化:可以解決 臟讀 不可重復讀 和 虛讀---相當於鎖表
以上四種隔離級別最高的是Serializable,最低的是Read uncommitted級別。當然,隔離級別越高,執行效率就越低。
01:Mysql的默認隔離級別是:可重復讀:Repeatable read;
02:oracle數據庫中,只支持seralizable(串行化)級別和Read committed();默認的是Read committed級別;
下面就四種隔離級別進行場景設計:
01: Read uncommitted 讀未提交; 公司發工資了,領導把5000元打到singo的賬號上,但是該事務並未提交,而singo正好去查看賬戶,發現工資已經到賬,是5000元整,非常高興。可是不幸的是,領導發現發給singo的工資金額不對,是2000元,於是迅速回滾了事務,修改金額后,將事務提交,最后singo實際的工資只有2000元,singo空歡喜一場。
02:Read committed 讀已提交; singo拿着工資卡去消費,系統讀取到卡里確實有2000元,而此時她的老婆也正好在網上轉賬,把singo工資卡的2000元轉到另一賬戶,並在singo之前提交了事務,當singo扣款時,系統檢查到singo的工資卡已經沒有錢,扣款失敗,singo十分納悶,明明卡里有錢,為何......
03:Repeatable read 重復讀 當singo拿着工資卡去消費時,一旦系統開始讀取工資卡信息(即事務開始),singo的老婆就不可能對該記錄進行修改,也就是singo的老婆不能在此時轉賬。
04:重復讀可能出現幻讀: singo的老婆工作在銀行部門,她時常通過銀行內部系統查看singo的信用卡消費記錄。有一天,她正在查詢到singo當月信用卡的總消費金額(select sum(amount) from transaction where month = 本月)為80元,而singo此時正好在外面胡吃海塞后在收銀台買單,消費1000元,即新增了一條1000元的消費記錄(insert transaction ... ),並提交了事務,隨后singo的老婆將singo當月信用卡消費的明細打印到A4紙上,卻發現消費總額為1080元,singo的老婆很詫異,以為出現了幻覺,幻讀就這樣產生了。
Serializabale:最高的事務隔離級別,代價花費最高,性能很低,很少使用,在此級別下,事務順序執行,避免上述產生的情況。