oracle中鎖的分類:
enqueues---隊列類型的鎖,通常和業務相關的通常dml操作導致,數據寫入
latches--系統資源方面的鎖,防止資源爭用,比如內存結構,sql解析等。
比如需要訪問某個資源,但是如果要訪問這個資源需要拿到數據庫某個資源的授權,而這個資源的授權可以理解為latch。
鎖的原則:
- 只有被修改時,行才會被鎖定
- 當一條語句修改了一條記錄,只有這條記錄上被鎖定,oracle數據庫不存在鎖升級(行級鎖升級為表級鎖 不存在)
- 當某行被修改的時候,他將阻塞別人對他的修改
- 當一個事務修改一行時,將在這個行上加上行鎖TX,用于阻止其他事務對相同行的修改
- 讀永遠不會阻止寫,但有一個例外 select for update
- 寫永遠不會阻塞讀
- 當一行被修改后,oracle通過回滾段提供一致性讀。
常見的鎖
最常見的已知資源類型是TM、TX和UL資源:
- TM資源(稱為DML排隊)是在引用表的語句執行期間獲取的,以便在執行期間不會刪除或更改表。
- TX 鎖是在事務啟動其第一個更改時獲取的,并一直保留到事務執行 COMMIT 或 ROLLBACK 為止。它主要用作排隊機制,以便其他會話可以等待事務完成。TX 鎖的鎖名稱(ID1 和 ID2)反映了活動事務的事務 ID。
- UL資源表示由DBMSLOCK包定義的用戶自定義的鎖
注意:TX 鎖是一個應用程序編碼、設計和使用問題,只能通過使用更頻繁和顯式的 COMMIT 語句和任何其他次要代碼更改來更改應用程序代碼來修復。Oracle 支持部門無法修復 TX 鎖定等待問題,只能幫助識別導致等待的對象和命令。請與開發人員合作修復代碼并緩解 TX 鎖定等待。
TM就是DML鎖,是表級上的鎖。TX是事務鎖,是行級鎖。在執行DML操作時,先對表加TM鎖,如果加鎖成功,然后再加TX鎖。一般情況下,一個會話中,只會出現一個TX鎖,可能有多個TM鎖,這些TM所共享一個TX鎖。不同的語句加TM鎖的類型不同,類型就是下面說的LOCK MODE。在表級上加了TM鎖也是為了防止其他會話再在表上加上排它鎖(例如對表執行DDL語句)。一個表上可以加上多個TM鎖、TX鎖的
常用視圖學習鎖
- v$transaction視圖
第一個視圖是v$transaction,就是Oracle數據庫所有活動的事務數,所有活動的事務每一個活動的事務在這里有一行。
v$transaction
XIDUSN表示當前事務使用的回滾段的編號
XIDSLOT說明該事務在回滾段頭部的事務表中對應的記錄編號(也可以叫做槽號)
XIDSQN說明序列號,即該槽(slot)被重用的次數
STATUS說明該事務是否為活動的
- 實驗:
LUQX@oradb>delete from t;
2 rows deleted.
select xidusn,xidslot,xidsqn,status from v$transaction;
XIDUSN:事務使用的回滾段編號
XIDSLOT:使用哪個槽位
XIDSQN: 即該槽(slot)被重用的次數
這三個唯一標識一個事務的編號。
status為active標識事務狀態
- v$lock視圖
v$lock 記錄了session已經獲得的鎖定以及正在請求的鎖定的信息
SID說明session的ID號
TYPE說明鎖的類型,主要關注TX和TM TM表示表鎖或DML鎖,TX表示行鎖或事務鎖
Oracle執行 DML 語句時,系統自動在所要操作的表上申請 TM 類型的鎖。當 TM鎖獲得后,系統再自動申請 TX 類型的鎖,并將實際鎖定的數據行的鎖標志位進行置位。
TM 鎖包括了SS 、 SX、 S 、X 等多種模式,在數據庫中用 0 -6 來表示
LMODE說明已經獲得的鎖定的模式,以數字編碼表示
REQUEST說明正在請求的鎖定的模式,以數字編碼表示
BLOCK說明是否阻止了其他用戶獲得鎖定,大于0說明是,等于0說明否
表級鎖TM和事務鎖TX。
對TM來講ID1是哪個對象,
對于TX來講ID1和ID2用來標識事務的和回滾段信息,標識事務信息。
ID1對應視圖V$TRANSACTION中的XIDUSN字段(Undo segment number:事務對應的撤銷段序列號)和XIDSLOT字段(Slot number:事務對應的槽位號)。
其中ID1的高16位為XIDUSN,低16位為XIDSLOT。
ID2對應視圖V$TRANSACTION中的XIDSQN字段(Sequence number:事務對應的序列號)以十進制數值表示環繞(wrap)次數,即該槽(slot)被重用的次數;
LMODE有如下幾種,針對TM鎖
0 =None;
1=Null ;
2=Row-S (SS,行級共享鎖,其他SQL語句只能查詢這些數據行),sql操作有select for update、lock for update、lock row share;
3=Row-X (SX,行級排它鎖,在提交前不允許做DML操作),sql操作有insert、update、delete、lock row share;
4=Share(共享鎖),sql操作有create index、lock share;
5=S/Row-X (SSX,共享行級排它鎖),sql操作有lock share row exclusive;
6=Exclusive(排它鎖),alter table、drop table、drop index、truncate table、look exclusive等DDL
不同級別鎖之間的兼容矩陣
可以看出從下往上排他性越來越強,如果對表加6級鎖那么此時此表不能加鎖操作
- 實驗
模擬兩個會話執行delete操作
會話1 sid144 執行delete from t;不提交
會話2 sid20 再次執行delete from t;語句的時候會處于卡住狀態。
新建會話查看此時數據塊的lock狀態。分析以下各個值的情況。
查看當前系統鎖狀態
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_mode,
decode(request,0,'None',1,'Null',2,'Row share',3,'Row Exclusive',4,'Share',5,'Share Row Exclusive',6,'Exclusive') request_mode,
block from v$lock
where type in ('TX','TM') order by 1,2;
圖上可以看出sid20及sid144兩個會話分別再表上面添加了TM及TX鎖。兩個會話TM類型的鎖的ID1對應的ID為鎖對象的object_id,可以通過dba_objects視圖查看對應的對象名稱。兩個會話TX類型的鎖對應的ID1和ID2的值一樣,是由于144會話阻塞了20會話導致的,正常來說兩個事務的id1和id2是不同的。圖上可以看出144持有lock_mode為exclusive-6級鎖。通過block字段值為1(表示有會話被阻塞),會話20并未持有任何tx鎖,而是再請求一個6級鎖。所以總上看出是由于144會話阻塞了20會話。
那么ID1和ID2如何轉換為回滾段相關信息呢如下步驟演示
SYS@oradb>select xidusn,xidslot,xidsqn,status from v$transaction;
通過transaction視圖查看當前活動的事務的事務信息
XIDUSN XIDSLOT XIDSQN STATUS
---------- ---------- ---------- ----------------
8 11 1807 ACTIVE
通過如下sql轉換TX鎖對應的ID1值進行拆分。輸入id1的值,通過如下命令id1可以轉換為對應的xidunsn及xidslot。
select trunc(524299/power(2,16)) as undo_blk#,bitand(524299,to_number('ffff','xxxx')) + 0 as slot# from dual;
另外可以看到sid20的會話正在請求鎖,這時對應的id1和id2并不是事務信息,而是持有鎖的事務的回歸段信息。當sid144會話提交或回滾后sid20的id1和id2會變為新的值(如下圖)。新值才是他的事務回滾段信息。同時sid144 后面的block值為1表示當前事務阻塞了其他事務的進行并不是代表阻塞了多少會話。
常用sql
- 查看當前的TX鎖及wait時常
select a.sid blocker_sid,
a.serial#,
a.username as blocker_username,
b.type,
decode(b.lmode,0,'None',1,'Null',2,'Row share',3,'Row Exclusive',4,'Share',5,'Share Row Exclusive',6,'Exclusive') lock_mode,
b.ctime as time_held,
c.sid as waiter_sid,
decode(c.request,0,'None',1,'Null',2,'Row share',3,'Row Exclusive',4,'Share',5,'Share Row Exclusive',6,'Exclusive') request_mode,
c.ctime time_waited from
v$lock b, v$enqueue_lock c, v$session a
where a.sid = b.sid and b.id1= c.id1(+) and b.id2 = c.id2(+) and c.type(+) = 'TX' and b.type = 'TX' and b.block = 1
order by
time_held, time_waited;
sql 144持有tx鎖并且持有993s 阻塞會話20 等待時間980.
2、TX鎖阻塞樹
column event format a30
column sess format a20
set linesize 250
set pagesize 0
break on id1 skip 1
select decode(request,0,'Holder:',' Waiter:') || s.inst_id || ':' || s.sid||','|| s.serial# sess,
id1, id2, lmode, request, l.type, ctime, s.username,s.sql_id, s.event
-- ,s.service_name
from gv$lock l, gv$session s
where (id1, id2, l.type) in
(select id1, id2, type from gv$lock where request>0
)
and l.sid=s.sid
and l.inst_id=s.inst_id
order by id1, ctime desc, request
/
可以看到holder持有鎖的會話信息sid 18 serial 231 id1 id2 lmod為6 request為0 tx類型
waiter等待鎖的會話信息sid 141 serial 401 id1 id2 lmod為0 request為6 tx類型
3、查看被阻塞會話執行的sql語句
查看被阻塞會話的sql執行語句
col event for a36
col username for a10
col sql_fulltext for a80
SELECT g.inst_id,
g.sid,
g.serial#,
g.event,
g.username,
g.sql_hash_value,
s.sql_fulltext
FROM gv$session g,
v$sql s
WHERE g.wait_class = 'Application'
AND g.sql_hash_value = s.hash_value;
4、查看某個快照周期出現row lock較多的對象
ALTER SESSION SET nls_timestamp_format='DD-MON-RR HH24:MI';
SELECT P.snap_id,
P.begin_interval_time,
O.owner,
O.object_name,
O.subobject_name,
O.object_type,
S.row_lock_waits_delta
FROM dba_hist_seg_stat S,
dba_hist_seg_stat_obj O,
dba_hist_snapshot P
WHERE S.dbid =O.dbid
AND S.ts# =O.ts#
AND S.obj# =O.obj#
AND S.dataobj# =O.dataobj#
AND S.snap_id =P.snap_id
AND S.dbid =P.dbid
AND S.instance_number =P.instance_number
AND S.row_lock_waits_delta > 0
AND P.snap_id BETWEEN 728 AND 729 #替換為你想查的snapid
ORDER BY 1,3,4;
5、查看鎖定的行信息(rowid)
查看到rowid后再根據rowid進行查看行信息。
column object_name format a30
SELECT do.object_name ,
s.row_wait_obj# ,
s.row_wait_file# ,
s.row_wait_block#,
s.row_wait_row# ,
dbms_rowid.rowid_create ( 1, data_object_id, rfile#, ROW_WAIT_BLOCK#, ROW_WAIT_ROW# )
FROM v$session s,
dba_objects do,
v$datafile v
WHERE s.blocking_session = &blocking_session
AND s.row_wait_obj# = do.object_id
AND s.row_wait_file# = v.file#; 輸入持有鎖的sid信息
其他視圖記錄
V$SESSION_WAIT
When a session is waiting on a resource, it can be found waiting on the enqueue wait event
Example:
SELECT * FROM V$SESSION_WAIT WHERE EVENT = 'enqueue';
SID identifier of session holding the lock
P1, P2, P3 determine the resource when event = 'enqueue'
SECONDS_IN_WAIT gives how long the wait did occurs
V$SESSION
Session information and row locking information
SID, SERIAL# identifier of the session
EVENT event waited on
P1, P2, P3 determine the resource when event = 'enqueue'
# SECONDS_IN_WAIT gives how long the wait did occurs
LOCKWAIT address of the lock waiting, otherwise null
ROW_WAIT_OBJ# object identified of the object we are waiting on (object_id of dba_objects)
ROW_WAIT_FILE#, ROW_WAIT_BLOCK#, ROW_WAIT_ROW#
file_id , block_id and row location within block of the locked row
V$LOCK
List of all the locks in the system
SID identifier of session holding the lock
TYPE, ID1 and ID2 determine the resource
LMODE and REQUEST indicate which queue the session is waiting on, as follows:
LMODE > 0, REQUEST = 0 owner
LMODE = 0, REQUEST > 0 acquirer
LMODE > 0, REQUEST > 0 converter
CTIME time since current mode was converted
BLOCK are we blocking another lock
BLOCK = 0 non blocking
BLOCK = 1 blocking others
DBA_LOCK or DBA_LOCKS
Formatted view on V$LOCK (created via $ORACLE_HOME/rdbms/admin/catblock.sql)
SESSION_ID == SID in V$LOCK
LOCK_TYPE, LOCK_ID1, LOCK_ID2 formatted value of TYPE, ID1, ID2 from V$LOCK
MODE_HELD and MODE_REQUESTED formatted value of LMODE and REQUEST from V$LOCK
LAST_CONVERT == CTIME of V$LOCK
BLOCKING_OTHERS formatted value of BLOCK from V$LOCK
V$TRANSACTION_ENQUEUE
Subset of V$LOCK for the blocking TX resources only
(same description as for the V$LOCK view)
V$ENQUEUE_LOCK
Subset of V$LOCK for the system resources only and
blocked TX resources only. (same description as for the V$LOCK view)
DBA_DML_LOCKS
Subset of the V$LOCK for the DML (TM) locks only
Created via $ORACLE_HOME/rdbms/admin/catblock.sql
Same description as the DBA_LOCK view
V$LOCKED_OBJECT
Same info as DBA_DML_LOCKS, but linked with the rollback and session information
XIDUSN, XIDSLOT and XIDSQN rollback information to be linked with V$TRANSACTION
OBJECT_ID object being locked
SESSION_ID session id
ORACLE_USERNAME oracle user name
OS_USER_NAME OS user name
PROCESS OS process id
LOCKED_MODE lock mode
V$RESOURCE
List of all the currently locked resources in the system.
Each row can be associated with one or more rows in V$LOCK
TYPE, ID1 and ID2 determine the resource
DBA_DDL_LOCKS
Has a row for each DDL lock that is being held, and one row for each outstanding request for a DDL lock.
It is subset of DBA_LOCKS
Same description as the DBA_LOCK view
DBA_WAITERS
View that retrieve information for each session waiting on a lock (created via $ORACLE_HOME/rdbms/admin/catblock.sql)
WAITING_SESSION waiting session
HOLDING_SESSION holding session
LOCK_TYPE, LOCK_ID1, LOCK_ID2 resource locked
MODE_HELD lock type held
MODE_REQUESTED lock type requested
DBA_BLOCKERS
View that gives the blocking sessions (created via $ORACLE_HOME/rdbms/admin/catblock.sql)
HOLDING_SESSION holding session