一、等待事件的相關知識
1.1 等待事件主要可以分為兩類,即空閑(IDLE)等待事件和非空閑(NON-IDLE)等待事件。
1). 空閑等待事件指ORACLE正等待某種工作,在診斷和優化數據庫的時候,不用過多注意這部分事件。
2). 非空閑等待事件專門針對ORACLE的活動,指數據庫任務或應用運行過程中發生的等待,這些等待事件 是在調整數據庫的時候需要關注與研究的。
在Oracle 10g中的等待事件有872個,11g中等待事件1116個。 我們可以通過v$event_name 視圖來查看等待事件的相關信息。
1.2 查看v$event_name視圖的字段結構
SQL> desc v$event_name;
名稱 是否為空 類型
------------------- --------------- --------
EVENT# NUMBER
EVENT_ID NUMBER
NAME VARCHAR2(64)
PARAMETER1 VARCHAR2(64)
PARAMETER2 VARCHAR2(64)
PARAMETER3 VARCHAR2(64)
WAIT_CLASS_ID NUMBER
WAIT_CLASS# NUMBER
WAIT_CLASS VARCHAR2(64)
1.3 查看等待事件分類情況
SELECT
wait_class#,
wait_class_id,
wait_class,
COUNT ( * ) AS "count"
FROM v$event_name
GROUP BY wait_class#, wait_class_id, wait_class
ORDER BY wait_class#;
WAIT_CLASS# WAIT_CLASS_ID WAIT_CLASS count
----------- ------------- -------------------- ----------
0 1893977003 Other 717
1 4217450380 Application 17
2 3290255840 Configuration 24
3 4166625743 Administrative 54
4 3875070507 Concurrency 32
5 3386400367 Commit 2
6 2723168908 Idle 94
7 2000153315 Network 35
8 1740759767 User I/O 45
9 4108307767 System I/O 30
10 2396326234 Scheduler 7
11 3871361733 Cluster 50
12 644977587 Queueing 9
1.4 相關的幾個視圖
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來記錄數據庫自啟動以來所有等待事件的匯總信息。通過這個視圖,用戶可以迅速獲得數據庫運行的總體概況。
1.5 等待事件相關查詢
--------------------------查詢數據庫等待時間和實際執行時間的相對百分比---------------------
select *
from v$sysmetric a
where a.METRIC_NAME in
('Database CPU Time Ratio', 'Database Wait Time Ratio')
and a.INTSIZE_CSEC = (select max(intsize_csec) from v$sysmetric);
-------------------------------------查詢數據庫中過去30分鍾引起最多等待的sql語句----------------
select ash.USER_ID,
u.username,
sum(ash.WAIT_TIME) ttl_wait_time,
s.SQL_TEXT
from v$active_session_history ash, v$sqlarea s, dba_users u
where ash.SAMPLE_TIME between sysdate - 60 / 2880 and sysdate
and ash.SQL_ID = s.SQL_ID
and ash.USER_ID = u.user_id
group by ash.USER_ID, s.SQL_TEXT, u.username
order by ttl_wait_time desc
-----------------------------------------查詢數據庫中的等待事件----------------------
select event, count(*)
from v$session_wait
group by event
order by count(*) desc
---------------------------------------查詢數據庫過去15分鍾最重要的等待事件---------------
select ash.EVENT, sum(ash.WAIT_TIME + ash.TIME_WAITED) total_wait_time
from v$active_session_history ash
where ash.SAMPLE_TIME between sysdate - 30 / 2880 and sysdate
group by event
order by total_wait_time desc
----------------------------------------在過去15分鍾哪些用戶經歷了等待---------------------
select s.SID,
s.USERNAME,
sum(ash.WAIT_TIME + ash.TIME_WAITED) total_wait_time
from v$active_session_history ash, v$session s
where ash.SAMPLE_TIME between sysdate - 30 / 2880 and sysdate
and ash.SESSION_ID = s.SID
group by s.SID, s.USERNAME
order by total_wait_time desc;
-------------------------------------查詢等待時間最長的對象---------------------------------------
select a.CURRENT_OBJ#,
d.object_name,
d.object_type,
a.EVENT,
sum(a.WAIT_TIME + a.TIME_WAITED) total_wait_time
from v$active_session_history a, dba_objects d
where a.SAMPLE_TIME between sysdate - 30 / 2880 and sysdate
and a.CURRENT_OBJ# = d.object_id
group by a.CURRENT_OBJ#, d.object_name, d.object_type, a.EVENT
order by total_wait_time desc;
--------------------------------------------查詢過去15分鍾等待時間最長的sql語句---------------------------
select a.USER_ID,
u.username,
s.SQL_TEXT,
sum(a.WAIT_TIME + a.TIME_WAITED) total_wait_time
from v$active_session_history a, v$sqlarea s, dba_users u
where a.SAMPLE_TIME between sysdate - 30 / 2880 and sysdate
and a.SQL_ID = s.SQL_ID
and a.USER_ID = u.user_id
group by a.USER_ID, s.SQL_TEXT, u.username
order by total_wait_time desc;
------------------------------------------那些SQL消耗更多的IO--------------------------------------
select *
from (select s.PARSING_SCHEMA_NAME,
s.DIRECT_WRITES,
substr(s.SQL_TEXT, 1, 500),
s.DISK_READS
from v$sql s
order by s.DISK_READS desc)
where rownum < 20
---------------------------------------查看哪些會話正在等待IO資源-------------------------------------
SELECT username, program, machine, sql_id
FROM V$SESSION
WHERE EVENT LIKE 'db file%read';
----------------------------------查看正在等待IO資源的對象-----------------------------------
SELECT d.object_name, d.object_type, d.owner
FROM V$SESSION s, dba_objects d
WHERE EVENT LIKE 'db file%read'
and s.ROW_WAIT_OBJ# = d.object_id
---------------------------查看redo日志切換頻率---------------------------------------------
Select round(FIRST_TIME, 'DD'), THREAD#, Count(SEQUENCE#)
From v$log_history
Group By round(FIRST_TIME, 'DD'), THREAD#
Order By 1, 2
SELECT trunc(first_time) "Date",
to_char(first_time, 'Dy') "Day",
count(1) "Total",
SUM(decode(to_char(first_time, 'hh24'),'00',1,0)) "h0",
SUM(decode(to_char(first_time, 'hh24'),'01',1,0)) "h1",
SUM(decode(to_char(first_time, 'hh24'),'02',1,0)) "h2",
SUM(decode(to_char(first_time, 'hh24'),'03',1,0)) "h3",
SUM(decode(to_char(first_time, 'hh24'),'04',1,0)) "h4",
SUM(decode(to_char(first_time, 'hh24'),'05',1,0)) "h5",
SUM(decode(to_char(first_time, 'hh24'),'06',1,0)) "h6",
SUM(decode(to_char(first_time, 'hh24'),'07',1,0)) "h7",
SUM(decode(to_char(first_time, 'hh24'),'08',1,0)) "h8",
SUM(decode(to_char(first_time, 'hh24'),'09',1,0)) "h9",
SUM(decode(to_char(first_time, 'hh24'),'10',1,0)) "h10",
SUM(decode(to_char(first_time, 'hh24'),'11',1,0)) "h11",
SUM(decode(to_char(first_time, 'hh24'),'12',1,0)) "h12",
SUM(decode(to_char(first_time, 'hh24'),'13',1,0)) "h13",
SUM(decode(to_char(first_time, 'hh24'),'14',1,0)) "h14",
SUM(decode(to_char(first_time, 'hh24'),'15',1,0)) "h15",
SUM(decode(to_char(first_time, 'hh24'),'16',1,0)) "h16",
SUM(decode(to_char(first_time, 'hh24'),'17',1,0)) "h17",
SUM(decode(to_char(first_time, 'hh24'),'18',1,0)) "h18",
SUM(decode(to_char(first_time, 'hh24'),'19',1,0)) "h19",
SUM(decode(to_char(first_time, 'hh24'),'20',1,0)) "h20",
SUM(decode(to_char(first_time, 'hh24'),'21',1,0)) "h21",
SUM(decode(to_char(first_time, 'hh24'),'22',1,0)) "h22",
SUM(decode(to_char(first_time, 'hh24'),'23',1,0)) "h23"
FROM V$log_history
group by trunc(first_time), to_char(first_time, 'Dy')
Order by 1
二、33個常見的等待事件
1. Buffer busy waits
從本質上講,這個等待事件的產生僅說明了一個會話在等待一個Buffer(數據塊),但是導致這個現象的原因卻有很多種。
常見的兩種是:
· 當一個會話試圖修改一個數據塊,但這個數據塊正在被另一個會話修改時。
· 當一個會話需要讀取一個數據塊,但這個數據塊正在被另一個會話讀取到內存中時。
Oracle 操作的最小單位是塊(Block),即使你要修改一條記錄,也需要對這條記錄所在的這個數據塊做操作。 當你對這個數據塊做修改時,其他的會話將被阻止對這個數據塊上的數據做修改(即使其他用戶修改的不是當前用戶修改的數據),但是可以以一致性的方式讀取這個數據塊(from undo)。當前的用戶修改完這個數據塊后,將會立即釋放掉加在這個數據塊上的排他鎖,這樣另一個會話就可以繼續修改它。修改操作是一個非常短暫的時間,這種加鎖的機制我們叫Latch。
當一個會話修改一個數據塊時,是按照以下步驟來完成的:
· 以排他的方式獲得這個數據塊(Latch)
· 修改這個數據塊。
· 釋放Latch。
Buffer busy waits等待事件常見於數據庫中存在熱塊的時候,當多個用戶頻繁地讀取或者修改同樣的數據塊時,這個等待事件就會產生。 如果等待的時間很長,我們在AWR或者statspack 報告中就可以看到。
這個等待事件有三個參數。查看有幾個參數我們可以用以下SQL:
/* Formatted on 6/27/2011 1:06:09 PM (QP5 v5.114.809.3010) */
SELECT name,
parameter1,
parameter2,
parameter3
FROM v$event_name
WHERE name = 'buffer busy waits';
NAME PARAMETER1 PARAMETER2 PARAMETER3
-------------------- ---------- ---------- ----------
buffer busy waits file# block# class#
在下面的示例中,查詢的方法和這個一樣,所以其他事件對參數的查詢將不做過多的說明。
File#: 等待訪問數據塊所在的文件id號。
Blocks: 等待訪問的數據塊號。
ID: 在10g之前,這個值表示一個等待時間的原因,10g之后則表示等待事件的類別。
2. Buffer latch
內存中數據塊的存放位置是記錄在一個hash列表(cache buffer chains)當中的。當一個會話需要訪問某個數據塊時,它首先要搜索這個hash 列表,從列表中獲得數據塊的地址,然后通過這個地址去訪問需要的數據塊,這個列表Oracle會使用一個latch來保護它的完整性。 當一個會話需要訪問這個列表時,需要獲取一個Latch,只有這樣,才能保證這個列表在這個會話的瀏覽當中不會發生變化。
產生buffer latch的等待事件的主要原因是:
· Buffer chains太長,導致會話搜索這個列表花費的時間太長,使其他的會話處於等待狀態。
· 同樣的數據塊被頻繁訪問,就是我們通常說的熱快問題。
產生buffer chains太長,我們可以使用多個buffer pool的方式來創建更多的buffer chains,或者使用參數DB_BLOCK_LRU_LATCHES來增加latch的數量,以便於更多的會話可以獲得latch,這兩種方法可以同時使用。
這個等待事件有兩個參數:
Latch addr: 會話申請的latch在SGA中的虛擬地址。
通過以下的SQL語句可以根據這個地址找到它對應的Latch名稱:
/* Formatted on 6/27/2011 1:12:48 PM (QP5 v5.114.809.3010) */
select * from v$latch a,v$latchname b where
addr=latch addr -- 這里的latch addr 是你從等待事件中看到的值
and a.latch#=b.latch#;
chain#: buffer chains hash 列表中的索引值,當這個參數的值等於s 0xfffffff時,說明當前的會話正在等待一個LRU latch。
3. Control file parallel write
當數據庫中有多個控制文件的拷貝時,Oracle 需要保證信息同步地寫到各個控制文件當中,這是一個並行的物理操作過程,因為稱為控制文件並行寫,當發生這樣的操作時,就會產生control file parallel write等待事件。
控制文件頻繁寫入的原因很多,比如:
· 日志太過頻繁,導致控制文件信息相應地需要頻繁更新。
· 系統I/O 出現瓶頸,導致所有I/O出現等待。
當系統出現日志切換過於頻繁的情形時,可以考慮適當地增大日志文件的大小來降低日志切換頻率。
當系統出現大量的control file parallel write 等待事件時,可以通過比如降低控制文件的拷貝數量,將控制文件的拷貝存放在不同的物理磁盤上的方式來緩解I/O 爭用。
這個等待事件包含三個參數:
Files: Oracle 要寫入的控制文件個數。
Blocks: 寫入控制文件的數據塊數目。
Requests: 寫入控制請求的I/O 次數。
4. Control file sequential read
當數據庫需要讀取控制文件上的信息時,會出現這個等待事件,因為控制文件的信息是順序寫的,所以讀取的時候也是順序的,因此稱為控制文件順序讀,它經常發生在以下情況:
備份控制文件
RAC 環境下不同實例之間控制文件的信息共享
讀取控制文件的文件頭信息
讀取控制文件其他信息
這個等待事件有三個參數:
File#: 要讀取信息的控制文件的文件號。
Block#: 讀取控制文件信息的起始數據塊號。
Blocks: 需要讀取的控制文件數據塊數目。
5. Db file parallel read
這是一個很容易引起誤導的等待事件,實際上這個等待事件和並行操作(比如並行查詢,並行DML)沒有關系。 這個事件發生在數據庫恢復的時候,當有一些數據塊需要恢復的時候,Oracle會以並行的方式把他們從數據文件中讀入到內存中進行恢復操作。
這個等待事件包含三個參數:
Files: 操作需要讀取的文件個數。
Blocks: 操作需要讀取的數據塊個數。
Requests: 操作需要執行的I/O次數。
6. Db file parallel write
這是一個后台等待事件,它同樣和用戶的並行操作沒有關系,它是由后台進程DBWR產生的,當后台進程DBWR向磁盤上寫入臟數據時,會發生這個等待。
DBWR會批量地將臟數據並行地寫入到磁盤上相應的數據文件中,在這個批次作業完成之前,DBWR將出現這個等待事件。如果僅僅是這一個等待事件,對用戶的操作並沒有太大的影響,當伴隨着出現free buffer waits等待事件時,說明此時內存中可用的空間不足,這時候會影響到用戶的操作,比如影響到用戶將臟數據塊讀入到內存中。
當出現db file parallel write等待事件時,可以通過啟用操作系統的異步I/O的方式來緩解這個等待。當使用異步I/O時,DBWR不再需要一直等到所有數據塊全部寫入到磁盤上,它只需要等到這個數據寫入到一個百分比之后,就可以繼續進行后續的操作。
這個等待事件有兩個參數:
Requests: 操作需要執行的I/O次數。
Timeouts: 等待的超時時間。
7. Db file scattered read
這個等待事件在實際生產庫中經常可以看到,這是一個用戶操作引起的等待事件,當用戶發出每次I/O需要讀取多個數據塊這樣的SQL 操作時,會產生這個等待事件,最常見的兩種情況是全表掃描(FTS: Full Table Scan)和索引快速掃描(IFFS: index fast full scan)。
這個名稱中的scattered( 分散),可能會導致很多人認為它是以scattered 的方式來讀取數據塊的,其實恰恰相反,當發生這種等待事件時,SQL的操作都是順序地讀取數據塊的,比如FTS或者IFFS方式(如果忽略需要讀取的數據塊已經存在內存中的情況)。
這里的scattered指的是讀取的數據塊在內存中的存放方式,他們被讀取到內存中后,是以分散的方式存在在內存中,而不是連續的。
這個等待事件有三個參數:
File#: 要讀取的數據塊所在數據文件的文件號。
Block#: 要讀取的起始數據塊號。
Blocks: 需要讀取的數據塊數目。
8. Db file sequential read
這個等待事件在實際生產庫也很常見,當Oracle 需要每次I/O只讀取單個數據塊這樣的操作時,會產生這個等待事件。最常見的情況有索引的訪問(除IFFS外的方式),回滾操作,以ROWID的方式訪問表中的數據,重建控制文件,對文件頭做DUMP等。
這里的sequential也並非指的是Oracle 按順序的方式來訪問數據,和db file scattered read一樣,它指的是讀取的數據塊在內存中是以連續的方式存放的。
這個等待事件有三個參數:
File#: 要讀取的數據塊鎖在數據文件的文件號。
Block#: 要讀取的起始數據塊號。
Blocks: 要讀取的數據塊數目(這里應該等於1)。
9. Db file single write
這個等待事件通常只發生在一種情況下,就是Oracle 更新數據文件頭信息時(比如發生Checkpoint)。
當這個等待事件很明顯時,需要考慮是不是數據庫中的數據文件數量太大,導致Oracle 需要花較長的時間來做所有文件頭的更新操作(checkpoint)。
這個等待事件有三個參數:
File#: 需要更新的數據塊所在的數據文件的文件號。
Block#: 需要更新的數據塊號。
Blocks: 需要更新的數據塊數目(通常來說應該等於1)。
10. Direct path read
這個等待事件發生在會話將數據塊直接讀取到PGA當中而不是SGA中的情況,這些被讀取的數據通常是這個會話私有的數據,所以不需要放到SGA作為共享數據,因為這樣做沒有意義。這些數據通常是來自於臨時段上的數據,比如一個會話中SQL的排序數據,並行執行過程中間產生的數據,以及Hash Join,merge join產生的排序數據,因為這些數據只對當前的會話的SQL操作有意義,所以不需要放到SGA當中。
當發生direct path read等待事件時,意味着磁盤上有大量的臨時數據產生,比如排序,並行執行等操作。或者意味着PGA中空閑空間不足。
這個等待事件有三個參數:
Descriptor address: 一個指針,指向當前會話正在等待的一個direct read I/O。
First dba: descriptor address 中最舊的一個I/O數據塊地址。
Block cnt: descriptor address上下文中涉及的有效的buffer 數量。
11. Direct path write
這個等待事件和direct path read 正好相反,是會話將一些數據從PGA中直接寫入到磁盤文件上,而不經過SGA。
這種情況通常發生在:
使用臨時表空間排序(內存不足)
數據的直接加載(使用append方式加載數據)
並行DML操作。
這個等待事件有三個參數:
Descriptor address: 一個指針,指向當前會話正在等待的一個direct I/O.
First dba: descriptor address 中最舊的一個I/O數據塊地址。
Block cnt: descriptor address 上下文中涉及的有效地 buffer 數量。
12. Enqueue
Enqueue 這個詞其實是lock 的另一種描述語。
當我們在AWR 報告中發現長時間的enqueue 等待事件時,說明數據庫中出現了阻塞和等待,可以關聯AWR報告中的enqueue activity部分來確定是哪一種鎖定出現了長時間等待。
這個等待事件有2個參數:
Name: enqueue 的名稱和類型。
Mode: enqueue的模式。
可以使用如下SQL 查看當前會話等待的enqueue名稱和類型:
/* Formatted on 6/27/2011 1:31:48 PM (QP5 v5.114.809.3010) */
SELECT CHR (TO_CHAR (BITAND (p1, -16777216)) / 16777215)
|| CHR (TO_CHAR (BITAND (p1, 16711680)) / 65535)
"Lock",
TO_CHAR (BITAND (p1, 65535)) "Mode"
FROM v$session_wait
WHERE event = 'enqueue';
13. Free buffer waits
當一個會話將數據塊從磁盤讀到內存中時,它需要到內存中找到空閑的內存空間來存放這些數據塊,當內存中沒有空閑的空間時,就會產生這個等待;除此之外,還有一種情況就是會話在做一致性讀時,需要構造數據塊在某個時刻的前映像(image),此時需要申請內存來存放這些新構造的數據塊,如果內存中無法找到這樣的內存塊,也會發生這個等待事件。
當數據庫中出現比較嚴重的free buffer waits等待事件時,可能的原因是:
(1)data buffer 太小,導致空閑空間不夠
(2)內存中的臟數據太多,DBWR無法及時將這些臟數據寫到磁盤中以釋放空間
這個等待事件包含2個參數:
File#: 需要讀取的數據塊所在的數據文件的文件號。
Block#: 需要讀取的數據塊塊號。
14. Latch free
在10g之前的版本里,latch free 等待事件代表了所有的latch等待,在10g以后,一些常用的latch事件已經被獨立了出來:
11gr2:
SQL> select name from v$event_name where name like 'latch%' order by 1;
NAME
----------------------------------------------------------------
latch activity
latch free
latch: Change Notification Hash table latch
latch: In memory undo latch
latch: MQL Tracking Latch
latch: PX hash array latch
latch: Undo Hint Latch
latch: WCR: processes HT
latch: WCR: sync
latch: cache buffer handles
latch: cache buffers chains
latch: cache buffers lru chain
latch: call allocation
latch: change notification client cache latch
latch: checkpoint queue latch
latch: enqueue hash chains
latch: gc element
latch: gcs resource hash
latch: ges resource hash list
latch: lob segment dispenser latch
latch: lob segment hash table latch
latch: lob segment query latch
latch: messages
latch: object queue header operation
latch: parallel query alloc buffer
latch: redo allocation
latch: redo copy
latch: redo writing
latch: row cache objects
latch: session allocation
latch: shared pool
latch: undo global data
latch: virtual circuit queues
已選擇33行。
10gr2 rac:
sys@ORCL> select name from v$event_name where name like 'latch%' order by 1;
NAME
--------------------------------------------------
latch activity
latch free
latch: Change Notification Hash table latch
latch: In memory undo latch
latch: KCL gc element parent latch
latch: MQL Tracking Latch
latch: Undo Hint Latch
latch: cache buffer handles
latch: cache buffers chains
latch: cache buffers lru chain
latch: checkpoint queue latch
latch: enqueue hash chains
latch: gcs resource hash
latch: ges resource hash list
latch: library cache
latch: library cache lock
latch: library cache pin
latch: messages
latch: object queue header heap
latch: object queue header operation
latch: parallel query alloc buffer
latch: redo allocation
latch: redo copy
latch: redo writing
latch: row cache objects
latch: session allocation
latch: shared pool
latch: undo global data
latch: virtual circuit queues
29 rows selected.
所以latch free 等待事件在10g以后的版本中並不常見,而是以具體的Latch 等待事件出現。
這個等待事件有三個參數:
Address: 會話等待的latch 地址。
Number: latch號,通過這個號,可以從v$latchname 視圖中找到這個latch 的相關的信息。
SQL> select * from v$latchname where latch#=number;
Tries: 會話嘗試獲取Latch 的次數。
15. Library cache lock
這個等待事件發生在不同用戶在共享中由於並發操作同一個數據庫對象導致的資源爭用的時候,比如當一個用戶正在對一個表做DDL 操作時,其他的用戶如果要訪問這張表,就會發生library cache lock等待事件,它要一直等到DDL操作完成后,才能繼續操作。
這個事件包含四個參數:
Handle address: 被加載的對象的地址。
Lock address: 鎖的地址。
Mode: 被加載對象的數據片段。
Namespace: 被加載對象在v$db_object_cache 視圖中namespace名稱。
10gr2 rac:
sys@ORCL> select name from v$event_name where name like 'library%' order by 1;
NAME
--------------------------------------------------
library cache load lock
library cache lock
library cache pin
library cache revalidation
library cache shutdown
16. Library cache pin
這個等待事件和library cache lock 一樣是發生在共享池中並發操作引起的事件。通常來講,如果Oracle 要對一些PL/SQL 或者視圖這樣的對象做重新編譯,需要將這些對象pin到共享池中。如果此時這個對象被其他的用戶特有,就會產生一個library cache pin的等待。
這個等待事件也包含四個參數:
Handle address: 被加載的對象的地址。
Lock address: 鎖的地址。
Mode: 被加載對象的數據片段。
Namespace: 被加載對象在v$db_object_cache 視圖中namespace名稱。
17. Log file parallel write
后台進程LGWR 負責將log buffer當中的數據寫到REDO 文件中,以重用log buffer的數據。如果每個REDO LOG組里面有2個以上的成員,那么LGWR進程會並行地將REDO 信息寫入這些文件中。
如果數據庫中出現這個等待事件的瓶頸,主要的原因可能是磁盤I/O性能不夠或者REDO 文件的分布導致了I/O爭用,比如同一個組的REDO 成員文件放在相同的磁盤上。
這個等待事件有三個參數:
Files: 操作需要寫入的文件個數。
Blocks: 操作需要寫入的數據塊個數。
Requests:操作需要執行的I/O次數。
18. Log buffer space
當log buffer 中沒有可用空間來存放新產生的redo log數據時,就會發生log buffer space等待事件。如果數據庫中新產生的redo log的數量大於LGWR 寫入到磁盤中的redo log 數量,必須等待LGWR 完成寫入磁盤的操作,LGWR必須確保redo log寫到磁盤成功之后,才能在redo buffer當中重用這部分信息。
如果數據庫中出現大量的log buffer space等待事件,可以考慮如下方法:
(1)增加redo buffer的大小。
(2)提升磁盤的I/O性能
19. Log file sequential read
這個等待事件通常發生在對redo log信息進行讀取時,比如在線redo 的歸檔操作,ARCH進程需要讀取redo log的信息,由於redo log的信息是順序寫入的,所以在讀取時也是按照順序的方式來讀取的。
這個等待事件包含三個參數:
Log#: 發生等待時讀取的redo log的sequence號。
Block#: 讀取的數據塊號。
Blocks: 讀取的數據塊個數。
20. Log file single write
這個等待事件發生在更新redo log文件的文件頭時,當為日志組增加新的日志成員時或者redo log的sequence號改變時,LGWR 都會更新redo log文件頭信息。
這個等待事件包含三個參數:
Log#: 寫入的redo log組的編號。
Block#:寫入的數據塊號。
Blocks:寫入的數據塊個數。
21. Log file switch(archiving needed)
在歸檔模式下,這個等待事件發生在在線日志切換(log file switch)時,需要切換的在線日志還沒有被歸檔進程(ARCH)歸檔完畢的時候。 當在線日志文件切換到下一個日志時,需要確保下一個日志文件已經被歸檔進程歸檔完畢,否則不允許覆蓋那個在線日志信息(否則會導致歸檔日志信息不完整)。
出現這樣的等待事件通常是由於某種原因導致ARCH 進程死掉,比如ARCH進程嘗試向目的地寫入一個歸檔文件,但是沒有成功(介質失效或者其他原因),這時ARCH進程就會死掉。 如果發生這種情況,在數據庫的alert log文件中可以找到相關的錯誤信息。
這個等待事件沒有參數。
22. Log file switch(checkpoint incomplete)
當一個在線日志切換到下一個在線日志時,必須保證要切換到的在線日志上的記錄的信息(比如一些臟數據塊產生的redo log)被寫到磁盤上(checkpoint),這樣做的原因是,如果一個在線日志文件的信息被覆蓋,而依賴這些redo 信息做恢復的數據塊尚未被寫到磁盤上(checkpoint),此時系統down掉的話,Oracle將沒有辦法進行實例恢復。
在v$log 視圖里記錄了在線日志的狀態。通常來說,在線日志有三種狀態。
Active: 這個日志上面保護的信息還沒有完成checkpoint。
Inactive: 這個日志上面保護的信息已完成checkpoint。
Current: 當前的日志。
Oracle 在做實例恢復時,會使用狀態為current和Active的日志進行實例恢復。
如果系統中出現大量的log file switch(checkpoint incomplete)等待事件,原因可能是日志文件太小或者日志組太少,所以解決的方法是,增加日志文件的大小或者增加日志組的數量。
這個等待事件沒有參數。
23. Log file sync
這是一個用戶會話行為導致的等待事件,當一個會話發出一個commit命令時,LGWR進程會將這個事務產生的redo log從log buffer里面寫到磁盤上,以確保用戶提交的信息被安全地記錄到數據庫中。
會話發出的commit指令后,需要等待LGWR將這個事務產生的redo 成功寫入到磁盤之后,才可以繼續進行后續的操作,這個等待事件就叫作log file sync。
當系統中出現大量的log file sync等待事件時,應該檢查數據庫中是否有用戶在做頻繁的提交操作。
這種等待事件通常發生在OLTP系統上。OLTP 系統中存在很多小的事務,如果這些事務頻繁被提交,可能引起大量的log file sync的等待事件。
這個等待事件包含一個參數:
Buffer#: redo buffer 中需要被寫入到磁盤中的buffer。
24. SQL*Net break/reset to client
當出現這個等待事件時,說明服務器端在給客戶端發送一個斷開連接或者重置連接的請求,正在等待客戶的響應,通常的原因是服務器到客戶端的網絡不穩定導致的。
這個等待事件包含兩個參數:
Driver id: 服務器和客戶端連接使用的協議信息。
Break?:零表示服務端向客戶端發送一個重置(reset)信息,非零表示服務器端向客戶端發送一個斷開(break)消息。
25. SQL*Net break/reset to dblink
這個等待事件和SQL*Net break/reset to client 相同。不過它表示的是數據庫通過dblink訪問另一台數據庫時,他們之間建立起一個會話,這個等待事件發生在這個會話之間的通信過程中,同樣如果出現這個等待事件,需要檢查兩台數據庫之間的通信問題。
這個等待事件有兩個參數:
Driver id: 服務器和客戶端連接使用的協議信息。
Break?:零表示服務端向客戶端發送一個重置(reset)信息,非零表示服務器端向客戶端發送一個斷開(break)消息。
26. SQL*Net message from client
這個等待事件基本上是最常見的一個等待事件。當一個會話建立成功后,客戶端會向服務器端發送請求,服務器端處理完客戶端請求后,將結果返回給客戶端,並繼續等待客戶端的請求,這時候會產生SQL*Net message from client 等待事件。
很顯然,這是一個空閑等待,如果客戶端不再向服務器端發送請求,服務器端將一直處於這個等待事件狀態。
這個等待事件包含兩個參數:
Driver id: 服務器端和客戶端連接使用的協議信息。
#bytes: 服務器端接收到的來自客戶端消息的字節數。
27. SQL*Net message from dblink
這個等待事件和SQL*Net message from client相同,不過它表示的是數據庫通過dblink 訪問另一個數據庫時,他們之間會建立一個會話,這個等待事件發生在這個會話之間的通信過程中。
這個等待事件也是一個空閑等待事件。
這個事件包含兩個參數:
Driver id: 服務器端和客戶端連接使用的協議信息。
#bytes: 服務器端通過dblink 收到的來自另一個服務器端消息的字節數。
28. SQL*Net message to client
這個等待事件發生在服務器端向客戶端發送消息的時候。當服務器端向客戶端發送消息產生等待時,可能的原因是用戶端太繁忙,無法及時接收服務器端送來的消息,也可能是網絡問題導致消息無法從服務器端發送到客戶端。
這個等待事件有兩個參數:
Driver id: 服務器端和客戶端連接使用的協議信息。
#bytes: 服務器端向客戶端發送消息的字節數。
29. SQL*Net message to dblink
這個等待事件和SQL*Net message to client 相同,不過是發生在數據庫服務器和服務器之間的等待事件,產生這個等待的原因可能是遠程服務器繁忙,而無法及時接收發送過來的消息,也可能是服務器之間網絡問題導致消息無法發送過來。
這個等待時間包含兩個參數:
Driver id: 服務器端和客戶端連接使用的協議信息。
#bytes: 服務器端通過dblink發送給另一個服務器消息的字節數。
30. SQL*Net more data from client
服務器端等待用戶發出更多的數據以便完成操作,比如一個大的SQL文本,導致一個SQL*Net 數據包無法完成傳輸,這樣服務器端會等待客戶端把整個SQL 文本發過來在做處理,這時候就會產生一個SQL*Net more data from client 等待事件。
這個等待時間包含兩個參數:
Driver id: 服務器端和客戶端連接使用的協議信息。
#bytes: 服務器端從客戶端接收到消息的字節數。
31. SQL*Net more data from dblink
在一個分布式事務中,SQL 分布在不同的數據庫中執行,遠程數據庫執行完畢后將結果通過dblink返給發出SQL的數據庫,在等待數據從其他數據庫中通過dblink傳回的過程中,如果數據在遠程數據庫上處理時間很久,或者有大量的結果集需要返回,或者網絡性能問題都會產生SQL*Net more data from dblink 等待事件,它的意思是本地數據庫需要等到所有的數據從遠程處理完畢通過dblink傳回后,才可以在本機繼續執行操作。
這個等待時間包含兩個參數:
Driver id: 服務器端和客戶端連接使用的協議信息。
#bytes: 服務器端通過dblink發送給另一個服務器消息的字節數。
32. SQL*Net more data to client
當服務器端有太多的數據需要發給客戶端時,可能會產生SQL*Net more data to client等待事件,也可能由於網絡問題導致服務器無法及時地將信息或者處理結果發送給客戶端,同樣會產生這個等待。
這個等待時間包含兩個參數:
Driver id: 服務器端和客戶端連接使用的協議信息。
#bytes: 服務器端向客戶端發送消息的字節數。
33. SQL*Net more data to dblink
這個等待事件和SQL*Net more data to client 等待時間基本相同,只不過等待發生在分布式事務中,即本地數據庫需要將更多的數據通過dblink發送給遠程數據庫。由於發送的數據太多或者網絡性能問題,就會出現SQL*Net more data to dblink等待事件。
這個等待時間包含兩個參數:
Driver id: 服務器端和客戶端連接使用的協議信息。
#bytes: 服務器端通過dblink發送給另一個服務器消息的字節數。