對於Oracle鎖的一些理論總結

oracle_ace發表於2007-12-13

首先什麼是鎖呢?可以理解為他是對一種共享資源併發訪問的一種控制:)
在資料庫中,基本的鎖型別有兩類,分別是
X-排他鎖:如果物件被一個排他鎖給瑣住,那麼按照鎖的相容性來講其他會話就不能夠在對這個會話所加鎖的物件加任何的鎖。
S-共享鎖:如果物件被一個共享鎖給鎖住,那麼按照鎖的相容性來講其他會話除了S鎖本身,都不能對這個會話所加鎖的物件加任何的鎖。

那麼在Oracle資料庫中呢,鎖是多粒度的,而且他的鎖型別可以分三大類
1.DML lock:目的是為了保護資料完整性
2.DDL lock:目的是為了保護資料庫物件的結構
3.一些內部鎖和latch:目的是為了保護資料庫的內部結構

這裡呢,主要想介紹一下DML鎖,因為其他型別的鎖基本上只會保持很短的一段時間

DML鎖呢共有兩種 1.row level lock  2.table level lock

1.TX(row level lock)
先介紹一下行級鎖吧,其實很多人都認為在資料庫中,行級鎖就是鎖定一行(注意我想說Oracle在資料行上面只有排他鎖X,而沒有共享鎖之類的其他鎖)。很多朋友認為一個資料表裡有多少行,就會有多少個行級別鎖,在Oracle卻不是這樣,其實需要澄清的是,Oracle對於行級鎖是事務級的。也就是說當一個事務發起一個更新(update)命令時,無論事務所涉及的行有多少,那麼Oracle只會分配一個TX鎖,所以在這裡Oracle是不會像其他資料庫一樣有鎖的升級(lock escalation),而且這中鎖升級也並不是資料庫的特性,但是他會執行鎖的轉換,Oracle會盡可能的在最低階別加鎖。因此對於開銷來講1個鎖的開銷和1000000個鎖的開銷其實是一樣的,都沒有什麼開銷。而且Oracle也不會像其他資料庫一樣來通過維護一個鎖的列表來管理鎖的資源(比如DB2,通過LOCKLIST,MAXLOCKS兩個引數來度量鎖的開銷),因為對於DB2來說,鎖是一種稀有的資源,需要對鎖的使用呢,進行監控,系統開銷就必然很大,而Oracle在鎖的維護上就大大的減少了開銷,而且也不會出現因為鎖數量不夠時引起的問題(鎖升級->死鎖).
讓我們來對比一下DB2和Oracle在行級的加鎖過程
DB2
------
加鎖的時候
1,找到想鎖定那一行的地址
2.在locklist中排隊(其實這種鎖管理器就是一種序列化的裝置,這樣做的好處是可以有效的避免活鎖)
3.鎖定列表
4.搜尋列表,看看別人是否已經對我要加鎖的那一樣上了鎖
5,如果沒有,則在列表中建立一個entry,表明我已經鎖住了這一行
6.對列表解鎖
解鎖的時候
1.再次進行排隊
2.鎖住我們的列表
3.在這個列表中搜尋,釋放我們的鎖
4,對列解鎖

我們看DB2對於鎖管理的開銷還是比較的大,鎖越多表明,這個操作花的時間就越長,開銷就比較大.

那麼Oracle是怎麼來做的呢?我們們來看一下:
當我想要加鎖的時候
1.找到要鎖定的一行.
2.定位那一樣,然後加鎖
對,沒錯就是這麼的簡單.讓你看到Oracle的實現就是這麼的piece of cake!!Oracle不需要傳統的鎖管理器,事務只是找資料如果資料沒有被加鎖,則加鎖.

