深刻理解數據庫鎖

本文以oracle數據庫學習數據庫鎖

鎖的分類

oracle中分爲兩種模式的鎖,一種是排他鎖(X鎖),另外一種是共享所(S鎖).數據庫

  • 排他鎖,也能夠叫寫鎖
  • 共享所,也能夠叫讀鎖

鎖是實現併發的主要手段,在數據庫中應用頻繁,但不少都由數據庫自動管理,當事務提交後會自動釋放鎖.編程

鎖的類型

Oracle爲了使數據庫實現高度併發訪問,它使用了不一樣類型的鎖來管理併發會話對數據對象的操做.Oracle的鎖按做用對象不一樣分爲以下幾種類型.
  • DML鎖: 該類型的鎖被稱爲數據鎖,用於保護數據
  • DDL鎖: 能夠保護模式中對象的結構
  • 內部閂鎖: 保護數據庫的內部結構,徹底自動調用

這裏主要介紹下經常使用的DML鎖,它主要保證了併發訪問時數據的完整性.它又能夠分爲如下兩種類型的鎖:
1) 行級鎖(TX),也能夠稱爲事務鎖.當修改表中某行記錄時,須要對將要修改的記錄加行級鎖,防止兩個事務同時修改相同記錄,事務結束,該鎖也會釋放,是粒度最細的鎖.該鎖只能屬於排他鎖(X鎖).併發

2) 表級鎖(TM),主要做用書防止在修改表的數據時,表的結構發生變化.例如,會話S在修改表A的數據時,它會獲得表A的TM鎖,而此時將不容許其餘會話對該表進行變動或刪除操做. 該狀況的驗證過程以下:oracle

UPDATE TABLE_NAME SET COLUMN= 'test' WHERE ID = 'id';

此時已經鎖定該表,表級鎖將不容許在事務結束前其餘會話對錶TABLE_NAME進行DDL操做.
其次,在執行DROP TABLE TABLE_NAME操做,執行後會提示ORA-00054錯誤.
緣由是:
在執行DML操做時,數據庫會先申請數據對象上的共享鎖,防止其餘會話對該對象執行DDL操做。一旦申請成功,則會對將要修改的記錄申請排他鎖,若是此時其餘會話正在修改該記錄,那麼等待其事務結束後再爲修改的記錄加上排他鎖。性能

表級鎖包含以下集中模式:

  • ROW SHARE:行級共享鎖(RS)。該模式下不容許其餘的並行會話對同一張表使用排他鎖,但容許其利用DML語句或lock命令鎖定同一張表中的其餘記錄。SELECT...FROM FOR UPDATE 語句就是給記錄加上了RS鎖.
  • ROW EXCLUSEIVE, 行級排他鎖(RX).該模式下容許並行會話對同一張表的其餘數據進行修改,但不容許並行會話對同一張表使用排他鎖.
  • SHARE,共享鎖(S).該模式下,不容許會話更新表,但容許會話對錶添加RS鎖.
  • SHARE ROW EXCLUSIVE,共享行級排他鎖(SRX).該模式下,不能對同一張表進行DML操做,也不能添加S鎖.
  • EXCLUSIVE,排他鎖(X).該模式下,其餘的並行會話不能對錶進行DML和DDL操做,該表只能讀.

下表列出了以上5中模式相互之間的兼容關係.其中,✔表示相互兼容,×表示相互不兼容學習

\ RS S RX SRX X
RS ×
S × × ×
RX × ×
SRX × × × ×
X × × × × ×

下面所示是Oracle中的各類SQL語句所產生的表級鎖模式以及容許的鎖定模式狀況的彙總.code

SQL語句 表鎖模式 RS S RX SRX X
SELECT ...FROM table NONE Y Y Y Y Y
INSERT INTO ... RX Y N Y N N
UPDATE table ... RX Y N Y N N
DELETE FROM table ... RX Y N Y N N
SELECT * FROM table FOR UPDATE RX Y N Y N N
LOCK TABLE table IN ROW SHARE MODE RS Y Y Y Y N
LOCK TABLE table IN ROW EXCLUSIVE MODE RX Y N Y N N
LOCK TABLE table IN SHARE MODE S Y N N N N
LOCK TABLE table IN SHARE ROW EXCLUSIVE MODE SRX Y N N N N
LOCK TABLE table IN EXCLUSIVE MODE X N N N N N

