數(shù)據(jù)庫的作用就是實(shí)現(xiàn)對數(shù)據(jù)的管理和查詢。任何一個數(shù)據(jù)庫系統(tǒng),必然存在對數(shù)據(jù)的大量讀或者寫或者兩種操作都大量存在。I/O 問題也往往是導(dǎo)致數(shù)據(jù)庫性能問題的重要原因。
Oracle結(jié)構(gòu)
(圖 1)Oracle 結(jié)構(gòu)
1.1. Orac le 實(shí) 例( Instance)
(圖 1.1)Oracle 實(shí)例
一個 Orac le 實(shí)例:
1.是訪問 Oracle database 的途徑
2.只能打開一個數(shù)據(jù)庫
3.由 SGA 內(nèi)存區(qū)和一組后臺進(jìn)程組成
1.2. 數(shù) 據(jù)庫 文件
(圖 1.2)數(shù)據(jù)庫文件
Orac le 數(shù)據(jù)庫的物理結(jié)構(gòu)是硬盤上的一組文件。主要有三類文件:即數(shù)據(jù)文件,日志文件和控制文件。
? 數(shù)據(jù)文件包含數(shù)據(jù)庫的實(shí)際數(shù)據(jù),數(shù)據(jù)存于用戶定義的表中,此外數(shù)據(jù)字典數(shù)據(jù)、回滾數(shù)據(jù)、索引等
均存于數(shù)據(jù)文件中。
? 日志文件記錄對數(shù)據(jù)庫的所有修改,用于數(shù)據(jù)庫的恢復(fù)。
? 控制文件記錄日志文件和數(shù)據(jù)文件的信息,用于保證數(shù)據(jù)庫文件的一致性和完整性。
歸檔日志文件是在線日志的拷貝,在歸檔模式下在線日志在重復(fù)使用之前必須歸檔。
Oracle中IO的產(chǎn)生
I/O 包括了讀、寫兩部分,先介紹 Oracle 中寫操作的產(chǎn)生。
2.1. 寫
介紹寫操作之前,先簡單的看下 Oracle 的物理結(jié)構(gòu):Oracle 的物理文件包括以下三種文件:控制文件(Control
Files)、重做日志文件(Redo Log Files)、數(shù)據(jù)文件(datafiles)。而數(shù)據(jù)文件中,根據(jù)功能的不同,還可以
分為:系統(tǒng)數(shù)據(jù)文件、用戶數(shù)據(jù)文件、臨時(shí)空間文件和回滾段文件。另外,如果數(shù)據(jù)庫的 Archive Log 模
式被激活,還存在歸檔日志文件。Oracle 的 I/O 產(chǎn)生,就是對這些文件的數(shù)據(jù)讀、寫操作。下面再詳細(xì)看
下幾種主要寫操作的產(chǎn)生及其過程。
2.1.1. 控制文件
控制文件中記錄了整個數(shù)據(jù)庫的物理結(jié)構(gòu)信息。同時(shí)控制文件還記錄系統(tǒng)和各個數(shù)據(jù)文件的 SCN(System
Change Number,關(guān)于 SCN 可以參見文章《Orac le SCN 機(jī)制詳解》)信息,以用于數(shù)據(jù)恢復(fù),因此數(shù)據(jù)文
件上的 SCN 變化后,Oracle 也會相應(yīng)修改控制文件上的 SCN 信息。
2.1.2. Redo Log
在非直接寫(Direct Write)的情況下,事務(wù)中的寫操作都會產(chǎn)生 Redo Log,作為數(shù)據(jù)塊異常關(guān)閉時(shí)的恢復(fù)
記錄。同樣,和寫用戶數(shù)據(jù)類似,Redo Log 也不會被直接寫入 Redo Log 文件,而是先寫入 Log Buffer 中。
Log Buffer 是一個可以循環(huán)重用的緩存區(qū)。LGWR 進(jìn)程負(fù)責(zé)將 Log Buffer 中的記錄寫入 Redo Log File 中去。
一旦 Log Buffer 中的條目被寫入了 Redo Log 文件中,就可以被重用了。
為了保證事務(wù)盡快獲得 Log Buffer,LGWR 進(jìn)程一般會盡快將 Log Buffer 中的數(shù)據(jù)寫入 Redo Log 文件中去。
在以下幾種情況下,LGWR 會將一個連續(xù)的 Log Buffer 寫入 Redo Log 文件中去:
1.當(dāng)一個事務(wù)提交(COMMIT)時(shí)。
2.每 3 秒鐘寫一次 Log Buffer。
3.當(dāng) Log Buffer 滿 1/3 時(shí)。
4.當(dāng) DBWn 進(jìn)程將“臟”數(shù)據(jù)寫入磁盤時(shí)。
2.1.3. 用戶數(shù)據(jù)文 件
由于內(nèi)存的讀寫效率比磁盤的讀寫效率高萬倍,因此,為了降低 I/O wait,Orac le 會將數(shù)據(jù) cache 在內(nèi)存
(Buffer Cache,對 Buffer Cache 的詳細(xì)介紹可以參見《Oracle 內(nèi)存全面分析》)中,對數(shù)據(jù)的讀寫盡量在
內(nèi)存中完成。當(dāng) Buffer Cache 中的數(shù)據(jù)緩存塊被修改過了,它就被標(biāo)記為“臟”數(shù)據(jù)。根據(jù) LRU Least Recently
Used)算法,如果一個數(shù)據(jù)塊最近很少被使用,它就稱為“冷”數(shù)據(jù)塊。進(jìn)程 DBWn(系統(tǒng)中可以存在多個
DBW 進(jìn)程,n 為序號)負(fù)責(zé)將“冷”的 “臟”數(shù)據(jù)寫入數(shù)據(jù)文件中去。DBWn 進(jìn)程會在以下兩種情況下將“臟”
數(shù)據(jù)寫入磁盤中去:
1. 當(dāng)服務(wù)進(jìn)程掃描一定數(shù)量(閥值)的 Buffer Cache 后還沒有找到干凈、可重用的緩存塊后,它會通知
DBWn 進(jìn)程將“臟”數(shù)據(jù)寫入文件中去,以釋放出空閑緩存。
2. 當(dāng)發(fā)生檢查點(diǎn)(Checkpoint)時(shí)。 檢查點(diǎn)的作用:
? 將數(shù)據(jù)緩存中所有改變的數(shù)據(jù)塊寫入數(shù)據(jù)文件(不管事物是否提交)
? 將數(shù)據(jù)文件的頭部標(biāo)為一致,并且在控制文件當(dāng)中記錄檢查點(diǎn)序號。
? 該檢查點(diǎn)號與日志文件中 SCN 號對應(yīng)。
? 檢查點(diǎn)操作的頻繁程度可由數(shù)據(jù)庫參數(shù)調(diào)節(jié)
2.1.4. 臨時(shí)表空間
當(dāng) Oracle 在執(zhí)行一些 SQL 時(shí),會需要一些臨時(shí)空間來存儲執(zhí)行時(shí)產(chǎn)生的中間數(shù)據(jù)。這些臨時(shí)空間由 Orac le
從指定的臨時(shí)表空間中分配給進(jìn)程。主要有三種情況會占用臨時(shí)空間:臨時(shí)表/索引操作、排序和臨時(shí) LO B
對象操作。
1.臨時(shí)表/索引:
在會話中,當(dāng)?shù)谝淮螌εR時(shí)表進(jìn)行 INSERT(包括 CTAS)時(shí) ,Orac le 會從臨時(shí)表空間中為臨時(shí)表
及其索引分配臨時(shí)空間一存儲數(shù)據(jù)。
2.排序:
任何會使用到排序的操作,包括 JOIN、創(chuàng)建(重建)INDEX、ORDER BY、聚合計(jì)算(GROUP
BY)以及統(tǒng)計(jì)數(shù)據(jù)收集,都可能使用到臨時(shí)表空間。排序操作首先會選擇在內(nèi)存中的 Sort Area
進(jìn)行(Sort In Memory),一旦 Sort Area 不足,則會使用臨時(shí)空間進(jìn)行排序操作(Sort In Disk)。
看下面的例子:
SQL> alter session set sort_area_size = 10000000;
Session altered.
SQL> select owner, object_name from t_test1 order by objec t_id;
47582 rows selected.
Exec ution Plan
Plan hash value : 1312425564
Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 47582 | 1486K| 155 (4)| 00:00:02 |
| 1 | SORT ORDER BY | | 47582 | 1486K| 155 (4)| 00:00:02 |
| 2 | TABLE ACCESS FULL| T_TEST1 | 47582 | 1486K| 150 (1)| 00:00:02 |
Statistics
1 recursive calls
0 db block gets
658 c onsistent gets
0 physic al reads
0 redo size
1566184 bytes sent via SQL*Net to c lient
35277 bytes received via SQL*Net from client
3174 SQL*Net roundtrips to/from c lient
1 sorts (memory)
0 sorts (disk)
47582 rows processed
SQL> alter session set sort_area_size = 10000;
Session altered.
SQL> select owner, object_name from t_test1 order by objec t_id;
47582 rows selected.
Exec ution Plan
Plan hash value : 1312425564
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time|
| 0 | SELECT STATEMENT | | 47582 | 1486K| | 1251 (1)| 00:00:16 |
| 1 | SORT ORDER BY | | 47582 | 1486K| 4136K| 1251 (1)| 00:00:16 |
| 2 | TABLE ACCESS FULL| T_TEST1 | 47582 | 1486K| | 150 (1)| 00:00:02 |
Statistics
6 recursive calls
20 db bloc k gets
658 c onsistent gets
629 physical reads
0 redo size
1566184 bytes sent via SQL*Net to c lient
35277 bytes received via SQL*Net from client
3174 SQL*Net roundtrips to/from c lient
0 sorts (memory)
1 sorts (disk)
47582 rows processed
3.臨時(shí) LOB 對象:
LOB 對象包括 BLOB、CLO B、NCLOB、和 BFILE。在 PLSQL 程序塊中,如果定義了 LOB 變量,
則這些 LOB 變量就是臨時(shí) LOB 對象。臨時(shí) LOB 對象被創(chuàng)建在臨時(shí)表空間上,直到 LOB 數(shù)據(jù)被
釋放,或者會話結(jié)束。
2.1.5. 回滾段
我們知道,一個事務(wù)在未被提交 前,其做的任何修改都 是可以被回滾(Rollbac k)的。這些回滾數(shù)據(jù)就被
放到回滾段(Rollback Segment)上。此外,一致性讀(Read Consistency)、數(shù)據(jù)庫恢復(fù)(Recover)都會用到回滾段。
任何數(shù)據(jù)塊的修改都會被記錄在回滾段中,甚至 Redo Log 也會產(chǎn)生回滾記錄。當(dāng)任何一個非只讀(只有
查詢)的事務(wù)開始時(shí),oracle 會自動為其指定下一個可用的回滾段。事務(wù)中任何數(shù)據(jù)變化都被寫入回滾段
中。如果事務(wù)回滾,Oracle 根據(jù)回滾段中的回滾記錄將 buffer cache 中的“臟”數(shù)據(jù)恢復(fù),釋放回滾段空間。
當(dāng)事務(wù)被提交,由于要保證一致性讀,Oracle 并不會立即釋放回滾段中的數(shù)據(jù),而是會保留一段時(shí)間。
2.1.6. Archive Log
當(dāng) Oracle 的 Archive Log 模式被激活后,所有 Redo Log 數(shù)據(jù)都會被寫入 Archive Log 文件中以便日后進(jìn)行
恢復(fù)。當(dāng)發(fā)生日志組切換時(shí),ARCn(Arc hive 進(jìn)程,可以存在多個)進(jìn)程就會將 Redo Log 文件拷貝到指
定存儲目錄中去,成為 Archive Log 文件。