標籤:style class blog color com get
一、多個事務並行執行階段的並發問題:
總結為第一類丟失更新、髒讀、虛讀、不可重複讀取、第二類丟失更新。
1、第一類丟失更新: 撤銷一個事務時,把其他事務已提交的更新資料覆蓋。
2、髒讀: 一個事務讀到另一個事務未提交的更新資料。
3、虛讀(幻讀): 一個事務讀到另一個事務已提交的新插入的資料。
4、不可重複讀取: 一個事務讀到另一個事務已提交的更新資料。
5、第二類丟失更新: 這是不可重複讀取的特例,一個事務覆蓋另一個事務已提交的更新資料。
二、資料庫系統的鎖的基本原理:
資料庫系統採用鎖來實現事務的隔離性。
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語句時,分配更新鎖定 |
解鎖條件 |
一般資料被讀取後,資料庫系統立刻解除共用鎖定。當查詢多條記錄時,也是一條一條的鎖定-解鎖。 |
獨佔鎖直到事務結束才能被解除。 |
資料讀取完畢,執行更新操作時,會把更新鎖定升級為獨佔鎖。 |
與其他鎖相容性 |
如果資料資源上放置了共用鎖定,還能再放置共用鎖定和更新鎖定。 |
不能和其他鎖相容。 |
與共用鎖定相容,但只能有一個更新鎖定,這樣可以避免死結 |
並發效能 |
具有良好的並發效能 |
並發效能較差 |
|
4、死結及其防治方法:
在資料庫系統中,死結是指多個事務分別鎖定一個資源,又試圖請求鎖定對方已經鎖定資源,這就產生了一個鎖定請求環,導致多個事務都處於等待對方釋放鎖定資源的狀態。
許多資料庫系統能自動定期搜尋和處理死結問題,當檢測到鎖定請求環時,系統將結束死結優先順序最低的事務,並撤銷該事務。
避免死結的方法:
A、合理安排表訪問順序。
B、使用短事務。
C、如果對資料的一致性要求不是很高,可以允許髒讀。
D、如果可能的話,錯開多個事務訪問相同資料資源的時間,以防止鎖衝突。
E、使用儘可能低的交易隔離等級。
三、資料庫的隔離等級:
一般情況下,應首先考慮讓資料庫系統自動管理鎖。
資料庫提供了4種交易隔離等級供使用者選擇:
隔離等級 |
是否有第一類丟失更新 |
是否髒讀 |
是否虛讀 |
是否不可重複讀取 |
是否第二類丟失更新 |
Serializable |
否 |
否 |
否 |
否 |
否 |
Repeatable Read |
否 |
否 |
是 |
否 |
否 |
Read Commited |
否 |
否 |
是 |
是 |
是 |
Read Uncommited |
否 |
是 |
是 |
是 |
是 |
1、在mysql.exe中設定隔離等級的相關語句:
select @@tx_isolation;set transaction isolation level read commited;set global transaction isolation level read commited;
2、在應用程式中設定隔離等級:
在Hibernate設定檔中可一個顯式配置:
hibernate.connection.isolation=2
1:Read Uncommited; 2:Read Commited; 4:Repeatable Read; 8:Serializabel
四、在應用程式中使用悲觀鎖:
1、從應用程式的角度,鎖可以分為2類:
A、悲觀鎖:指在應用程式中顯式的為資料資源加鎖。會影響並發效能。
B、樂觀鎖:樂觀鎖假定當前事務操作資料資源時,不會有其他事務同時訪問該資料資源,因此完全依靠資料庫的隔離等級來自動管理鎖。
2、悲觀鎖的實現方式:
A、在應用程式中顯示指定採用資料庫系統的獨佔鎖來鎖定資料來源。
B、通過在資料庫表中增加一個標記欄位,來判斷事務是否可以訪問。
3、利用資料庫系統的獨佔鎖來實現悲觀鎖:
A、SQL語句控制:
select .. for update;
B、Hibernate中使用get()或者load()方法時:
Account account = (Account)session.get(Account.class,new Long(1),LockMode.UPGRADE);
LockMode不再深入介紹。
五、利用Hibernate的版本控制來實現樂觀鎖:
基本的實現邏輯是:在資料庫裡定義一個表示版本的欄位,或者一個時間戳記欄位,然後在對應檔中配置一個<version>元素,或者一個<timestamp>元素。
暫時不做深入瞭解。