1 引言
在關聯式資料庫(DB2,Oracle,Sybase,Informix和SQL Server)最小的恢複和交易單位為一個事務(Transactions),事務具有ACID(原子性,一致性,隔離性和永久性)特徵。關聯式資料庫為了確保並發使用者在存取同一資料庫物件時的正確性(即無丟失更新、可重複讀、不讀"髒"資料,無"幻像"讀),資料庫中引入了並發(鎖)機制。基本的鎖類型有兩種:排它鎖(Exclusive locks記為X鎖)和共用鎖定(Share locks記為S鎖)。
排它鎖:若事務T對資料D加X鎖,則其它任何事務都不能再對D加任何類型的鎖,直至T釋放D上的X鎖;一般要求在修改資料前要向該資料加排它鎖,所以排它鎖又稱為寫鎖。
共用鎖定:若事務T對資料D加S鎖,則其它事務只能對D加S鎖,而不能加X鎖,直至T釋放D上的S鎖;一般要求在讀取資料前要向該資料加共用鎖定,所以共用鎖定又稱為讀鎖。
2 DB2 多粒度封鎖機制介紹
2.1 鎖的對象
DB2支援對錶空間、表、行和索引加鎖(大型主機上的資料庫還可以支援對資料頁加鎖)來保證資料庫的並發完整性。不過在考慮使用者應用程式的並發性的問題上,通常並不檢查用於資料表空間和索引的鎖。該類問題分析的焦點在於表鎖和行鎖。
2.2 鎖的策略
DB2可以只對錶進行加鎖,也可以對錶和表中的行進行加鎖。如果只對錶進行加鎖,則表中所有的行都受到同等程度的影響。如果加鎖的範圍針對於表及下屬的行,則在對錶加鎖後,相應的資料行上還要加鎖。究竟應用程式是對錶加行鎖還是同時加表鎖和行鎖,是由應用程式執行的命令和系統的隔離等級確定。
2.2.1 DB2表鎖的模式
DB2在表一級加鎖可以使用以下加鎖方式:
表一:DB2資料庫表鎖的模式
下面對幾種表鎖的模式進一步加以闡述:
IS、IX、SIX方式用於表一級並需要行鎖配合,他們可以阻止其他應用程式對該表加上排它鎖。
• 如果一個應用程式獲得某表的IS鎖,該應用程式可獲得某一行上的S鎖,用於唯讀操作,同時其他應用程式也可以讀取該行,或是對錶中的其他行變更。
• 如果一個應用程式獲得某表的IX鎖,該應用程式可獲得某一行上的X鎖,用於更改操作,同時其他應用程式可以讀取或更改表中的其他行。
• 如果一個應用程式獲得某表的SIX鎖,該應用程式可以獲得某一行上的X鎖,用於更改操作,同時其他應用程式只能對錶中其他行進行唯讀操作。
S、U、X和Z方式用於表一級,但並不需要行鎖配合,是比較嚴格的表加鎖策略。
• 如果一個應用程式得到某表的S鎖。該應用程式可以讀表中的任何資料。同時它允許其他應用程式獲得該表上的唯讀請求鎖。如果有應用程式需要更改讀該表上的資料,必須等S鎖被釋放。
• 如果一個應用程式得到某表的U鎖,該應用程式可以讀表中的任何資料,並最終可以通過獲得表上的X鎖來得到對錶中任何資料的修改權。其他應用程式只能讀取該表中的資料。U鎖與S鎖的區別主要在於更改的意圖上。U鎖的設計主要是為了避免兩個應用程式在擁有S鎖的情況下同時申請X鎖而造成死結的。
• 如果一個應用程式得到某表上的X鎖,該應用程式可以讀或修改表中的任何資料。其他應用程式不能對該表進行讀或者更改操作。
• 如果一個應用程式得到某表上的Z鎖,該應用程式可以讀或修改表中的任何資料。其他應用程式,包括未提交讀程式都不能對該表進行讀或者更改操作。
IN鎖用於表上以允許未提交讀這一概念。
2.2.2 DB2行鎖的模式
除了表鎖之外,DB2還支援以下幾種方式的行鎖。
表二:DB2資料庫行鎖的模式
2.2.3 DB2鎖的相容性
表三:DB2資料庫表鎖的相容矩陣
表四:DB2資料庫行鎖的相容矩陣
下表是筆者總結了DB2中各SQL語句產生表鎖的情況(假設預設的隔離等級為CS):
2.3 DB2鎖的升級
每個鎖在記憶體中都需要一定的記憶體空間,為了減少鎖需要的記憶體開銷,DB2提供了鎖定擴大的功能。鎖定擴大是通過對錶加上非意圖性的表鎖,同時釋允許存取鎖來減少鎖的數目,從而達到減少鎖需要的記憶體開銷的目的。鎖定擴大是由資料庫管理員自動完成的,有兩個資料庫的配置參數直接影響鎖定擴大的處理:
locklist--在一個資料庫全域記憶體中用於鎖儲存的記憶體。單位為頁(4K)。
maxlocks--一個應用程式允許得到的鎖佔用的記憶體所佔locklist大小的百分比。
鎖定擴大會在這兩種情況下被觸發:
• 某個應用程式請求的鎖所佔用的記憶體空間超出了maxlocks與locklist的乘積大小。這時,資料庫管理員將試圖通過為提出鎖請求的應用程式申請表鎖,並釋允許存取鎖來節省空間的。
• 在一個資料庫中已被加上的全部鎖所佔的記憶體空間超出了locklist定義的大小。這時,資料庫管理員也將試圖通過為提出鎖請求的應用程式申請表鎖,並釋允許存取鎖來節省空間的。
• 鎖定擴大雖然會降低OLTP應用程式的並發效能,但是鎖定擴大後會釋放鎖佔有記憶體並增大可用的鎖的記憶體空間。
鎖定擴大是有可能會失敗的,比如,現在一個應用程式已經在一個表上加有IX鎖,表中的某些行上加有X鎖,另一個應用程式又來請求表上的IS鎖,以及很多行上的S鎖,由於申請的鎖數目過多引起鎖的升級。資料庫管理員試圖為該應用程式申請表上的S鎖來減少所需要的鎖的數目,但S鎖與表上原有的IX鎖衝突,鎖定擴大不能成功。
如果鎖定擴大失敗,引起鎖定擴大的應用程式將接到一個-912的SQLCODE。在鎖定擴大失敗後,DBA應該考慮增加locklist的大小或者增大maxlocks的百分比。同時對編程人員來說可以在程式裡對發生鎖定擴大後程式復原後重新提交事務(例如:if sqlca.sqlcode=-912 then rollback and retry等)。
3 Oracle 多粒度鎖機制介紹
根據保護對象的不同,Oracle資料庫鎖可以分為以下幾大類:
(1) DML lock(data locks,資料鎖):用於保護資料的完整性;
(2) DDL lock(dictionary locks,字典鎖):用於保護資料庫物件的結構(例如表、視圖、索引的結構定義);
(3) Internal locks 和latches(內部鎖與閂):保護內部資料庫結構;
(4) Distributed locks(分布式鎖):用於OPS(並行伺服器)中;
(5) PCM locks(並行快取管理鎖):用於OPS(並行伺服器)中。
在Oracle中最主要的鎖是DML(也可稱為data locks,資料鎖)鎖。從封鎖粒度(封鎖對象的大小)的角度看,Oracle DML鎖共有兩個層次,即行級鎖和表級鎖。
3.1 Oracle的TX鎖(行級鎖、事務鎖)
許多對Oracle不太瞭解的技術人員可能會以為每一個TX鎖代表一條被封鎖的資料行,其實不然。TX的本義是Transaction(事務),當一個事務第一次執行資料更改(Insert、Update、Delete)或使用SELECT… FOR UPDATE語句進行查詢時,它即獲得一個TX(事務)鎖,直至該事務結束(執行COMMIT或ROLLBACK操作)時,該鎖才被釋放。所以,一個TX鎖,可以對應多個被該事務鎖定的資料行(在我們用的時候多是啟動一個事務,然後SELECT… FOR UPDATE NOWAIT)。
在Oracle的每行資料上,都有一個標誌位來表示該行資料是否被鎖定。Oracle不像DB2那樣,建立一個鏈表來維護每一行被加鎖的資料,這樣就大大減小了行級鎖的維護開銷,也在很大程度上避免了類似DB2使用行級鎖時經常發生的鎖數量不夠而進行鎖定擴大的情況。資料行上的鎖標誌一旦被置位,就表明該行資料被加X鎖,Oracle在資料行上沒有S鎖。
3.2 TM鎖(表級鎖)
3.2.1 意圖鎖定的引出
表是由行組成的,當我們向某個表加鎖時,一方面需要檢查該鎖的申請是否與原有的表級鎖相容;另一方面,還要檢查該鎖是否與表中的每一行上的鎖相容。比如一個事務要在一個表上加S鎖,如果表中的一行已被另外的事務加了X鎖,那麼該鎖的申請也應被阻塞。如果表中的資料很多,逐行檢查鎖標誌的開銷將很大,系統的效能將會受到影響。為瞭解決這個問題,可以在表級引入新的鎖類型來表示其所屬行的加鎖情況,這就引出了"意圖鎖定"的概念。
意圖鎖定的含義是如果對一個結點加意圖鎖定,則說明該結點的下層結點正在被加鎖;對任一結點加鎖時,必須先對它的上層結點加意圖鎖定。如:對錶中的任一行加鎖時,必須先對它所在的表加意圖鎖定,然後再對該行加鎖。這樣一來,事務對錶加鎖時,就不再需要檢查表中每行記錄的鎖標誌位了,系統效率得以大大提高。
3.2.2 意圖鎖定的類型
由兩種基本的鎖類型(S鎖、X鎖),可以自然地派生出兩種意圖鎖定:
意圖共用鎖(Intent Share Lock,簡稱IS鎖):如果要對一個資料庫物件加S鎖,首先要對其上級結點加IS鎖,表示它的後裔結點擬(意向)加S鎖;
意向排它鎖(Intent Exclusive Lock,簡稱IX鎖):如果要對一個資料庫物件加X鎖,首先要對其上級結點加IX鎖,表示它的後裔結點擬(意向)加X鎖。
另外,基本的鎖類型(S、X)與意圖鎖定類型(IS、IX)之間還可以組合出新的鎖類型,理論上可以組合出4種,即:S+IS,S+IX,X+IS,X+IX,但稍加分析不難看出,實際上只有S+IX有新的意義,其它三種組合都沒有使鎖的強度得到提高(即:S+IS=S,X+IS=X,X+IX=X,這裡的"="指鎖的強度相同)。所謂鎖的強度是指對其它鎖的排斥程度。
這樣我們又可以引入一種新的鎖的類型:
共用意向排它鎖(Shared Intent Exclusive Lock,簡稱SIX鎖):如果對一個資料庫物件加SIX鎖,表示對它加S鎖,再加IX鎖,即SIX=S+IX。例如:事務對某個表加SIX鎖,則表示該事務要讀整個表(所以要對該表加S鎖),同時會更新個別行(所以要對該表加IX鎖)。
這樣資料庫物件上所加的鎖類型就可能有5種:即S、X、IS、IX、SIX。
具有意圖鎖定的多粒度封鎖方法中任意事務T要對一個資料庫物件加鎖,必須先對它的上層結點加意圖鎖定。申請封鎖時應按自上而下的次序進行;釋放封鎖時則應按自下而上的次序進行;具有意圖鎖定的多粒度封鎖方法提高了系統的並發度,減少了加鎖和解鎖的開銷。
3.3 Oracle的TM鎖(表級鎖)
Oracle的DML鎖(資料鎖)正是採用了上面提到的多粒度封鎖方法,其行級鎖雖然只有一種(即X鎖),但其TM鎖(表級鎖)類型共有5種,分別稱為共用鎖定(S鎖)、排它鎖(X鎖)、行級共用鎖定(RS鎖)、行級排它鎖(RX鎖)、共用行級排它鎖(SRX鎖),與上面提到的S、X、IS、IX、SIX相對應。需要注意的是,由於Oracle在行級只提供X鎖,所以與RS鎖(通過SELECT … FOR UPDATE語句獲得)對應的行級鎖也是X鎖(但是該行資料實際上還沒有被修改),這與理論上的IS鎖是有區別的。鎖的相容性是指當一個應用程式在表(行)上加上某種鎖後,其他應用程式是否能夠在表(行)上加上相應的鎖,如果能夠加上,說明這兩種鎖是相容的,否則說明這兩種鎖不相容,不能對同一資料對象並發存取。
下表為Oracle資料庫TM鎖的相容矩陣(Y=Yes,表示相容的請求; N=No,表示不相容的請求;-表示沒有加鎖請求):
表五:Oracle資料庫TM鎖的相容矩陣
一方面,當Oracle執行SELECT…FOR UPDATE、INSERT、UPDATE、DELETE等DML語句時,系統自動在所要操作的表上申請表級RS鎖(SELECT…FOR UPDATE)或RX鎖(INSERT、UPDATE、DELETE),當表級鎖獲得後,系統再自動申請TX鎖,並將實際鎖定的資料行的鎖標誌位置位(指向該TX鎖);另一方面,程式或操作人員也可以通過LOCK TABLE語句來指定獲得某種類型的TM鎖。下表是筆者總結了Oracle中各SQL語句產生TM鎖的情況:
表六:Oracle資料庫TM鎖小結
我們可以看到,通常的DML操作(SELECT…FOR UPDATE、INSERT、UPDATE、DELETE),在表級獲得的只是意圖鎖定(RS或RX),其真正的封鎖粒度還是在行級;另外,Oracle資料庫的一個顯著特點是,在預設情況下,單純地讀資料(SELECT)並不加鎖,Oracle通過復原段(Rollback segment)來保證使用者不讀"髒"資料。這些都提高了系統的並發程度。
由於意圖鎖定及資料行上鎖標誌位的引入,減小了Oracle維護行級鎖的開銷,這些技術的應用使Oracle能夠高效地處理高度並發的事務請求。
4 DB2多粒度封鎖機制的監控
在DB2中對鎖進行監控主要有兩種方式,第一種方式是快照監控,第二種是事件監控方式。
4.1 快照監控方式
當使用快照方式進行鎖的監控前,必須把監控鎖的開關開啟,可以從執行個體層級和會話層級開啟,具體命令如下:
db2 update dbm cfg using dft_mon_lock on(執行個體層級)
db2 update monitor switches using lock on(會話層級,推薦使用)
當開關開啟後,可以執行下列命令來進行鎖的監控
db2 get snapshot for locks on ebankdb(可以得到當前資料庫中具體鎖的詳細資料)
db2 get snapshot for locks on ebankdb
Fri Aug 15 15:26:00 JiNan 2004(紅色為鎖的關鍵資訊)
Database Lock Snapshot
Database name = DEV
Database path = /db2/DEV/db2dev/NODE0000/SQL00001/
Input database alias = DEV
Locks held = 49
Applications currently connected = 38
Agents currently waiting on locks = 6
Snapshot timestamp = 08-15-2003 15:26:00.951134
Application handle = 6
Application ID = *LOCAL.db2dev.030815021007
Sequence number = 0001
Application name = disp+work
Authorization ID = SAPR3
Application status = UOW Waiting
Status change time =
Application code page = 819
Locks held = 0
Total wait time (ms) = 0
Application handle = 97
Application ID = *LOCAL.db2dev.030815060819
Sequence number = 0001
Application name = tp
Authorization ID = SAPR3
Application status = Lock-wait
Status change time = 08-15-2003 15:08:20.302352
Application code page = 819
Locks held = 6
Total wait time (ms) = 1060648
Subsection waiting for lock = 0
ID of agent holding lock = 100
Application ID holding lock = *LOCAL.db2dev.030815061638
Node lock wait occurred on = 0
Lock object type = Row
Lock mode = Exclusive Lock (X)
Lock mode requested = Exclusive Lock (X)
Name of tablespace holding lock = PSAPBTABD
Schema of table holding lock = SAPR3
Name of table holding lock = TPLOGNAMES
Lock wait start timestamp = 08-15-2003 15:08:20.302356
Lock is a result of escalation = NO
List Of Locks
Lock Object Name = 29204
Node number lock is held at = 0
Object Type = Table
Tablespace Name = PSAPBTABD
Table Schema = SAPR3
Table Name = TPLOGNAMES
Mode = IX
Status = Granted
Lock Escalation = NO
db2 get snapshot for database on dbname |grep -i locks(UNIX,LINUX平台)
Locks held currently = 7
Lock waits = 75
Time database waited on locks (ms) = 82302438
Lock list memory in use (Bytes) = 20016
Deadlocks detected = 0
Lock escalations = 8
Exclusive lock escalations = 8
Agents currently waiting on locks = 0
Lock Timeouts = 20
db2 get snapshot for database on dbname |find /i "locks"(NT平台)
db2 get snapshot for locks for applications agentid 45(註:45為應用程式控制代碼)
Application handle = 45
Application ID = *LOCAL.db2dev.030815021827
Sequence number = 0001
Application name = tp
Authorization ID = SAPR3
Application status = UOW Waiting
Status change time =
Application code page = 819
Locks held = 7
Total wait time (ms) = 0
List Of Locks
Lock Object Name = 1130185838
Node number lock is held at = 0
Object Type = Key Value
Tablespace Name = PSAPBTABD
Table Schema = SAPR3
Table Name = TPLOGNAMES
Mode = X
Status = Granted
Lock Escalation = NO
Lock Object Name = 14053937
Node number lock is held at = 0
Object Type = Row
Tablespace Name = PSAPBTABD
Table Schema = SAPR3
Table Name = TPLOGNAMES
Mode = X
Status = Granted
Lock Escalation = NO
也可以執行下列表函數(註:在DB2 V8之前只能通過命令,DB2 V8後可以通過表函數,推薦使用表函數來進行鎖的監控)
db2 select * from table(snapshot_lock('DBNAME',-1)) as locktable監控鎖資訊
db2 select * from table(snapshot_lockwait('DBNAME',-1) as lock_wait_table監控應用程式鎖等待的資訊
4.2 事件監控方式:
當使用事件監控器進行鎖的監控時候,只能監控死結(死結的產生是因為由於鎖請求衝突而不能結束事務,並且該請求衝突不能夠在本事務內解決。通常是兩個應用程式互相持有對方所需要的鎖,在得不到自己所需要的鎖的情況下,也不會釋放現有的鎖)的情況,具體步驟如下:
db2 create event monitor dlock for deadlocks with details write to file '$HOME/dir'
db2 set event monitor dlock state 1
db2evmon -db dbname -evm dlock看具體的死結輸出(如)
Deadlocked Connection ...
Deadlock ID: 4
Participant no.: 1
Participant no. holding the lock: 2
Appl Id: G9B58B1E.D4EA.08D387230817
Appl Seq number: 0336
Appl Id of connection holding the lock: G9B58B1E.D573.079237231003
Seq. no. of connection holding the lock: 0126
Lock wait start time: 06/08/2005 08:10:34.219490
Lock Name : 0x000201350000030E0000000052
Lock Attributes : 0x00000000
Release Flags : 0x40000000
Lock Count : 1
Hold Count : 0
Current Mode : NS - Share (and Next Key Share)
Deadlock detection time: 06/08/2005 08:10:39.828792
Table of lock waited on : ORDERS
Schema of lock waited on : DB2INST1
Tablespace of lock waited on : USERSPACE1
Type of lock: Row
Mode of lock: NS - Share (and Next Key Share)
Mode application requested on lock: X - Exclusive
Node lock occured on: 0
Lock object name: 782
Application Handle: 298
Deadlocked Statement:
Type : Dynamic
Operation: Execute
Section : 34
Creator : NULLID
Package : SYSSN300
Cursor : SQL_CURSN300C34
Cursor was blocking: FALSE
Text : UPDATE ORDERS SET TOTALTAX = ?, TOTALSHIPPING = ?,
LOCKED = ?, TOTALTAXSHIPPING = ?, STATUS = ?, FIELD2 = ?, TIMEPLACED = ?,
FIELD3 = ?, CURRENCY = ?, SEQUENCE = ?, TOTALADJUSTMENT = ?, ORMORDER = ?,
SHIPASCOMPLETE = ?, PROVIDERORDERNUM = ?, TOTALPRODUCT = ?, DESCRIPTION = ?,
MEMBER_ID = ?, ORGENTITY_ID = ?, FIELD1 = ?, STOREENT_ID = ?, ORDCHNLTYP_ID = ?,
ADDRESS_ID = ?, LASTUPDATE = ?, COMMENTS = ?, NOTIFICATIONID = ? WHERE ORDERS_ID = ?
List of Locks:
Lock Name : 0x000201350000030E0000000052
Lock Attributes : 0x00000000
Release Flags : 0x40000000
Lock Count : 2
Hold Count : 0
Lock Object Name : 782
Object Type : Row
Tablespace Name : USERSPACE1
Table Schema : DB2INST1
Table Name : ORDERS
Mode : X - Exclusive
Lock Name : 0x00020040000029B30000000052
Lock Attributes : 0x00000020
Release Flags : 0x40000000
Lock Count : 1
Hold Count : 0
Lock Object Name : 10675
Object Type : Row
Tablespace Name : USERSPACE1
Table Schema : DB2INST1
Table Name : BKORDITEM
Mode : X - Exclusive(略去後面資訊)
5 Oracle 多粒度封鎖機制的監控
為了監控Oracle系統中鎖的狀況,我們需要對幾個系統檢視表有所瞭解:
5.1 v$lock視圖
v$lock視圖列出當前系統持有的或正在申請的所有鎖的情況,其主要欄位說明如下:
表七:v$lock視圖主要欄位說明
其中在TYPE欄位的取值中,本文只關心TM、TX兩種DML鎖類型;
5.2 v$locked_object視圖
v$locked_object視圖列出當前系統中哪些對象正被鎖定,其主要欄位說明如下:
表八:v$locked_object視圖欄位說明
5.3 Oracle鎖監控指令碼
根據上述系統檢視表,可以編製指令碼來監控資料庫中鎖的狀況。
5.3.1 showlock.sql
第一個指令碼showlock.sql,該指令碼通過串連v$locked_object與all_objects兩視圖,顯示哪些對象被哪些會話鎖住:
/* showlock.sql */
column o_name format a10
column lock_type format a20
column object_name format a15
select rpad(oracle_username,10) o_name,session_id sid,
decode(locked_mode,0,'None',1,'Null',2,'Row share',
3,'Row Exclusive',4,'Share',5,'Share Row Exclusive',6,'Exclusive') lock_type,
object_name ,xidusn,xidslot,xidsqn
from v$locked_object,all_objects
where v$locked_object.object_id=all_objects.object_id;
5.3.2 showalllock.sql
第二個指令碼showalllock.sql,該指令碼主要顯示當前所有TM、TX鎖的資訊;
/* showalllock.sql */
select sid,type,id1,id2,
decode(lmode,0,'None',1,'Null',2,'Row share',
3,'Row Exclusive',4,'Share',5,'Share Row Exclusive',6,'Exclusive')
lock_type,request,ctime,block
from v$lock
where TYPE IN('TX','TM');
6 DB2 多粒度封鎖機制樣本
以下樣本均運行在DB2 UDB中,適用所有資料庫版本。首先開啟三個命令列視窗(DB2 CLP),其中兩個(以下用SESS#1、SESS#2表示)以db2admin使用者連入資料庫,以操作SAMPLE庫中提供的樣本表(employee);另一個(以下用SESS#3表示)以db2admin使用者連入資料庫,對執行的每一種類型的SQL語句監控加鎖的情況;希望讀者通過這種方式對每一種類型的SQL語句監控加鎖的情況。(因為樣本篇幅很大,筆者在此就不做了,建議讀者用類似方法驗證加鎖情況)
/home/db2inst1>db2 +c update employee set comm=9999(SESS#1)
/home/db2inst1>db2 +c select * from employee(SESS#2處於lock wait)
/home/db2inst1>db2 +c get snapshot for locks on sample(SESS#3監控加鎖情況)
註:db2 +c為不自動認可(commit)SQL語句,也可以通過 db2 update command options using c off關閉自動認可(autocommit,預設是自動認可)
7 總結
總的來說,DB2的鎖和Oracle的鎖主要有以下大的區別:
1.Oracle通過具有意圖鎖定的多粒度封鎖機制進行並發控制,保證資料的一致性。其DML鎖(資料鎖)分為兩個層次(粒度):即表級和行級。通常的DML操作在表級獲得的只是意圖鎖定(RS或RX),其真正的封鎖粒度還是在行級;DB2也是通過具有意圖鎖定的多粒度封鎖機制進行並發控制,保證資料的一致性。其DML鎖(資料鎖)分為兩個層次(粒度):即表級和行級。通常的DML操作在表級獲得的只是意圖鎖定(IS,SIX或IX),其真正的封鎖粒度也是在行級;另外,在Oracle資料庫中,單純地讀資料(SELECT)並不加鎖,這些都提高了系統的並發程度,Oracle強調的是能夠"讀"到資料,並且能夠快速的進行資料讀取。而DB2的鎖強調的是"讀一致性",進行讀資料(SELECT)時會根據不同的隔離等級(RR,RS,CS)而分別加S,IS,IS鎖,只有在使用UR隔離等級時才不加鎖。從而保證不同應用程式和使用者讀取的資料是一致的。
2. 在支援高並發度的同時,DB2和Oracle對鎖的操縱機制有所不同:Oracle利用意圖鎖定及資料行上加鎖標誌位等設計技巧,減小了Oracle維護行級鎖的開銷,使其在資料庫並發控制方面有著一定的優勢。而DB2中對每個鎖會在鎖的記憶體(locklist)中申請分配一定位元組的記憶體空間,具體是X鎖64位元組記憶體,S鎖32位元組記憶體(註:DB2 V8之前是X鎖72位元組記憶體而S鎖36位元組記憶體)。
3. Oracle資料庫中不存在鎖定擴大,而DB2資料庫中當資料庫表中行級鎖的使用超過locklist*maxlocks會發生鎖定擴大。
4. 在Oracle中當一個session對錶進行insert,update,delete時候,另外一個session仍然可以從Orace復原段或者還原資料表空間中讀取該表的前映象(before image); 而在DB2中當一個session對錶進行insert,update,delete時候,另外一個session仍然在讀取該表資料時候會處於lock wait狀態,除非使用UR隔離等級可以讀取第一個session的未提交的值;所以Oracle同一時刻不同的session有讀不一致的現象,而DB2在同一時刻所有的session都是"讀一致"的。
8 結束語
DB2中關於並發控制(鎖)的建議
1.正確調整locklist,maxlocks,dlchktime和locktimeout等和鎖有關的資料庫配置參數(locktimeout最好不要等於-1)。如果鎖記憶體不足會報SQL0912錯誤而影響並發。
2.寫出高效而簡潔的SQL語句(非常重要)。
3.在商務邏輯處理完後儘可能快速commit釋放鎖。
4.對引起鎖等待(SQL0911返回碼68)和死結(SQL0911返回碼2)的SQL語句建立最合理的索引(非常重要,盡量建立複合索引和包含索引)。
5.使用 altER TABLE 語句的 LOCKSIZE 參數控制如何在持久基礎上對某個特定表進行鎖定。檢查syscat.tables中locksize欄位,盡量在符合商務邏輯的情況下,每個表中該欄位為"R"(行級鎖)。
6.根據商務邏輯使用正確的隔離等級(RR,RS,CS和UR)。
7.當執行大量更新時,更新之前,在整個事務期間鎖定整個表(使用 SQL LOCK TABLE 語句)。這隻使用了一把鎖從而防止其它事務進行這些更新,但是對於其他使用者它的確減少了資料並發性。