程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> Oracle數據庫 >> Oracle數據庫基礎 >> 在Oracle中使用鎖進行並發控制

在Oracle中使用鎖進行並發控制

編輯:Oracle數據庫基礎

現在主流的數據庫管理系統中,都支持多個事務同時執行,這樣提高了數據庫管理系統的運行效率。試想如果只允許一個事務運行,而這個事務又需要很長的時間,那麼其他的用戶必須一直等待該事務結束,效率何其低下。執行不同的事務雖然可以提高性能,但是有可能會破壞數據的完整性,所以我們必須在性能和數據完整性之間進行權衡。那麼什麼是並發控制呢?並發控制是數據庫管理系統協調多個運行事務的行為。首先了解一下,並發控制中經常遇到的三個問題。

髒讀

我們通過一個products表來解釋一下什麼是髒讀,該products表有一列quantity(數量),現在的值為20。假如現在有兩個事務T1和T2,它們都是要更新quantity列,T1將該列值加100,T2將此列減10,但是T1執行失敗進行了回滾。我們很容易計算出正確的結果20-10=10,但是如果事務按照以下方式運行,能夠得出什麼結果?

時間   事務   步驟                 存儲值

1      T1     讀出quantity的值         20

2      T1      quantity=20+100        120

3      T1      寫入quantity值         120

4      T2      讀出quantity(T1未提交)     120

5      T2      quantity=120-10        110

6      T1      回滾(rollback)          20

7      T2      寫入quantity值         110

以上得出了110的結果,顯然是不正確的,問題就在於T2讀取到了T1沒有提交的數據,我們把這種情況就稱之為髒讀。

不可重復讀

還是事務T1和T2,它們都是要更新quantity列,T1將該列值加100,T2將此列減10,而且兩個事務都成功。我們很容易計算出正確的結果20+100-10=110,但是如果事務按照以下方式運行,能夠得出什麼結果?

時間   事務   步驟                存儲值

1      T1     讀出quantity的值         20

2      T2     讀出quantity的值          20

3      T1     quantity=20+100         120

4      T2     quantity=20-10          10

5      T1     寫入quantity值(更新丟失)      110

6      T2     寫入quantity值           10

得出了10的結果,仍然是不正確的。問題就在於T2的值覆蓋了T1的值,我們把這種情況稱之為不可重復讀。

幻覺讀

例如T1對一個表中的所有行修改,同時T2向該表中插入一行記錄。這時在T1中就會發生還有沒有被修改的數據行,就好象發生了幻覺一樣。

SQL92標准定義了四種隔離級別,以解決以上問題,四種隔離級別如下圖所示:

Oracle提供了三種隔離級別,分別是Read Committed Serializable和Read Only。Read Committed是Oracle的默認隔離級別,可以看出這種隔離級別消除了髒讀,但是避免不了不可重復讀和幻覺讀的發生,不過一般的應用還是可以使用該隔離級別的。Serializable這種隔離級別可以消除以上三個問題,但是效率會降低很多。Read Only隔離級別不是SQL92標准中定義的,它不允許事務進行更新操作,這種隔離級別也可以消除髒讀。

Oracle中在事務開始之前可以通過以下方式設置隔離級別:

set transation isolation level read committed;
set transation isolation level serialezable;
set transation isolation level read only;

也可以在單獨的會話中設置隔離級別:

alter session set isolation_level read committed;
alter session set isolation_level serialezable;
alter session set isolation_level read only;

通過剛才的介紹,我們知道了可以設置隔離級別來降低或者消除數據的不完整性,那數據庫管理系統是怎麼做到這一點的呢?答案是,采用鎖。鎖可以保護數據,當一個事務修改數據時,鎖會將該數據鎖定,防止這些數據在同一時刻被其它事務修改。

大多數情況下,我們可以不必自己管理鎖,Oracle會自動創建並管理,但是了解鎖是如何工作的,對我們來說也是非常有必要的。下列這些情況Oracle會創建鎖:

當我們運行了create truncate alter語句時,Oracle會創建鎖,稱之為DDL鎖。

當我們運行了insert update delete語句,Oracle會創建鎖,稱之為DML鎖。

還有一種是內部鎖,由Oracle在內部使用,比如管理數據文件。在這裡我們不做介紹。

從級別上講,鎖還可以分為數據庫級別鎖、表級別鎖、行級別鎖和列級別鎖(Oracle不支持)。

1、數據庫級別鎖:它會鎖定數據庫以禁止任何新會話和新事務。鎖定數據庫的最主要目的是在沒有用戶干擾的情況下完成維護。在Oracle中使用以下語句鎖定數據庫為限制模式:

alter system enable restricted session;

通過下列語句取消數據庫限制模式:

alter system disable restricted session;

以下語句將鎖定數據庫為只讀模式:

startup mount;
alter database open read only;

2、表級別鎖:它會鎖定整張表,以防止其它事務對表結構進行修改。比如當我們運行一個insert語句,如果表沒有沒鎖定,其它的事務修改了一列(將列名修改),這時我們運行update語句就會出錯,所以當我們運行DML語句時,Oracle會自動將表鎖定,DML語句執行完,會釋放表級別鎖。我們也可以通過lock語句鎖定表。

3、行級別鎖:當我們運行DML語句時,當前行上就會有行級別鎖,防止其它事務對該行進行修改。

當我們運行DML語句時,Oracle會自動加鎖,請看以下示例:

update dept set loc='北京' where deptno=40;

然後在Oracle的企業管理器中觀察Oracle自動管理的鎖,如下圖:

從上圖中我們可以看到,我們運行了一個update語句,產生了兩個鎖,都是scott用戶,SID表示會話是10,鎖類型TX表示表級別鎖,而TX表示行級別鎖,占用的模式我們後面給大家介紹。

鎖類型:TM 鎖模式:share 某個事務鎖定了一張表,允許其它事務再鎖定這張表,但不允許這個事務對這張表進行更新。

鎖類型:TM 鎖模式:row share 某個事務鎖定了一張表,允許其它事務再鎖定這張表中的其它行。

鎖類型:TM 鎖模式:row eclusive 某個事務鎖定了一張表,允許其它事務以相同的鎖模式鎖定這張表。

鎖類型:TM 鎖模式:share row eclusive 在share模式基礎上,不允許其它事務鎖定這張表。

鎖類型:TM 鎖模式:eclusive  不允許其它事務再鎖定該表,也不允許其它事務更新。

鎖類型:TX 鎖模式:eclusive  該行已經被鎖定,不允許其它事務鎖定。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved