標籤:
前段是時間涉及到資料庫的隔離等級問題,在網上搜尋一下,發現大部分都說的模稜兩可,而且也有很多錯誤。於是查閱了上學時的課本《資料庫系統概論》 和JDBC的文檔。現在把總結的結果記錄下來,供大家分享.
1. DBMS事務並發控制
1.1 事務並行作業的問題 DMBS允許東西運行多個事務,這些事務可能同時操作同一資料對象。這可能造成以下問題 丟失修改 : 一個事務的修改被另一個事務覆蓋。 不可重複讀取 : 在一個事務中執行相同的查詢,兩個的結果不一樣。 幻讀 : 幻讀是不可重複多的一種,在一個事務中執行相同的查詢,第二次的結果行比第一次少或者多(行被delete或者被insert) 髒讀 : 一個事務讀到的資料無效的,是另外一個交易回復的資料
所以需要對事務進行並發控制,採用的主要技術是鎖。
1.2 鎖
鎖是指一個事務對每個資料對象進行操作時,需要對資料對象加對應鎖。這樣其他事務最此資料對象訪問就受限。當操作結束後事務釋放此鎖。
1.2.1 鎖的粒度
鎖的粒度包括邏輯單元也可以是邏輯單元:
列值(注意不是列)、列值集合、行、表、索引項目、整個索引、資料庫;
也可以是物理單元:
資料頁、索引頁、塊。
事務可以對各種類型的資料對象加鎖,即多粒度加鎖。這樣在DBMS中就存在了可以被加鎖的資料對象樹,簡稱多粒度樹。如下,三級多粒度樹。
1.2.2 鎖的類型
鎖分為5中類型,如下 獨佔鎖定(X鎖): 也叫寫鎖。若事務T對資料對象A添加X鎖,則只允許T讀取和修改A,其他任何事務都不能再對A添加任何類型的鎖,直到T釋放此鎖。 共用鎖定(S鎖): 也叫讀鎖。若事務T對資料對象A添加此類型鎖,則事務T允許讀取A但不允許修改A,其他事務只能再對A添加S鎖,而不能加X鎖,直到A上的所有S鎖都被釋放。 意向獨佔鎖定(IX鎖): 如果對一個資料對象加IX鎖,表示他在多粒度樹中的後裔(包括直接孩子,孩子的孩子等等所有的後面的結點)有被加X鎖的可能(意向)。 意圖共用鎖(IS鎖): 如果對一個資料對象加IS鎖,表示他在多粒度樹中的後裔(包括直接孩子,孩子的孩子等等所有的後面的結點)有被加S鎖的可能(意向)。 共用意向獨佔鎖定(SIX): 如果對一個資料對象加SIX鎖,則表示對他加S鎖,再加IX鎖。
這個5類鎖的相容矩陣如下, T1已經對資料對象加鎖,T2嘗試對資料對象加鎖。Y表示成功,N表示失敗。
在Oracle中上面五個類型的鎖分別對應X鎖、S鎖、RX鎖、RS鎖、SRX鎖,而且加鎖粒度包括行級和表級,不包括資料庫。
1.2.3鎖協議
對資料對象加鎖時,需要約定一些規則,例如合適申請、持鎖時間、何時釋放。這些規則稱為鎖協議。DBMS遵循哪些協議要看具體情況。下面介紹一些協議: 基本鎖協議:當事務T對資料對象A加鎖時,如果A上已經存在鎖且和T欲加鎖不相容, 那麼T對待,直到A上存在的所被釋放。 一級鎖協議:事務T在修改資料對象A之前必須先對其加X鎖,知道事務結束才釋放。 二級鎖協議:在一級鎖協議的基礎上加上事務T在讀取資料對象A之前必須先對其加S鎖,讀完後即可釋放S鎖。 三級鎖協議:在一級鎖協議的基礎上加上事務T在讀取資料對象A之前必須先對其加S鎖,直到事務結束才釋放。 多粒度鎖協議: 多粒度樹中的每個結點被獨立地加鎖(顯式鎖)。對一個結點加鎖意味著其所有後裔結點也被加以同樣類型的鎖(隱式鎖, 並沒有真正在後裔結點加鎖,只是在邏輯上後裔結點具有同樣類型的鎖,所以叫隱式鎖。)。顯式鎖和隱式鎖的效果是一樣的,因此檢查鎖相容時不僅要檢查顯式鎖還要檢查隱式鎖。所以事務T要對資料對象A加鎖,需要檢查其祖先(包括直接的和間接的所有上層結點)上的顯式鎖(檢查A的隱式鎖是否與欲加的顯式鎖不相容)、檢查其顯式鎖(檢查A已存在的顯式鎖是否與欲加的顯式鎖不相容)、檢查其後裔的顯式鎖(檢查欲加給後裔的隱式鎖是否與後裔已存在的顯式鎖不相容),如果發現一個不相容鎖,則T等待。 意圖鎖定協議:對任一結點加鎖時,必須先對其祖先(包括直接的和間接的所有上層結點)加意圖鎖定,順序為自上而下。釋放結點上鎖後,釋放其祖先上的意圖鎖定,釋放順序為自下而上。意圖鎖定的含義是如果對一個結點加意圖鎖定,則說明該結點的後裔結點正在被加鎖。所以事務T要對資料對象A加鎖,需要檢查A祖先上的所有鎖(檢查祖先上的鎖是否與欲加給祖先的意圖鎖定相容)、檢查A上的所有鎖(檢查A上的鎖是否與欲加他的鎖相容),如果發現一個不相容鎖,則T等待。 多粒度鎖協議,在給結點加鎖時需要遞迴檢查子結點的顯式鎖,當子結點很多時,將帶來很多的效能開銷。意圖鎖定是針對這個問題進行的改進,他將鎖在多粒度樹間的傳遞由原來的由上而下變成由下而上,從而提高了效能。Oracle採用了意圖鎖定協議。
2.DBMS交易隔離等級
2.1 交易隔離等級的說明 上一節討論的內容是DBMS實現事務並發控制的內容,是DBMS內部問題。那麼如何從外面幹預DBMS內部的事務並發控制呢? 當事務寫資料對象時,DBMS使用X鎖及其相關鎖(例如IX)進行操作,這個過程是固定的,外界無法也無需幹預。 當事務讀資料對象時,哪些資料對象應該對此事務可見呢?例如,其他事務已寫還未提交的、其他事務已寫已提交的,等等。這個應該是可以選擇的,也就是 說外界可以幹預。DBMS通過交易隔離等級來讓事務選擇讀哪些資料對象。 可以這樣理解,寫是嚴格操作,不允許發生錯誤,所以其並發控制是最嚴格的,也是不可選的。而讀是寬鬆的操作,允許出現 不可重複讀取 、幻讀、髒讀問題,所以其並發控制是分多個層級的,可以選擇相應的層級改變並發度和允許出現的錯誤。
2.2 交易隔離等級類型 ANSI/ISO SQ92標準定義了如下交易隔離等級: 2.2.1未提交讀(read uncommitted) 事務可以讀其他事務未提交資料對象。 潛在問題: 髒讀、不可重複讀取、幻讀 DBMS鎖操作 :不加任何鎖,直接讀任意資料對象。 2.2.2提交讀(read committed) 事務可以讀其他事務已提交資料對象,讀完後此資料對象可以被其他事務再讀寫。 可能出現的問題: 不可重複讀取、幻讀 DBMS鎖操作(採用意圖鎖定協議) :加S鎖,祖先加IS鎖,讀完後立即釋放S鎖和祖先的IS鎖。 2.2.3 重複讀(repeatabe read) : 事務可以讀其他事務已提交資料對象,讀完後此資料對象不可以被其他事務再寫但可以讀,直到 此事務結束。 可能出現的問題: 幻讀 DBMS鎖操作 (採用意圖鎖定協議):加S鎖,祖先加IS鎖。事務結束後釋放S鎖和祖先的IS鎖。 2.2.4 序列化(seriaizabe): 事務讀之前,其他事務已提交的資料對象對此事務可見,讀完後整個多粒度樹唯讀不能寫,直到事務結束。所以他嚴重的降低了事務的並發度,特別是多粒度樹很深時,這也是Oracle沒有將資料庫作為多粒度樹根的原因。在此層級下事務完全隔離,就如所有的事務都順序執行一樣。 可能出現的問題: 無 DBMS鎖操作 (採用意圖鎖定協議):加S鎖,祖先加SIX鎖,事務結束後釋放S鎖和祖先的SIX鎖。
2.3 隔離等級的使用 隔離等級是針對事務的。但是也可以配置Session(對應JDBC的Connection)預設的和DBMS全域預設的交易隔離等級。這樣建立事務時不指定就採用預設的交易隔離等級。
3. JDBC事務 在JDBC中通過Connection執行事務。一個Connection可以執行多個事務。一個事務可以執行多個SQL語句。
3.1 事務的開啟 在Connection中,如果不存在事務,那麼在執行SQL語句之前自動開啟一個事務。如果事務已經存在那麼直接使用其執行SQL語句。
3.2 事務的結束 SQL陳述式完成之後調用Connection的commit或者rollback方法結束當前事務。在執行之後的SQL語句之前自動開啟一個新的事務。
3.3 設定事務的隔離等級 在JDBC中不能單獨設定事務的隔離等級,只能通過Session(對應Connection)間接設定,通過Connection的setTransactionIsolation方法。調用此方法之後,如果存在當前事務並且改變了Connection的交易隔離等級那麼會引起當前事務立刻提交,之後開啟的事務將採用此交易隔離等級。
3.4 SQL語句的完成時間 SQL語句的類型不同,其SQL陳述式完成時間不同。具體如下 DML, DDL語句:SQL語句執行完成,那麼SQL語句就算完成。 Select語句:查詢語句執行完成後返回ResultSet,當調用ResultSet的close方法後SQL語句算完成。 多結果語句:當SQL語句返回多結果時(例如執行預存程序,批處理),那麼SQL語句的完成時間是所以結果的最大者。
3.5Connection的自動認可模式 Connection有個模式叫自動認可,在這種模式下SQL完成後立即調用Connection的commit方法或者rollback方法。這就使每個SQL在獨立的事務中執行。自動認可模式模式是開啟的。
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。
事務並發控制