1. 程式人生 > >事務隔離級別

事務隔離級別

避免死鎖 數據庫 鎖定 兼容性 sans 關系數據庫 一段時間 cnblogs 模式

事務具有四個特征:原子性( Atomicity )、一致性( Consistency )、隔離性( Isolation )和持續性( Durability )。

這四個特性簡稱為 ACID 特性。
1 、原子性
事務是數據庫的邏輯工作單位,事務中包括的各操作要麽都做。要麽都不做
2 、一致性
數據庫事務不能破壞關系數據庫的完整性以及業務邏輯上的一致性。
3 、隔離性
一個事務的運行不能其他事務幹擾。即一個事務內部的操作及使用的數據對其他並發事務是隔離的,並發運行的各個事務之間不能互相幹擾。
4 、持續性
也稱永久性。指一個事務一旦提交,它對數據庫中的數據的改變就應該是永久性的。接下來的其他操作或故障不應該對其運行結果有不論什麽影響。


事務應用場景:

對於同一個銀行帳戶A內有200元,甲進行提款操作100元,乙進行轉帳操作100元到B帳戶。假設事務沒有進行隔離可能會並發例如以下問題:

臟讀(Dirty Read): 一個事務讀到還有一個事務未提交的更新數據。

事務T1更新了數據還未提交,這時事務T2來讀取同樣的數據,則T2讀到的數據事實上是錯誤的數據,即臟數據。基於臟數據所作的操作是不可能正確的 。

臟讀:甲取款100元未提交,乙進行轉帳查到帳戶內剩有100元,這是甲放棄操作回滾,乙正常操作提交。帳戶內終於為0元。乙讀取了甲的臟數據,客戶損失100元。

解讀:甲進行回滾操作,賬戶將變成200元,乙進行正常提交,200元將被覆蓋為0。故顧客損失100元

第一類丟失更新: 撤銷一個事務時,把其它事務已提交的更新數據覆蓋。

樣例:首先甲提款時帳戶內有200元,同一時候乙轉帳也是200元,然後甲乙同一時候操作。甲操作成功取走100元。乙操作失敗回滾,帳戶內終於為200元。這樣甲的操作被覆蓋掉了,銀行損失100元。

不可反復讀(Nonrepeatable Read)一個事務讀到還有一個事務已提交的更新數據。


一個事務的兩次讀取中,讀取同樣的資源得到不同的值。當事務T2在事務T1的兩次讀取之間更新數據,則會發生此種錯誤。(重點在改動)

樣例:甲乙同一時候開始都查到帳戶內為200元,甲先開始取款100元提交,這時乙在準備最後更新的時候又進行了一次查詢。發現結果是100元,這時乙就會非常困惑。不知道該將帳戶改為100還是0。

幻讀(虛讀): 一個事務讀到還有一個事務已提交的新插入的數據。

(解釋一)

事務T1對一定範圍內運行操作,T2對同樣的範圍內運行不兼容的操作,這時會發生幻讀。
如:T1刪除符合條件C1的全部數據。T2又插入了一些符合條件C1的數據,則在T1中再次查找符合條件C1的數據還是能夠查到,這對T1來說好像是幻覺一樣。這時的讀取操作稱為幻讀。(重點在新增或刪除)事務T1對一定範圍內運行操作,T2對同樣的範圍內運行不兼容的操作,這時會發生幻讀。
如:T1刪除符合條件C1的全部數據,T2又插入了一些符合條件C1的數據,則在T1中再次查找符合條件C1的數據還是能夠查到,這對T1來說好像是幻覺一樣。這時的讀取操作稱為幻讀。(重點在新增或刪除)

如:是針對於插入操作過程中的讀取問題,如丙存款100元未提交,這時銀行做報表進行統計查詢帳戶為200元,然後丙提交了,這時銀行再統計發現帳戶為300元了,無法推斷究竟以哪個為準?

大家好像認為統計這個東西肯定是時時更新的,這樣的情況非常正常;可是假設統計是在一個事務中的時候就不正常了,比方我們的一個統計應用須要將統計結果分別輸出到電腦屏幕和遠程網絡某臺計算機的磁盤文件裏,為了
提高性能和用戶響應我們分成2個線程,這時先完畢的和後完畢的統計數據就可能不一致,我們就不知道以哪個為準了。