在Oracle中除了執行DML時自動爲表添加TM鎖外,也能夠主動地爲表添加TM鎖,語法以下:對象

LOCK TABLE [schema.] table IN 
[EXCLUSIVE] 
[SHARE]
[ROW EXCLUSIVE]
[SHARE ROW EXCLUSIVE]
[ROW SHARE* | SHARE UPDATE*]
MODE [NOWAIT]

DDL鎖也能夠稱爲數據字典鎖,主要做用是保護模式中對象的結構.當執行DDL操做時首先Oracle會自動地隱式提交一次事務,而後自動地給處理對象加上鎖;當DDL結束時,Oracle會隱式地提交事務並釋放DDL鎖.與DML不一樣的是,用戶不能顯式的要求使用DDL鎖.事務

DDL鎖分爲以下3類:資源

  • Exclusive DDL Lock,排他DDL鎖定.若是對象加上了該類型的鎖,那麼對象不能被其餘會話修改,並且該對象也不能再增長其餘類型的DDL鎖.若是是表,此時能夠讀取數據.
  • Shared DDL Lock,共享DDL鎖定.保護對象的結構,其餘會話不能修改該對象的結構,可是容許修改數據.
  • Breakable Parsed Lock,能打破的解析鎖定.該類型的鎖能夠被打斷,不能禁止DDL操做.

鎖等待與死鎖

鎖等待

在某些狀況下因爲佔用的資源不能及時釋放,而形成鎖等待,也能夠叫鎖衝突.鎖等待會嚴重地影響數據庫性能和平常工做.

例如當一個會話修改表A的記錄時,它會對該記錄加鎖,而此時若是另外一個會話也來修改此記錄,那麼第二個會話將因得不到排他鎖而一直等待,此時會出現執行SQL時數據庫長時間沒有響應的現象.直到第一個會話把事務提交,釋放鎖,第二個會話才能對數據進行操做.

下面爲你們示例鎖等待現象:

  1. 打開SLQ*PLUS窗口,修改PRODUCTINFO 表中PRODUCTID 字段爲1的記錄,腳本以下:

UPDATE PRODUCTINFO SET ORIGIN = '修改1' WHERE PRODUCTID = 1;

此時雖然提示已更新,但事務並無提交.接下來進行第二步操做.

  1. 打開另外一個SQL*PLUS 窗口,一樣修改PRODUCTINFO 表中PRODUCTID字段爲1的記錄,腳本以下:

UPDATE PRODUCTINFO SET ORIGIN = '修改2' WHERE PRODUCTID = 1;

此時執行效果不會提示已更新,而是一直等待.

此時的狀況是由於第一個會話封鎖了該記錄,但事務沒有結束,鎖不會釋放,而這時第二個會話也要修改同一條記錄,但它缺沒有辦法得到排他鎖,因此只能等待.若是第一個會話修改數據的事務結束,那麼第二個會話會結束等待.及時地結束事務是解決鎖等待狀況發生的有效方法.

死鎖

死鎖的發生和鎖等待不一樣,它是鎖等待的一個特例,一般發生在兩個或者多個會話之間.假設一個會話想要修改兩個資源對象,能夠是表也能夠是字段,修改這兩個資源的操做在一個事務當中,當它修改第一個對象時須要對其鎖定,而後等待第二個對象,這時若是另一個會話也須要修改這兩個資源對象,而且已經得到對第二個對象的鎖定,那麼就會出現死鎖,由於當前會話鎖定了第一個對象等待第二個對象,而另外一個會話鎖定了第二個對象等待第一個對象.這樣,兩個會話都不能獲得想要獲得的對象,因而出現死鎖.

這裏例子就不在展現,你們能夠自行試一試.實際開發中出現死鎖狀況大體有如下幾種緣由:

  1. 用戶沒有良好的編程習慣,偶爾會忘記提交事務,致使長時間佔用資源.
  2. 操做的記錄過多,並且操做過程當中沒有良好地對其分組.對於數據兩很大的操做,能夠將其分紅幾組提交事務,這樣能夠避免長時間的佔用資源.
  3. 邏輯錯誤,兩個會話都想獲得已佔有的資源.
相關文章
相關標籤/搜索