那麼Oracle沒有了鎖管理器,看似簡單的問題,他是怎麼實現的呢?
這就要從資料塊說起,在Oracle中,其最小的邏輯單元就是block,在每一個block頭部,都保留有一個ITL的事務列表.每當一個事務要修改block中所保留的行的時候,就會在在ITL的SLOT中記錄一項.而每一行的行首還有一個Lock byte用來表示行的鎖定,因此未commit的事務用ITL的slot和lock byte來表示那些被封鎖的行.
剛才說過,Oracle的行級鎖是TX,是事務級的.如果一個事務要修改被另一個事務更新還沒有提交的資料時,他就會阻塞.等待鎖的釋放,但是等待的絕對不是行的鎖,而是事務鎖(TX)的釋放.所以真正的TX鎖釋放了(而不是隱式的那些行).被阻塞的事務才可以繼續進行.所以即使你加了savepoint也無用,回滾到某一個savepoint只能釋放某些隱式行上的鎖,但是不能釋放真正的事務鎖. 那麼ITL中的SLOT的數量是由誰決定的呢?其實一個slot項一般會佔用block的24個位元組,在建物件的時候會通過指定initrans和maxtrans來設定slot的數目.需要注意的是Oracle 10g中這個maxtrans的設定已經被廢棄,意思是說,即使我們指定了maxtrans,Oracle也會忽略這個限制,只要block有空間,Oracle就會不受約束的擴大ITL中的slot.

2.TM(table level lock)
表級鎖,其實就是向表加鎖了(廢話嘛).那麼在對一個表加鎖之前,資料庫需要做一些判斷,首先是他要對錶加的這個鎖是否與表中所加的這個鎖相容.其次,還要檢查該鎖是否與表中的每一行上的鎖相容,對於這一點如果我一個表裡面有很多的行,那麼如果我要對一個表加鎖的話,就需要遍歷表中的所有行,來檢視鎖的相容性,這對資料庫來講無疑是高效能的一個障礙.所以呢,Oracle引出了一個意向鎖的概念.
那麼什麼是意向鎖呢?如果我給了一個節點加了一個意向鎖,就表示我要對其下層節點加一個同等型別的鎖,意思也就是說要對一個節點加鎖,就要先在其上層節點上加個意向鎖,這樣一來,如果我要對一個表加鎖的話,那麼只要判斷和意向鎖的相容性就好了,不需要再遍歷表中的行來檢查每一行的鎖了,這樣系統的效率就大大提高了.
意向鎖有那些型別呢?
1.Intent share lock(意向共享鎖 IS):如果要對一個物件加S鎖,那麼首先就要在其上層節點加IS鎖
2.Intent exclusive lock(意向排他鎖 IX):如果要對一個物件加X鎖,首先也要對其上級節點加IX鎖.
3.Shared intent exclusive lock(共享意向排他鎖):如果一個事務對某個表加了SIX鎖的話,則表示整個事務要讀取整個的表,同時又會更新個別行.
這樣我們可以總結一下,在對資料庫物件加鎖的時候就有5種
X , S , IX , IS ,  SIX

因此Oracle的DML鎖,在行級只有X鎖,在TM級有5種就是我們剛剛提到的:X , S , IX , IS , SIX
表示起來就是,S , X , RS , RX , SRX

我們可以看到,通常的DML操作(SELECT…FOR UPDATE、INSERT、UPDATE、DELETE),在表級獲得的只是意向鎖(RS或RX),其真正的封鎖粒度還是在行級;另外,Oracle資料庫的一個顯著特點是,在預設情況下,單純地讀資料(SELECT)並不加鎖,Oracle通過回滾段(Rollback segment)來保證使用者不讀“髒”資料。這些都極大地提高了系統的併發程度。(撤消對讀取的塊所做的塊修改)由於意向鎖及資料行上鎖標誌位的引入,極大地減小了Oracle維護行級鎖的開銷,這些技術的應用使Oracle能夠高效地處理高度併發的事務請求。

最後,給出兩個表格是IT PUBer的朋友提供的:

        T2

T1

S

X

RS

RX

SRX

-

S

Y

N

Y

N

N

Y

X

N

N

N

N

N

Y

RS

Y

N

Y

Y

Y

Y

RX

N

N

Y

Y

N

Y

SRX

N

N

Y

N

N

Y

-

Y

Y

Y

Y

Y

Y

表一:Oracle資料庫TM鎖的相容矩陣

SQL語句

表鎖模式

允許的鎖模式

Select * from table_name……

RSRXSSRXX

Insert into table_name……

RX

RSRX

Update table_name……

RX

RSRX

Delete from table_name……

RX

RSRX

Select * from table_name for update

RS

RSRXSSRX

lock table table_name in row share mode

RS

RSRXSSRX

lock table table_name in row exclusive mode

RX

RSRX

lock table table_name in share mode

S

RSS

lock table table_name in share row exclusive mode

SRX

RS

lock table table_name in exclusive mode

X

表二:Oracle資料庫TM鎖小結

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/12361284/viewspace-542/,如需轉載,請註明出處,否則將追究法律責任。

相關文章