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