一 鎖(Lock)
01,鎖的概念
數據庫是一個多用戶使用的共享資源。當多個用戶併發地存取數據時,在數 據庫中就會產生多個事務同時存取同一數據的狀況。若對併發操做不加控制就可 能會讀取和存儲不正確的數據,破壞數據庫的一致性。 加鎖是實現數據庫併發控制的一個很是重要的技術。當事務在對某個數據對 象進行操做前,先向系統發出請求,對其加鎖。加鎖後事務就對該數據對象有了 必定的控制,在該事務釋放鎖以前,其餘的事務不能對此數據對象進行更新操做。 在Oracle 數據庫中,它並非對某個表加上鎖或者某幾行加上鎖,鎖是以 數據塊的一個屬性存在的。 也就是說,每一個數據塊自己就存儲着本身數據塊中 數據的信息,這個地方叫ITL(Interested Transaction List),凡是在這個數據塊上有活動的事務,它的信息就會記錄在這裏面供後續的操做查詢,一保證事務的一 致性。
二 ,鎖的分類
按用戶與系統劃分,能夠分爲自動鎖與顯示鎖
a) 自動鎖(Automatic Locks):
當進行一項數據庫操做時,缺省狀況下,系統自動爲此數據庫操做得到全部有必要的鎖。自動鎖分DML鎖,DDL鎖,system locks。 node
b) 顯示鎖(Manual Data Locks):
某些狀況下,須要用戶顯示的鎖定數據庫操做要用到的數據,才能使數據庫操做執行得更好,顯示鎖是用戶爲數據庫對象設定的。sql
按鎖級別劃分,可分爲: 排它鎖(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)
共享方式的表級鎖是對錶中的全部數據進行加鎖,該鎖用於保護查詢數據的一致性,防止其它用戶對已加鎖的表進行更新。session
其它用戶只能對該表再施加共享方式的鎖,而不能再對該表施加獨佔方式的鎖,共享更新鎖能夠再施加,但不容許持有共享更新封鎖的進程作更新。數據結構
共享該表的全部用戶只能查詢表中的數據,但不能更新。併發
共享方式的表級鎖只能由用戶用 SQL 語句來設置.oracle
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系統中能自動發現死鎖,並選擇代價最小的,即完成工做量最少的事務予以撤消,釋放該事務所擁有的所有鎖,記其它的事務繼續工做下去。 從系統性能上考慮,應該儘量減小資源競爭,增大吞吐量,所以用戶在給併發操做加鎖時,應注意如下幾點: 一、對於UPDATE和DELETE操做,應只鎖要作改動的行,在完成修改後當即提交。 二、當多個事務正利用共享更新的方式進行更新,則不要使用共享封鎖,而應採用共享更新鎖,這樣其它用戶就能使用行級鎖,以增長並行性。
三、儘量將對一個表的操做的併發事務施加共享更新鎖,從而可提升並行性。 四、在應用負荷較高的期間,不宜對基礎數據結構(表、索引、簇和視圖)進行修改 若是死鎖不能自動釋放,就須要咱們手工的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
來記錄數據庫自啓動以來全部等待事件的彙總信息。經過這個視圖,用戶能夠迅
速得到數據庫運行的整體概況。
來自書籍>>