和臟讀的差別是,臟讀是讀取前一事務未提交的臟數據,不可反復讀是又一次讀取了前一事務已提交的數據。

第二類丟失更新: 這是不可反復讀的特例,一個事務覆蓋還有一個事務已提交的更新數據。

如上,乙不做第二次查詢而是直接操作完畢,帳戶內終於為100元,甲的操作被覆蓋掉了。銀行損失100元。


在多個事務並發做數據庫操作的時候,假設沒有有效的避免機制,就會出現種種問題。

大體上有三種問題:

1、丟失更新說明事務進行數據庫寫操作的時候可能會出現的問題。

2、不可反復讀說明了做數據庫讀操作的時候可能會出現的問題。

3、臟讀

數據庫系統採用鎖來實現事務的隔離性。  

1、鎖的基本原理例如以下

    A、當一個事務訪問某種數據庫資源時,假設運行select語句,必須先獲得共享鎖;假設運行insert、update或者delete語句,必須獲得獨占鎖。
    B、當第二個事務也要訪問同樣的資源時。假設運行select語句,也必須先獲得共享鎖。假設運行inert、update或者delete語句。也必須先獲得獨占鎖。此時依據已經放置在資源上的鎖的類型,來決定第二個事務應該等待還是馬上獲取該鎖。


    第二個事務獲取鎖的情況說明:

資源上已經放置的鎖 第二個事務進行讀操作 第二個事務進行更新操作
馬上獲得共享鎖 馬上獲得獨占鎖
共享鎖 馬上獲得共享鎖 等待第一個事務解除共享鎖
獨占鎖 等待第一個事務解除獨占鎖 等待第一個事務解除獨占鎖
2、鎖的多粒度性及自己主動鎖升級
    數據庫系統可以鎖定的資源包含:數據庫、表、區域、頁面、鍵值(指帶有索引的行數據)、行。


    依照鎖定資源的粒度,鎖能夠分為下面類型:
      A、數據庫級鎖:鎖定整個數據庫。
      B、表級鎖:鎖定一張數據庫表。
      C、區域級鎖:鎖定數據庫的特定區域。


      D、頁面級鎖:鎖定數據庫的特定頁面。
      E、鍵值級鎖:鎖定數據庫表中帶有索引的一行記錄。


      F、行級鎖:鎖定數據庫表中的單行記錄。
    鎖的粒度越大,事務間的隔離性就越高,事務間的並發性能就越低。
    鎖升級是指調整鎖的粒度。將多個低粒度的鎖替換成少數更高粒度的鎖。以此來減少系統負荷。

3、鎖的類型和兼容性
    A、共享鎖:
      共享鎖用於讀數據操作。它是非獨占的,同意其它事務同一時候讀取其鎖定的資源,可是不同意其它事務更新它。


    B、獨占鎖:
      獨占鎖也叫排他鎖。適用於改動數據的場合。它所鎖定的資源。其它事務不能讀取也不能改動。
    C、更新鎖:
      更新鎖在更新操作的初始化階段用來鎖定可能要被改動的資源,這樣能夠避免使用共享鎖造成的死鎖現象。
    共享鎖、獨占鎖、更新鎖的特征總結:

特征項 共享鎖 獨占鎖 更新鎖
加鎖條件

當一個事務運行select語句時,數據庫會

為這個事務分配一個共享鎖。來鎖定被查詢的數據。

事務運行inert、update、delete語句時,分配獨占鎖。

事務運行

update語句時

。分配更新鎖

解鎖條件

一般數據被讀取後,數據庫系統立馬解除共享鎖

。當查詢多條記錄時。也是一條一條的鎖定-解鎖。

獨占鎖直到事務結束才幹被解除。

數據讀取完成。

運行更新操作時

。會把更新鎖升

級為獨占鎖。

與其它鎖兼容性 假設數據資源上放置了共享鎖。還能再放置共享鎖和更新鎖。

