資料庫是一個多使用者使用的共用資源。當多個使用者並發地存取資料時,在資料庫中就會產生多個事務同時存取同一資料的情況。若對並行作業不加控制就可能會讀取和儲存不正確的資料,破壞資料庫的一致性。加鎖是實現資料庫並發控制的一個非常重要的技術。當事務在對某個資料對象進行操作前,先向系統發出請求,對其加鎖。加鎖後事務就對該資料對象有了一定的控制,在該事務釋放鎖之前,其他的事務不能對此資料對象進行更新操作。在資料庫中有兩種基本的鎖類型:排它鎖(Exclusive Locks,即X鎖)和共用鎖定(Share Locks,即S鎖)。當資料對象被加上排它鎖時,其他的事務不能對它讀取和修改。加了共用鎖定的資料對象可以被其他事務讀取,但不能修改。資料庫利用這兩種基本的鎖類型來對資料庫的事務進行並發控制。根據保護的對象不同,Oracle資料庫鎖可以分為以下幾大類:DML鎖(data locks,資料鎖),用於保護資料的完整性;DDL鎖(dictionary locks,字典鎖),用於保護資料庫物件的結構,如表、索引等的結構定義;內部鎖和閂(internal locks and latches),保護資料庫的內部結構,應用於SGA;在我們實際應用開發中涉及較多的是DML鎖,其他兩種的話DBA會更加關心點;DML鎖的目的在於保證並發情況下的資料完整性,主要包括TM鎖和TX鎖,其中TM鎖稱為表級鎖,TX鎖稱為事務鎖或行級鎖。當Oracle執行DML語句時,系統自動在所要操作的表上申請TM類型的鎖。當TM鎖獲得後,系統再自動申請TX類型的鎖,並將實際鎖定的資料行的鎖標誌位進行置位。這樣在事務加鎖前檢查TX鎖相容性時就不用再逐行檢查鎖標誌,而只需檢查TM鎖模式的相容性即可,大大提高了系統的效率。TM鎖包括了SS、SX、S、X等多種模式,在資料庫中用0-6來表示。不同的SQL操作產生不同類型的TM鎖。如所示:值 鎖模式 鎖描述 SQL0 NONE 1 NULL 空 SELECT2 SS(ROW-S) 行級共用鎖定其他對象只能查詢這些資料行 SELECT FOR UPDATE、LOCK FOR UPDATE、LOCK ROW SHARE3 SX(ROW-X) 行級排它鎖在提交前不允許做DML操作 INSERT、UPDATE、DELETE、LOCK ROW SHARE4 S(SHARE) 共用鎖定 CREATE INDEX、LOCK SHARE5 SSX(S/ROW-X) 共用行級排它鎖 LOCK SHARE ROW EXCLUSIVE6 X(eXclusive) 排它鎖 ALTER TABLE、DROP TABLE、DROP INDEX、TRUNCATE TABLE、LOCK EXCLUSIVE在資料行上只有X鎖(獨佔鎖定)。在 Oracle資料庫中,當一個事務首次發起一個DML語句時就獲得一個TX鎖,該鎖保持到事務被提交或復原。當兩個或多個會話在表的同一條記錄上執行 DML語句時,第一個會話在該條記錄上加鎖,其他的會話處於等待狀態。當第一個會話提交後,TX鎖被釋放,其他會話才可以加鎖。在大概瞭解oracle的鎖機制之後,我們來解決幾個基本的問題:1.UPDATE/DELETE操作會將RS鎖定,直至操作被COMMIT或者ROLLBACK;若操作未COMMIT之前其他session對同樣的RS做變更操作,則操作會被hold,直至前session的UPDATE/DELETE操作被COMMIT;2.session內外SELECT的RS範圍前提:INSERT、UPDATE操作未COMMIT之前進行SELECT;若在同一session內,SELECT出來的RS會包括之前INSERT、UPDATE影響的記錄;若不在同一session內,SELECT出來的RS不會包括未被COMMIT的記錄;3.SELECT.... FOR UPDATE [OF cols] [NOWAIT/WAIT] [SKIP LOCKED]OF cols:只鎖定指定欄位所在表的RS,而沒有指定的表則不會鎖定,只會在多表聯集查詢時出現;NOWAIT:語句不會hold,而是直接返回錯誤ORA-00054: resource busy and acquire with NOWAIT specified;WAIT N:語句被hold N秒,之後返回錯誤ORA-30006: resource busy; acquire with WAIT timeout expired;SKIP LOCKED:不提示錯誤,而是直接返回no rows selected;以上幾個選項可以聯合使用的,比較推薦的有:SELECT.... FOR UPDATE NOWAIT:對同一RS執行該SQL時,直接返回錯誤;SELECT.... FOR UPDATE NOWAIT SKIP LOCKED:對同一RS執行該SQL時,直接返回空行;PS:當RS被LOCK住之後,只對同樣請求LOCK的語句有效,對無需LOCK的SELECT語句並沒有任何影響;