鎖概念基礎數據庫
數據庫是一個多用戶使用的共享資源。當多個用戶併發地存取數據時,在數據庫中就會產生多個事務同時存取同一數據的狀況。若對併發操做不加控制就可能會讀取和存儲不正確的數據,破壞數據庫的一致性。安全
加鎖是實現數據庫併發控制的一個很是重要的技術。當事務在對某個數據對象進行操做前,先向系統發出請求,對其加鎖。加鎖後事務就對該數據對象有了必定的控制,在該事務釋放鎖以前,其餘的事務不能對此數據對象進行更新操做。session
在數據庫中有兩種基本的鎖類型:排它鎖(Exclusive Locks,即X鎖)和共享鎖(Share Locks,即S鎖)。當數據對象被加上排它鎖時,其餘的事務不能對它讀取和修改。加了共享鎖的數據對象能夠被其餘事務讀取,但不能修改。數據庫利用這兩 種基本的鎖類型來對數據庫的事務進行併發控制。併發
Oracle數據庫的鎖類型 oracle
根據保護的對象不一樣,Oracle數據庫鎖能夠分爲如下幾大類:DML鎖(data locks,數據鎖),用於保護數據的完整性;DDL鎖(dictionary locks,字典鎖),用於保護數據庫對象的結構,如表、索引等的結構定義;內部鎖和閂(internal locks and latches),保護數據庫的內部結構。 app
DML鎖的目的在於保證併發狀況下的數據完整性,。在Oracle數據庫中,DML鎖主要包括TM鎖和TX鎖,其中TM鎖稱爲表級鎖,TX鎖稱爲事務鎖或行級鎖。 ide
當Oracle 執行DML語句時,系統自動在所要操做的表上申請TM類型的鎖。當TM鎖得到後,系統再自動申請TX類型的鎖,並將實際鎖定的數據行的鎖標誌位進行置位。 這樣在事務加鎖前檢查TX鎖相容性時就不用再逐行檢查鎖標誌,而只需檢查TM鎖模式的相容性便可,大大提升了系統的效率。TM鎖包括了SS、SX、S、X 等多種模式,在數據庫中用0-6來表示。不一樣的SQL操做產生不一樣類型的TM鎖。 ui
在數據行上只有X鎖(排他鎖)。在 Oracle數據庫中,當一個事務首次發起一個DML語句時就得到一個TX鎖,該鎖保持到事務被提交或回滾。當兩個或多個會話在表的同一條記錄上執行 DML語句時,第一個會話在該條記錄上加鎖,其餘的會話處於等待狀態。當第一個會話提交後,TX鎖被釋放,其餘會話才能夠加鎖。 spa
當Oracle數據庫發生TX鎖等待時,若是不及時處理經常會引發Oracle數據庫掛起,或致使死鎖的發生,產生ORA-60的錯誤。這些現象都會對實際應用產生極大的危害,如長時間未響應,大量事務失敗等。 .net
悲觀封鎖和樂觀封鎖1、悲觀封鎖
鎖在用戶修改以前就發揮做用:
Select ..for update(nowait)
Select * from tab1 for update
用戶發出這條命令以後,oracle將會對返回集中的數據創建行級封鎖,以防止其餘用戶的修改。
若是此時其餘用戶對上面返回結果集的數據進行dml或ddl操做都會返回一個錯誤信息或發生阻塞。
1:對返回結果集進行update或delete操做會發生阻塞。
2:對該表進行ddl操做將會報:Ora-00054:resource busy and acquire with nowait specified.
緣由分析
此時Oracle已經對返回的結果集上加了排它的行級鎖,全部其餘對這些數據進行的修改或刪除操做都必須等待這個鎖的釋放,產生的外在現象就是其餘的操做將發生阻塞,這個這個操做commit或rollback.
一樣這個查詢的事務將會對該表加表級鎖,不容許對該表的任何ddl操做,不然將會報出ora-00054錯誤::resource busy and acquire with nowait specified.
阻塞
定義:
當一個會話保持另外一個會話正在請求的資源上的鎖定時,就會發生阻塞。被阻塞的會話將一直掛起,直到持有鎖的會話放棄鎖定的資源爲止。4個常見的dml語句會產生阻塞
INSERT
UPDATE
DELETE
SELECT…FOR UPDATE
INSERT
Insert發生阻塞的惟一狀況就是用戶擁有一個建有主鍵約束的表。當2個的會話同時試圖向表中插入相同的數據時,其中的一個會話將被阻塞,直到另一個會話提交或會滾。一個會話提交時,另外一個會話將收到主鍵重複的錯誤。回滾時,被阻塞的會話將繼續執行。
UPDATE 和DELETE當執行Update和delete操做的數據行已經被另外的會話鎖定時,將會發生阻塞,直到另外一個會話提交或會滾。
Select …for update
當一個用戶發出select..for update的錯做準備對返回的結果集進行修改時,若是結果集已經被另外一個會話鎖定,就是發生阻塞。須要等另外一個會話結束以後纔可繼續執行。能夠經過發出 select… for update nowait的語句來避免發生阻塞,若是資源已經被另外一個會話鎖定,則會返回如下錯誤:Ora-00054:resource busy and acquire with nowait specified.
死鎖-deadlock
定義:當兩個用戶但願持有對方的資源時就會發生死鎖.
即兩個用戶互相等待對方釋放資源時,oracle認定爲產生了死鎖,在這種狀況下,將以犧牲一個用戶做爲代價,另外一個用戶繼續執行,犧牲的用戶的事務將回滾.
例子:
1:用戶1對A表進行Update,沒有提交。
2:用戶2對B表進行Update,沒有提交。
此時雙反不存在資源共享的問題。
3:若是用戶2此時對A表做update,則會發生阻塞,須要等到用戶一的事物結束。
4:若是此時用戶1又對B表做update,則產生死鎖。此時Oracle會選擇其中一個用戶進行會滾,使另外一個用戶繼續執行操做。
原由:
Oracle的死鎖問題實際上不多見,若是發生,基本上都是不正確的程序設計形成的,通過調整後,基本上都會避免死鎖的發生。
表1 Oracle的TM鎖類型 | |||
鎖模式 | 鎖描述 | 解釋 | SQL操做 |
0 | none | ||
1 | NULL | 空 | Select |
2 | SS(Row-S) | 行級共享鎖,其餘對象只能查詢這些數據行 | Select for update、Lock for update、Lock row share |
3 | SX(Row-X) | 行級排它鎖,在提交前不容許作DML操做 | Insert、Update、Delete、Lock row share |
4 | S(Share) | 共享鎖 | Create index、Lock share |
5 | SSX(S/Row-X) | 共享行級排它鎖 | Lock share row exclusive |
6 | X(Exclusive) | 排它鎖 | Alter table、Drop able、Drop index、Truncate table 、Lock exclusive |
1. 關於 V$lock 表和相關視圖的說明
Column |
Datatype |
Description |
ADDR |
RAW(4 | 8) |
Address of lock state object |
KADDR |
RAW(4 | 8) |
Address of lock |
SID |
NUMBER |
Identifier for session holding or acquiring the lock |
TYPE |
VARCHAR2(2) |
Type of user or system lock The locks on the user types are obtained by user applications. Any process that is blocking others is likely to be holding one of these locks. The user type locks are: TM - DML enqueue TX - Transaction enqueue UL - User supplied -- 咱們主要關注TX 和TM 兩種類型的鎖 --UL 鎖用戶本身定義的,通常不多會定義,基本不用關注 -- 其它均爲系統鎖,會很快自動釋放,不用關注 |
ID1 |
NUMBER |
Lock identifier #1 (depends on type) |
ID2 |
NUMBER |
Lock identifier #2 (depends on type) --- 當lock type 爲TM 時,id1 爲DML-locked object 的object_id --- 當lock type 爲TX 時,id1 爲usn+slot ,而id2 爲seq 。 -- 當lock type 爲其它時,不用關注 |
LMODE |
NUMBER |
Lock mode in which the session holds the lock:
--大於0時表示 當前會話以某種模式 佔有 該鎖,等於0時表示當前會話正在等待該鎖資源,即表示該會話被阻塞。 -- 每每在發生TX 鎖時,伴隨着TM 鎖,好比一個sid=9 會話擁有一個TM 鎖,通常會擁有一個或幾個TX 鎖,但他們的id1 和id2 是不一樣的,請注意 |
REQUEST |
NUMBER |
Lock mode in which the process requests the lock:
-- 大於0時,表示當前會話被阻塞,其它會話佔有改鎖的模式 |
CTIME |
NUMBER |
Time since current mode was granted |
BLOCK |
NUMBER |
The lock is blocking another lock 0, 'Not Blocking', /* Not blocking any other processes */
|
2.其它相關視圖說明
視圖名 | 描述 | 主要字段說明 |
v$session | 查詢會話的信息和鎖的信息。 | sid,serial#:表示會話信息。 program:表示會話的應用程序信息。 row_wait_obj#:表示等待的對象,和dba_objects中的object_id相對應。 lockwait :該會話等待的鎖的地址,與v$lock的kaddr對應. |
v$session_wait | 查詢等待的會話信息。 | sid:表示持有鎖的會話信息。 Seconds_in_wait:表示等待持續的時間信息 Event:表示會話等待的事件,鎖等於enqueue |
dba_locks | 對v$lock的格式化視圖。 | Session_id:和v$lock中的Sid對應。 Lock_type:和v$lock中的type對應。 Lock_ID1: 和v$lock中的ID1對應。 Mode_held,mode_requested:和v$lock中 的lmode,request相對應。 |
v$locked_object | 只包含DML的鎖信息,包括回滾段和會話信息。 | Xidusn,xidslot,xidsqn:表示回滾段信息。和 v$transaction相關聯。 Object_id:表示被鎖對象標識。 Session_id:表示持有鎖的會話信息。 Locked_mode:表示會話等待的鎖模式的信 息,和v$lock中的lmode一致。 |
select a.sid holdsid,b.sid waitsid,a.type ,a.id1,a.id2,a.ctime from v$lock a,v$lock b
where a.id1=b.id1 and a.id2=b.id2 and a.block = 1 and b.block = 0 ;