不能和其它鎖兼容。

與共享鎖兼容,

但僅僅能有一個更

新鎖,這樣能夠

避免死鎖

並發性能 具有良好的並發性能 並發性能較差
更新鎖

更 新 (U) 鎖能夠防止通常形式的死鎖。一般更新模式由一個事務組成。此事務讀取記錄。獲取資源(頁或行)的共享 (S) 鎖。然後改動行,此操作要求鎖轉換為排它 (X) 鎖。假設兩個事務獲得了資源上的共享模式鎖,然後試圖同一時候更新數據。則一個事務嘗試將鎖轉換為排它 (X) 鎖。

共享模式到排它鎖的轉換必須等待一段時間,由於一個事務的排它鎖與其他事務的共享模式鎖不兼容;發生鎖等待。第二個事務試圖獲取排它 (X) 鎖以進行更新。由於兩個事務都要轉換為排它 (X) 鎖。而且每一個事務都等待還有一個事務釋放共享模式鎖。因此發生死鎖。


若要避免這樣的潛 在的死鎖問題,請使用更新 (U) 鎖。

一次僅僅有一個事務能夠獲得資源的更新 (U) 鎖。假設事務改動資源,則更新 (U) 鎖轉換為排它 (X) 鎖。否則,鎖轉換為共享鎖。

4、死鎖及其防治方法

    在數據庫系統中,死鎖是指多個事務分別鎖定一個資源。又試圖請求鎖定對方已經鎖定的資源,這就產生了一個鎖定請求環,導致多個事務都處於等待對方釋放鎖定資源的狀態。


    很多數據庫系統能自己主動定期搜索和處理死鎖問題,當檢測到鎖定請求環時,系統將結束死鎖優先級最低的事務,並撤銷該事務。
    避免死鎖的方法:
      A、合理安排表訪問順序。
      B、使用短事務。
      C、假設對數據的一致性要求不是非常高,能夠同意臟讀。
      D、假設可能的話,錯開多個事務訪問同樣數據資源的時間,以防止鎖沖突。
      E、使用盡可能低的事務隔離級別。


數據庫的隔離級別

 數據庫提供了4種事務隔離級別供用戶選擇:

隔離級別 是否有第一類丟失更新 是否出現臟讀 是否出現虛讀 是否出現不可反復讀 是否出現第二類丟失更新
Serializable
Repeatable Read
Read Commited
Read Uncommited
Serializable(串行化):一個事務在運行過程中全然看不到其它事務對數據庫所做的更新(事務運行的時候不同意別的事務並發運行。事務串行化運行,事務僅僅能一個接著一個地運行,而不能並發運行)。

Repeatable Read(可反復讀):一個事務在運行過程中能夠看到其它事務已經提交的新插入的記錄,可是不能看到其它其它事務對已有記錄的更新。

Read Commited(讀已提交數據):一個事務在運行過程中能夠看到其它事務已經提交的新插入的記錄。並且能看到其它事務已經提交的對已有記錄的更新。

Read Uncommitted(讀未提交數據):一個事務在運行過程中能夠看到其它事務沒有提交的新插入的記錄,並且能看到其它事務沒有提交的對已有記錄的更新。

1、從應用程序的角度。鎖能夠分為2類
    A、悲觀鎖:指在應用程序中顯式的為數據資源加鎖。會影響並發性能。
    B、樂觀鎖:樂觀鎖假定當前事務操作數據資源時,不會有其它事務同一時候訪問該數據資源。因此全然依靠數據庫的隔離級別來自己主動管理鎖。
  2、悲觀鎖的實現方式
    A、在應用程序中顯示指定採用數據庫系統的獨占鎖來鎖定數據源。


    B、通過在數據庫表中添加一個標記字段,來推斷事務能否夠訪問。


驗證:http://xm-king.iteye.com/blog/770721

參考文獻:

http://blog.chinaunix.net/uid-22741583-id-127431.html

http://kinglyhum.iteye.com/blog/784428

http://www.cnblogs.com/tq03/p/3789434.html?utm_source=tuicool&utm_medium=referral(重點參考)

事務隔離級別