一 鎖(Lock)
01,鎖的概念
數據庫是一個多用戶使用的共享資源。當多個用戶並發地存取數據時,在數
據庫中就會產生多個事務同時存取同一數據的情況。若對並發操作不加控制就可
能會讀取和存儲不正確的數據,破壞數據庫的一致性。
加鎖是實現數據庫並發控制的一個非常重要的技術。當事務在對某個數據對
象進行操作前,先向系統發出請求,對其加鎖。加鎖后事務就對該數據對象有了
一定的控制,在該事務釋放鎖之前,其他的事務不能對此數據對象進行更新操作。
在Oracle 數據庫中,它並不是對某個表加上鎖或者某幾行加上鎖,鎖是以
數據塊的一個屬性存在的。 也就是說,每個數據塊本身就存儲着自己數據塊中
數據的信息,這個地方叫ITL(Interested Transaction List),凡是在這個數據塊上有活動的事務,它的信息就會記錄在這里面供后續的操作查詢,一保證事務的一
致性。
二 ,鎖的分類
按用戶與系統划分,可以分為自動鎖與顯示鎖
a) 自動鎖(Automatic Locks):
當進行一項數據庫操作時,缺省情況下,系統自動為此數據庫操作獲得所有有必要的鎖。自動鎖分DML鎖,DDL鎖,system locks。
b) 顯示鎖(Manual Data Locks):
某些情況下,需要用戶顯示的鎖定數據庫操作要用到的數據,才能使數據庫操作執行得更好,顯示鎖是用戶為數據庫對象設定的。
按鎖級別划分,可分為: 排它鎖(Exclusive Locks,即X鎖)和共享鎖(Share Locks,即S鎖)
a) 共享鎖( S ):
共享鎖使一個事務對特定數據庫資源進行共享訪問——另一事務也可對此資源進行訪問或獲得相同共享鎖。共享鎖為事務提供高並發性,但如拙劣的事務設計+共享鎖容易造成死鎖或數據更新丟失。
b) 排它鎖( X):
事務設置排它鎖后,該事務單獨獲得此資源,另一事務不能在此事務提交之前獲得相同對象的共享鎖或排它鎖。
按操作划分,可分為DML鎖(data locks,數據鎖)、DDL鎖(data dictionary lock)和 System Locks。
a) DML鎖
DML 鎖用於控制並發事務中的數據操縱,保證數據的一致性和完整性。 DML鎖主要用於保護並發情況下的數據完整性。 DML 語句能夠自動地獲得所需的表級鎖(TM)與行級(事務)鎖(TX)。 它又分為: ( 1) TM 鎖(表級鎖) ( 2) TX 鎖( 事務鎖或行級鎖) 當 Oracle 執行 DML 語句時,系統自動在所要操作的表上申請 TM 類型的鎖。當 TM 鎖獲得后,系統再自動申請 TX 類型的鎖,
並將實際鎖定的數據行的鎖標志位進行置位。 這樣在事務加鎖前檢查 TX鎖相容性時就不用再逐行檢查鎖標志,而只需檢查 TM 鎖模式的相容性即可,大大提高了系統的效率。 在數據行上只有 X 鎖(排他鎖)。 在 Oracle 數據庫中,當一個事務首次發起一個 DML 語句時就獲得一個 TX 鎖,該鎖保持到事務被提交或回滾。
當兩個或多個會話在表的同一條記錄上執行 DML 語句時,第一個會話在該條記錄上加鎖,其他的會話處於等待狀態。當第一個會話提交后, TX 鎖被釋放,
其他會話才可以加鎖。 當 Oracle 數據庫發生 TX 鎖等待時,如果不及時處理常常會引起 Oracle 數據庫掛起,或導致死鎖的發生,產生ORA-600 的錯誤。
這些現象都會對實際應用產生極大的危害,如長時間未響應,大量事務失敗等。
A,1)TM鎖(表鎖)
TM 鎖用於確保在修改表的內容時,表的結構不會改變,例如防止在 DML 語句執行期間相關的表被移除。當用戶對表執行 DDL 或 DML 操作時,
將獲取一個此表的表級鎖。 當事務獲得行鎖后,此事務也將自動獲得該行的表鎖(共享鎖),以防止其它事務進行 DDL 語句影響記錄行的更新。 事務也可以在進行過程中獲得共享鎖或排它鎖,只有當事務顯示使用 LOCK TABLE 語 句顯示的定義一個排它鎖時,事務才會獲得表上的排它鎖,
也可使用 LOCK TABLE 顯示的定義一個表級的共享鎖。 TM 鎖包括了 SS、 SX、 S、 X 等多種模式,在數據庫中用 0-6 來表示。不同的 SQL 操作產生不同類型的 TM 鎖
A,2) TX 鎖( 事務鎖或行級鎖)
當事務執行數據庫插入、更新、刪除操作時,該事務自動獲得操作表中操作行的排它鎖。
事務發起第一個修改時會得到TX 鎖(事務鎖),而且會一直持有這個鎖,直至事務執行提交(COMMIT)或回滾(ROLLBACK)。
對用戶的數據操縱, Oracle 可以自動為操縱的數據進行加鎖,但如果有操縱授權,則為滿足並發操縱的需要另外實施加鎖。
DML 鎖可由一個用戶進程以顯式的方式加鎖,也可通過某些 SQL 語句隱含方式實現。 這部分屬於 Manual Data Locks。
原理:一個事務要修改塊中的數據,必須獲得該塊中的一個itl,通過itl和undo segment header中的transaction table,
可以知道事務是否處於活動階段。事務在修改塊時(其實就是在修改行)會檢查行中row header中的標志位,如果該標志位為0(該行沒有被活動的事務鎖住),
就把該標志位修改為事務在該塊獲得的itl的序號,這樣當前事務就獲得了對記錄的鎖定,然后就可以修改行數據了,這也就是oracle行鎖實現的原理。
DML 鎖有如下三種加鎖方式:
共享鎖方式( SHARE) 獨占鎖方式( EXCLUSIVE) 共享更新鎖( SHARE UPDATE)
其中:
SHARE, EXCLUSIVE 用於 TM 鎖(表級鎖)
SHARE UPDATE 用於 TX 鎖( 行級鎖)
(1)共享鎖方式( SHARE)
共享方式的表級鎖是對表中的所有數據進行加鎖,該鎖用於保護查詢數據的一致性,防止其它用戶對已加鎖的表進行更新。
其它用戶只能對該表再施加共享方式的鎖,而不能再對該表施加獨占方式的鎖,共享更新鎖可以再施加,但不允許持有共享更新封鎖的進程做更新。
共享該表的所有用戶只能查詢表中的數據,但不能更新。
共享方式的表級鎖只能由用戶用 SQL 語句來設置.
LOCK TABLE <表名>[,<表名>]... IN SHARE MODE [NOWAIT]
執行該語句,對一個或多個表施加共享方式的表封鎖。當指定了選擇項 NOWAIT,若該鎖暫時不能施加成功,則返回並由用戶決定是進行等待,還是先去執行別的語句。
持有共享鎖的事務,在出現如下之一的條件時,便釋放其共享鎖:
A、執行COMMIT或ROLLBACK語句。
B、退出數據庫(LOG OFF)。
C、程序停止運行。
共享方式表級鎖常用於一致性查詢過程,即在查詢數據期間表中的數據不發生改變。
(2)獨占方式表級鎖(Exclusive)
獨占方式表級鎖是用於加鎖表中的所有數據,擁有該獨占方式表封鎖的用戶,即可以查詢該表,又可以更新該表,其它的用戶不能再對該表施加任何加鎖
(包括共享、獨占或共享更新封鎖)。其它用戶雖然不能更新該表,但可以查詢該表。
獨占方式的表封鎖可通過如下的SQL語句來顯示地獲得:
LOCK TABLE <表名>[,<表名>].... IN EXCLUSIVE MODE [NOWAIT]
獨占方式的表級鎖也可以在用戶執行DML語句INSERT、UPDATE、DELETE時隱含獲得。
擁有獨占方式表封鎖的事務,在出現如下條件之一時,便釋放該封鎖:
(1)、執行COMMIT或ROLLBACK語句。
(2)、退出數據庫(LOG OFF)
(3)、程序停止運行。
獨占方式封鎖通常用於更新數據,當某個更新事務涉及多個表時,可減少發生死鎖。
(3)共享更新加鎖方式(Share Update)
共享更新加鎖是對一個表的一行或多行進行加鎖,因而也稱作行級加鎖。表級加鎖雖然保證了數據的一致性,但卻減弱了操作數據的並行性。行級加鎖確保
在用戶取得被更新的行到該行進行更新這段時間內不被其它用戶所修改。因而行級鎖即可保證數據的一致性又能提高數據操作的迸發性。
可通過如下的兩種方式來獲得行級封鎖:
(1)、執行如下的SQL封鎖語句,以顯示的方式獲得:
LOCK TABLE <表名>[,<表名>].... IN SHARE UPDATE MODE
[NOWAIT]
(2)、用如下的SELECT ...FOR UPDATE語句獲得:
SELECT <列名>[,<列名>]...FROM <表名> WHERE <條件> FOR
UPDATE OF <列名>[,<列名>].....[NOWAIT]
一旦用戶對某個行施加了行級加鎖,則該用戶可以查詢也可以更新被加鎖的數據行,其它用戶只能查詢但不能更新被加鎖的數據行.如果其它用戶想更新該
表中的數據行,則也必須對該表施加行級鎖.即使多個用戶對一個表均使用了共享更新,但也不允許兩個事務同時對一個表進行更新,真正對表進行更新時,是
以獨占方式鎖表,一直到提交或復原該事務為止。行鎖永遠是獨占方式鎖。
當出現如下之一的條件,便釋放共享更新鎖:
(1)、執行提交(COMMIT)語句;
(2)、退出數據庫(LOG OFF)
(3)、程序停止運行。
執行ROLLBACK操作不能釋放行鎖。
b) DDL鎖(dictionary locks)
DDL鎖用於保護數據庫對象的結構,如表、索引等的結構定義。 DDL鎖又可以分為:排它DDL鎖、共享DDL鎖、分析鎖
1) 排它DDL鎖:
創建、修改、刪除一個數據庫對象的DDL語句獲得操作對象的 排它鎖。如使用alter table語句時,為了維護數據的完成性、一致性、合法性,該事務獲得一排
它DDL鎖。
(2) 共享DDL鎖:
需在數據庫對象之間建立相互依賴關系的DDL語句通常需共享獲得DDL鎖。如創建一個包,該包中的過程與函數引用了不同的數據庫表,當編譯此包時,
該事務就獲得了引用表的共享DDL鎖。
(3) 分析鎖:
ORACLE使用共享池存儲分析與優化過的SQL語句及PL/SQL程序,使運行相同語句的應用速度更快。一個在共享池中緩存的對象獲得它所引用數據庫對
象的分析鎖。分析鎖是一種獨特的DDL鎖類型,ORACLE使用它追蹤共享池對象及它所引用數據庫對象之間的依賴關系。當一個事務修改或刪除了共享池持有
分析鎖的數據庫對象時,ORACLE使共享池中的對象作廢,下次在引用這條SQL/PLSQL語 句時,ORACLE重新分析編譯此語句。
DDL級加鎖也是由ORACLE RDBMS來控制,它用於保護數據字典和數據定義改變時的一致性和完整性。它是系統在對SQL定義語句作語法分析時自動
地加鎖,無需用戶干予。
字典/語法分析加鎖共分三類:
(1)字典操作鎖:
用於對字典操作時,鎖住數據字典,此封鎖是獨占的,從而保護任何一
個時刻僅能對一個字典操作。
(2)字典定義鎖:
用於防止在進行字典操作時又進行語法分析,這樣可以避免在查詢字典
的同時改動某個表的結構。
(3)表定義鎖:
用於一個SQL語句正當訪問某個表時,防止字典中與該表有關的項目被
修改。
死鎖
死鎖
當兩個用戶希望持有對方的資源時就會發生死鎖.
即兩個用戶互相等待對方釋放資源時,oracle認定為產生了死鎖,在這種情況下,將以犧牲一個用戶作為代價,另一個用戶繼續執行,犧牲的用戶的事務將回滾。
場景
1:用戶 1 對 A 表進行 Update,沒有提交。
2:用戶 2 對 B 表進行 Update,沒有提交。
此時雙反不存在資源共享的問題。
3:如果用戶 2 此時對 A 表作 update,則會發生阻塞,需要等到用戶一的事物結束。
4:如果此時用戶 1 又對 B 表作 update,則產生死鎖。此時 Oracle 會選擇其中一個用戶進行會滾,使另一個用戶繼續執行操作。
起因:
Oracle的死鎖問題實際上很少見,如果發生,基本上都是不正確的程序設計造成的,經過調整后,基本上都會避免死鎖的發生。
在Oracle系統中能自動發現死鎖,並選擇代價最小的,即完成工作量最少的事務予以撤消,釋放該事務所擁有的全部鎖,記其它的事務繼續工作下去。
從系統性能上考慮,應該盡可能減少資源競爭,增大吞吐量,因此用戶在給並發操作加鎖時,應注意以下幾點:
1、對於UPDATE和DELETE操作,應只鎖要做改動的行,在完成修改后立即提交。
2、當多個事務正利用共享更新的方式進行更新,則不要使用共享封鎖,而應采用共享更新鎖,這樣其它用戶就能使用行級鎖,以增加並行性。
3、盡可能將對一個表的操作的並發事務施加共享更新鎖,從而可提高並行性。
4、在應用負荷較高的期間,不宜對基礎數據結構(表、索引、簇和視圖)進行修改
如果死鎖不能自動釋放,就需要我們手工的kill session。
三,鎖的操作
01,創建鎖
生成鎖,即啟動三個連接到oracle數據庫,兩台同時操作一個表,另一台查看爭用用情況
02,查看死鎖情況
SELECT 'alter system kill session ''' || sid || ',' || serial# || ''';' "Deadlock" FROM v$session WHERE sid IN (SELECT sid FROM v$lock WHERE block = 1);
需要注意的是id再100以下可能是一個aplication,對應的是事務才能kill
03,跟蹤問題 的sql
SELECT s.sid, q.sql_text FROM v$sqltext q, v$session s WHERE q.address = s.sql_address AND s.sid = &sid ORDER BY piece;
點擊后要求輸入id,這個為查詢出來的id值
04,查看誰鎖了誰
SELECT s1.username || '@' || s1.machine || ' ( SID=' || s1.sid || ' ) is blocking ' || s2.username || '@' || s2.machine || ' ( SID=' || s2.sid || ' ) ' AS blocking_status FROM v$lock l1, v$session s1, v$lock l2, v$session s2 WHERE s1.sid = l1.sid AND s2.sid = l2.sid AND l1.BLOCK = 1 AND l2.request > 0 AND l1.id1 = l2.id1 AND l2.id2 = l2.id2;
或者這樣查看
SQL> col USER_NAME format a10; SQL> col OWNER format a10; SQL> col OBJECT_NAME format a10; SQL> col OBJECT_TYPE format a10; SQL> SELECT LPAD (' ', DECODE (l.xidusn, 0, 3, 0)) || l.oracle_username User_name, o.owner, o.object_name, o.object_type, s.sid, s.serial# FROM v$locked_obje 2 3 4 5 6 7 8 9 10 ct l, dba_objects o, v$session s WHERE l.object_id = o.object_id AND l.session_id = s.sid ORDER BY o.object_id, xidusn DESC 11 12 ; USER_NAME OWNER OBJECT_NAM OBJECT_TYP SID SERIAL# ---------- ---------- ---------- ---------- ---------- ---------- SYS SYS T TABLE 276 6522 SYS SYS T TABLE 29 25094
四,鎖與阻塞
01,概念
通常來講,系統如果平時運行正常,突然會停止不動,多半是被阻塞(Blocked)住了。 我們可以通過v$lock 這張視圖,看查看阻塞的信息。
鎖的視圖:
SQL> desc v$lock Name Null? Type ----------------------------------------- -------- ---------------------------- ADDR RAW(8) KADDR RAW(8) SID NUMBER TYPE VARCHAR2(2) ID1 NUMBER ID2 NUMBER LMODE NUMBER REQUEST NUMBER CTIME NUMBER BLOCK NUMBER CON_ID NUMBER
SQL> select * from v$lock; ADDR KADDR SID TY ID1 ID2 LMODE REQUEST CTIME BLOCK CON_ID ---------------- ---------------- ---------- -- ---------- ---------- ---------- ---------- ---------- ---------- ---------- 000000007DABD000 000000007DABD080 246 MR 21 0 4 0 165382 0 0 000000007DAC0640 000000007DAC06C0 7 KT 18972 5 4 0 510918 0 0 000000007DABCBA0 000000007DABCC20 247 XR 4 0 1 0 0 0 0 000000007DABCA88 000000007DABCB08 247 RD 1 0 1 0 693013 0 0 000000007DABC970 000000007DABC9F0 247 CF 0 0 2 0 693013 0 0 000000007DABCDD0 000000007DABCE50 10 RT 1 0 6 0 693009 0 0 000000007DABCCB8 000000007DABCD38 247 RS 25 1 2 0 693009 0 0 000000007DABD248 000000007DABD2C8 246 MR 3 0 4 0 693009 0 0 000000007DABDA08 000000007DABDA88 246 MR 5 0 4 0 693008 0 0 000000007DABE3F8 000000007DABE478 246 MR 6 0 4 0 693008 0 0 000000007DABF018 000000007DABF098 246 MR 9 0 4 0 692971 0 0 ADDR KADDR SID TY ID1 ID2 LMODE REQUEST CTIME BLOCK CON_ID ---------------- ---------------- ---------- -- ---------- ---------- ---------- ---------- ---------- ---------- ---------- 000000007DABDF80 000000007DABE000 246 MR 203 0 4 0 692971 0 0 000000007DABD590 000000007DABD610 246 MR 1 0 4 0 693009 0 0 000000007DABCEE8 000000007DABCF68 246 MR 4 0 4 0 693009 0 0 000000007DABD6A8 000000007DABD728 246 MR 7 0 4 0 693009 0 0 000000007DABD7C0 000000007DABD840 246 MR 201 0 4 0 693009 0 0 000000007DAC0DE8 000000007DAC0E68 246 MR 19 0 4 0 167393 0 0 000000007DABD478 000000007DABD4F8 248 TS 3 1 3 0 693009 0 1 000000007DABD8D8 000000007DABD958 7 KD 0 0 6 0 693009 0 0 000000007DABE1B0 000000007DABE230 246 MR 8 0 4 0 693008 0 0 000000007DABD360 000000007DABD3E0 16 AE 133 1 4 0 693008 0 0 000000007DABDD50 000000007DABDDD0 275 AE 133 1 4 0 451 0 0 ADDR KADDR SID TY ID1 ID2 LMODE REQUEST CTIME BLOCK CON_ID ---------------- ---------------- ---------- -- ---------- ---------- ---------- ---------- ---------- ---------- ---------- 000000007DABECD0 000000007DABED50 276 AE 133 1 4 0 14025 0 0 000000007DAC1260 000000007DAC12E0 29 AE 133 1 4 0 11965 0 0 000000007DAC0758 000000007DAC07D8 7 KT 18972 3 4 0 17990 0 0 000000007DABF130 000000007DABF1B0 246 MR 10 0 4 0 692971 0 0 000000007DABC858 000000007DABC8D8 246 MR 204 0 4 0 512035 0 0 000000007DABE2E0 000000007DABE360 246 MR 202 0 4 0 693008 0 0 000000007DABDC38 000000007DABDCB8 246 PW 1 0 3 0 693007 0 0 000000007DAC0870 000000007DAC08F0 246 MR 18 0 4 0 510918 0 0 000000007DABF248 000000007DABF2C8 246 MR 11 0 4 0 692971 0 0 000000007DABE628 000000007DABE6A8 7 KT 18972 2 4 0 693008 0 0 000000007DABFF98 000000007DAC0018 246 MR 22 0 4 0 165311 0 0 ADDR KADDR SID TY ID1 ID2 LMODE REQUEST CTIME BLOCK CON_ID ---------------- ---------------- ---------- -- ---------- ---------- ---------- ---------- ---------- ---------- ---------- 000000007DAC0BB8 000000007DAC0C38 7 KT 18972 4 4 0 512035 0 0 000000007DAC0988 000000007DAC0A08 246 MR 15 0 4 0 512035 0 0 000000007DABF360 000000007DABF3E0 246 MR 12 0 4 0 692971 0 0 000000007DABEDE8 000000007DABEE68 248 TS 3 1 3 0 689410 0 3 000000007DABF8F0 000000007DABF970 29 TX 65541 1671 0 6 397 0 1 000000007ADFBA08 000000007ADFBA90 276 TX 65541 1671 6 0 406 1 1 000000007DAC0AA0 000000007DAC0B20 7 KT 19005 1 4 0 3591 0 0 000000007DABF490 000000007DABF510 248 TS 3 1 3 0 513214 0 4 000000007DAC0510 000000007DAC0590 246 MR 17 0 4 0 510918 0 0 000000007DABEA88 000000007DABEB08 246 MR 13 0 4 0 512035 0 0 000000007DAC03F8 000000007DAC0478 246 MR 14 0 4 0 512035 0 0 ADDR KADDR SID TY ID1 ID2 LMODE REQUEST CTIME BLOCK CON_ID ---------------- ---------------- ---------- -- ---------- ---------- ---------- ---------- ---------- ---------- ---------- 000000007DABFA08 000000007DABFA88 246 MR 205 0 4 0 510918 0 0 000000007DAC00B0 000000007DAC0130 246 MR 20 0 4 0 165939 0 0 000000007DABFC38 000000007DABFCB8 246 MR 16 0 4 0 510918 0 0 00007FD03B161448 00007FD03B1614B8 29 TM 75220 0 3 0 397 0 1 00007FD03B161448 00007FD03B1614B8 276 TM 75220 0 3 0 11897 0 1 49 rows selected.
我們關注的比較多的是request 和 block 字段。
如果某個request列是一個非0值,那么它就是在等待一個鎖。 如果block列是1,這個SID 就持有了一個鎖,並且阻塞別人獲得這個鎖。 這個鎖的類型由TYPE 字段定義。鎖的模式有LMODE 字段定義,ID1 和ID2 字段定義了這個鎖的相關信息。ID1相同,就代表指向同一個資源。 這樣就有可能有加鎖者和等待者。
參考下面的TM鎖類型表。
結合 v$lock
和 v$session
視圖來查詢相關的信息:
SQL> SELECT sn.username, m.SID, sn.SERIAL#, m.TYPE, DECODE(m.lmode, 0, 'None', 1, 'Null', 2, 'Row Share', 3, 'Row Excl.', 2 3 4 5 6 7 8 9 10 11 12 13 4, 'Share', 5, 'S/Row Excl.', 6, 'Exclusive', lmode, LTRIM(TO_CHAR(lmode, '990'))) lmode, DECODE(m.request, 0, 14 15 16 17 18 19 20 21 22 23 24 'None', 1, 'Null', 2, 'Row Share', 3, 'Row Excl.', 4, 'Share', 5, 'S/Row Excl.', 6, ' 25 26 27 28 29 30 31 32 33 34 35 36 Exclusive', request, LTRIM(TO_CHAR(m.request, '990'))) request, m.id1, m.id2 FROM v$session sn, v$lock m WHERE (sn.SID = m.SID AND m.request != 0) --存在鎖請求,即被阻塞 OR (sn.SID = m.SID 37 38 39 40 41 42 43 44 45 --不存在鎖請求,但是鎖定的對象被其他會話請求鎖定 AND m.request = 0 AND lmode != 4 AND (id1, id2) IN (SELECT s.id1, s.id2 FROM v$lock s WHERE request != 0 AND s.id1 = m.id1 AND s.id2 = m.id2)) ORDER BY id1, id2, m.request; 46 47 48 49 50 51 52 USERNAME SID SERIAL# TY LMODE REQUEST ID1 ID2 -------------------------------------------------------------------------------------------------------------------------------- ---------- ---------- -- ----------- ----------- ---------- ---------- SYS 276 6522 TX Exclusive None 65541 1671 SYS29 25094 TX None Exclusive 65541 1671 SQL>
或者通過下面查詢
SQL> SELECT /*+ rule */ s.username, DECODE(l.TYPE, 'TM', 'TABLE LOCK', 'TX', 'ROW LOCK', NULL) lock_level, o.owner, o.object_name, o.object_type, s.sid, s.serial#, s.terminal, s.machine, s.program, s.osuser FROM v$session s, v$lock l, dba_objects o 2 3 4 5 6 7 8 9 10 11 12 13 WHERE l.sid = s.sid AND l.id1 = o.object_id(+) AND s.username IS NOT NULL; 14 15 16 USERNAMELOCK_LEVEL OWNER OBJECT_NAM OBJECT_TYP SID SERIAL# TERMINAL MACHINE PROGRAM OSUSER -------------------------------------------------------------------------------------------------------------------------------- ---------- ---- SYS SYS ORA$BASE EDITION 29 25094 pts/3 node12c01 sqlplus@node12c01 (TNS V1-V3) oracle SYSROW LOCK PUBLIC oracle/ord SYNONYM 29 25094 pts/3 node12c01 sqlplus@node12c01 (TNS V1-V3) oracle /media/jai /io/Memory CacheSeeka bleOutputS tream SYSTABLE LOCK SYS T TABLE 29 25094 pts/3 node12c01 sqlplus@node12c01 (TNS V1-V3) oracle SYSTABLE LOCK SYS T TABLE 276 6522 pts/0 node12c01 sqlplus@node12c01 (TNS V1-V3) oracle SYSROW LOCK PUBLIC oracle/ord SYNONYM 276 6522 pts/0 node12c01 sqlplus@node12c01 (TNS V1-V3) oracle USERNAMELOCK_LEVEL OWNER OBJECT_NAM OBJECT_TYP SID SERIAL# TERMINAL MACHINE PROGRAM OSUSER -------------------------------------------------------------------------------------------------------------------------------- ---------- --- CacheSeeka bleOutputS tream SYS SYS ORA$BASE EDITION 276 6522 pts/0 node12c01 sqlplus@node12c01 (TNS V1-V3) oracle SYS SYS ORA$BASE EDITION 275 12753 pts/4 node12c01 sqlplus@node12c01 (TNS V1-V3) oracle 7 rows selected. SQL>
引起阻塞的幾種常見情況
(1)DML語句引起阻塞
當一個會話保持另一個會話正在請求的資源上的鎖定時,就會發生阻塞。被阻塞的會話將一直掛起,直到持有鎖的會話放棄鎖定的資源為止。 4個常見的dml語句會產生阻塞: (1)INSERT (2)UPDATE (3)DELETE (4)SELECT…FOR UPDATE INSERT Insert 發生阻塞的唯一情況就是用戶擁有一個建有主鍵約束的表。當2個的會話同時試圖向表中插入相同的數據時,其中的一個會話將被阻塞,直到另外一個會話提交或會滾。 一個會話提交時,另一個會話將收到主鍵重復的錯誤。回滾時,被阻塞的會話將繼續執行。 Update 和 Delete UPDATE 和DELETE當執行Update和delete操作的數據行已經被另外的會話鎖定時,將會發生阻塞,直到另一個會話提交或會滾。 Select …for update 當一個用戶發出select..for update的錯作准備對返回的結果集進行修改時,如果結果集已經被另一個會話鎖定,此時Oracle已經對返回的結果集上加了排它 的行級鎖,所有其他對這些數據進行的修改或刪除操作都必須等待這個鎖的釋放(操作commit或rollback.),產生的外在現象就是其他的操作將發生阻塞. 同樣這個查詢的事務將會對該表加表級鎖,不允許對該表的任何ddl操作,否則將會報出Ora-00054:resource busy and acquire with nowait specified. 可以通過發出 select„ for update nowait的語句來避免發生阻塞,如果資源已經被另一個會話鎖定,則會返回以下錯誤:Ora-00054:resource busy and acquire with nowait specified.
(2)外鍵沒有創建索引
如果系統中有主,外鍵引用關系,並且滿足一下三個條件中的任意一個,那么就應該考慮給外鍵字段創建索引,否則系統的性能可能會下降甚至阻塞。 (1) 主表上有頻繁的刪除操作 (2) 主鍵上有頻繁的修改操作。 (3) 業務上經常會出現主表和從表做關聯查詢的情況。 第一和第二個條件操作的時候,主表會在從表上創建一個鎖定,以保證主表主鍵的修改不會導致從表的數據在引用上出現問題,這是一個數據引用完整性的 要求。 如果主表上經常出現這樣的刪除或者是對主鍵列進行修改的操作,或者每次操作的記錄數很多,都將會造成從表長時間被鎖定,而影響其他用戶的正常 操作。 比如主表每次刪除1000行數據,它就需要掃描從表1000次,以確定每一行記錄的改變都不會造成從表數據在引用上的不完整。 特別是在OLAP 系統中,從表經常會是非常巨大的表,在這種情況下,如果從表沒有索引,那么查詢幾乎是不可想象的。
Latch是內存中的資源鎖,數據庫對象(表,索引等)的鎖叫Lock。 Latch和Lock的區別: (1). Latch 是對內存數據結構提供互斥訪問的一種機制,而Lock是以不同 的模式來套取共享資源對象,各個模式間存在着兼容或排斥,從這點看出,Latch 的訪問,包括查詢也是互斥的,任何時候,只能有一個進程能pin住內存的某一 塊,幸好這個過程是相當的短暫,否則系統性能將沒的保障,從9I開始,允許 多個進程同時查詢相同的內存塊。 (2). Latch 只作用於內存中,他只能被當前實例訪問,而Lock作用於數據 庫對象,在RAC體系中實例間允許Lock檢測與訪問 (3). Latch 是瞬間的占用,釋放,Lock的釋放需要等到事務正確的結束, 他占用的時間長短由事務大小決定 (4). Latch 是非入隊的,而Lock是入隊的 (5). Latch 不存在死鎖,而Lock中存在。
V$SESSION: 代表數據庫活動的開始,視為源起。
V$SESSION_WAIT: 視圖用以實時記錄活動SESSION的等待情況,是當前信
息。
V$SESSION_WAIT_HISTORY: 是對V$SESSION_WAIT的簡單增強,記錄活
動SESSION的最近10次等待。
V$SQLTEXT: 當數據庫出現瓶頸時,通常可以從V$SESSION_WAIT找到那
些正在等待資源的SESSION,通過SESSION 的SID,聯合V$SESSION和
V$SQLTEXT視圖就可以捕獲這些SESSION正在執行的SQL語句。
V$ACTIVE_SESSION_HISTORY: 是ASH的核心,用以記錄活動SESSION的歷
史等待信息,每秒采樣一次,這部分內容記錄在內存中,期望值是記錄一個小時
的內容。
WRH#_ACTIVE_SESSION_HISTORY : 是V$ACTIVE_SESSION_HISTORY在
AWR的存儲地。
V$ACTIVE_SESSION_HISTORY: 中的信息會被定期(每小時一次)的刷新到負載
庫中,並缺省保留一個星期用於分析。
DBA_HIST_ACTIVE_SESS_HISTORY: 視圖是 WRH#_ACTIVE_SESSION_HISTORY視圖和其他幾個視圖的聯合展現,通常通
過這個視圖進行歷史數據的訪問。
V$SYSTEM_EVENT 由於V$SESSION記錄的是動態信息,和SESSION的生命
周期相關,而並不記錄歷史信息,所以ORACLE提供視圖V$SYSTEM_EVENT
來記錄數據庫自啟動以來所有等待事件的匯總信息。通過這個視圖,用戶可以迅
速獲得數據庫運行的總體概況。
來自書籍>>