1. 程式人生 > >關於資料庫事務隔離級別與鎖

關於資料庫事務隔離級別與鎖

 一、什麼是事務
事務簡單的來說就是把對資料庫的一系列操作放到一個可控制的過程中,進行可量化的控制,事務有4個必須的屬性原則:
1、原子性:必須保證在一個事務中的操作要麼全部執行,要麼全部不執行。
2、一致性:事務操作在完成時必須使資料庫保持一致的狀態,內部資料結構必須是完整的。比如一個例子 A和B都有50塊錢,他們兩個無論怎麼進行相互轉賬,A+B始終是100。
3、隔離性:簡單的來說就是各個事務之間的影響程度。
4、永續性:
不管資料庫是否發生問題,事務在完成之後資料應該永遠的儲存在資料庫中 
二、針對事務的隔離性引發的問題
 事務之間是會相互影響的,這時候需要有一個規則來約束事務操作,於是有了事務隔離。
事務隔離分為4種 : 
由低到高依次為Read uncommitted(讀未提交)、Read committed(讀提交)、Repeatable read(重複讀)、Serializable(序列化,也叫序列化),這四個級別可以逐個解決髒讀、不可重複讀、幻讀這幾類問題。
注:Sql Server 、Oracle事務隔離級別預設是Read committed(讀提交),MySQL的預設隔離級別就是Repeatable read(重複讀)
假設資料庫事務隔離級別為以下4種依次舉例:
1、Read uncommitted(讀未提交):A進行了一條資料操作,但是沒有提交事務,這時候如果B進行這條資料查詢,是可以查到A的資料操作的,但是這時候A還沒有提交事務,如果A不提交或者進行了事務回滾,那麼B查詢到的資料就是髒資料。

2、Read committed(讀提交):A正在進行資料操作,還沒有提交事務,B這個時候也去查詢了A操作的這個資料,並且修改了,馬上提交了事務,這時候A再去提交事務的時候會發現資料不對了,因為A手上的資料是B沒修改之前的,現在去提交時,資料庫的資料已經變成B更改之後的了,這種場景發生在金錢上會有很大問題,明明卡上有錢的A去消費,結果B搶在A前面消費完了,這時候A就是沒法付賬了。這就是不可重複讀。
3、Repeatable read(重複讀):這種情況只會發生在有一個事務在新增操作,比如A在查自己的銀行卡現在是100塊錢,A表示看花了,想再查一次,這時候有個人在給他轉賬,然後A第二次查詢,查出了1000塊了,又不敢相信自己是不是看花了。這就是幻讀。

4、Serializable(序列化,也叫序列化):Serializable是最高的事務隔離級別,同時代價也花費最高,效能很低,一般很少使用,在該級別下,事務順序執行,不僅可以避免髒讀、不可重複讀,還避免了幻像讀。
事務隔離級別參考了一個哥們的部落格http://blog.csdn.net/fg2006/article/details/6937413
三、資料庫鎖(這裡只說幾種常見的鎖,不怎麼用的鎖我不知道、也不研究,需要的自行問度娘)
樂觀鎖與悲觀鎖就是一個操作資料的姿勢問題,樂觀心態與悲觀心態
1、樂觀鎖:每次去找資料庫拿資料都認為別人不會對資料做什麼更改,所以不會上鎖。但是在找資料庫要資料的時候會帶一個數據版本過來,做更新的時候會去把拿到的這個版本與資料庫現在的要修改的資料版本做對比 只有大於或者等於資料庫中的資料版本,那麼它就認為這次操作是對的,可以執行。否則就不執行。
2、悲觀鎖(for update):每次去找資料庫拿資料都認為別人會改,所以它在查詢的時候就給資料加鎖,其他人只能查詢資料不能對資料做修改,只能等加鎖的人操作完成之後才會釋放鎖。
樂觀鎖適用於寫比較少的情況下,即衝突真的很少發生的時候,這樣可以省去了鎖的開銷,加大了系統的整個吞吐量。但如果經常產生衝突,上層應用會不斷的進行retry,這樣反倒是降低了效能,所以這種情況下用悲觀鎖就比較合適。
3、共享鎖:又稱讀鎖,若事務T對資料物件A加上S鎖,則事務T可以讀A但不能修改A,其他事務只能再對A加S鎖,而不能加X鎖,直到T釋放A上的S鎖。這保證了其他事務可以讀A,但在T釋放A上的S鎖之前不能對A做任何修改
4、排它鎖:又稱寫鎖。若事務T對資料物件A加上X鎖,事務T可以讀A也可以修改A,其他事務不能再對A加任何鎖,直到T釋放A上的鎖。這保證了其他事務在T釋放A上的鎖之前不能再讀取和修改A。