數(shù)據(jù)庫的作用就是實現(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 實 例( Instance)
(圖 1.1)Oracle 實例
一個 Orac le 實例:
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ù)據(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ù)據(jù)庫的 Archive Log 模
式被激活,還存在歸檔日志文件。Oracle 的 I/O 產(chǎn)生,就是對這些文件的數(shù)據(jù)讀、寫操作。下面再詳細(xì)看
下幾種主要寫操作的產(chǎn)生及其過程。
2.1.1. 控制文件
控制文件中記錄了整個數(shù)據(jù)庫的物理結(jié)構(gòu)信息。同時控制文件還記錄系統(tǒng)和各個數(shù)據(jù)文件的 SCN(System
Change Number,關(guān)于 SCN 可以參見文章《Orac le SCN 機制詳解》)信息,以用于數(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)閉時的恢復(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)時。
2.每 3 秒鐘寫一次 Log Buffer。
3.當(dāng) Log Buffer 滿 1/3 時。
4.當(dāng) DBWn 進(jìn)程將“臟”數(shù)據(jù)寫入磁盤時。
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ā)生檢查點(Checkpoint)時。 檢查點的作用:
? 將數(shù)據(jù)緩存中所有改變的數(shù)據(jù)塊寫入數(shù)據(jù)文件(不管事物是否提交)
? 將數(shù)據(jù)文件的頭部標(biāo)為一致,并且在控制文件當(dāng)中記錄檢查點序號。
? 該檢查點號與日志文件中 SCN 號對應(yīng)。
? 檢查點操作的頻繁程度可由數(shù)據(jù)庫參數(shù)調(diào)節(jié)
2.1.4. 臨時表空間
當(dāng) Oracle 在執(zhí)行一些 SQL 時,會需要一些臨時空間來存儲執(zhí)行時產(chǎn)生的中間數(shù)據(jù)。這些臨時空間由 Orac le
從指定的臨時表空間中分配給進(jìn)程。主要有三種情況會占用臨時空間:臨時表/索引操作、排序和臨時 LO B
對象操作。
1.臨時表/索引:
在會話中,當(dāng)?shù)谝淮螌εR時表進(jìn)行 INSERT(包括 CTAS)時 ,Orac le 會從臨時表空間中為臨時表
及其索引分配臨時空間一存儲數(shù)據(jù)。
2.排序:
任何會使用到排序的操作,包括 JOIN、創(chuàng)建(重建)INDEX、ORDER BY、聚合計算(GROUP
BY)以及統(tǒng)計數(shù)據(jù)收集,都可能使用到臨時表空間。排序操作首先會選擇在內(nèi)存中的 Sort Area
進(jìn)行(Sort In Memory),一旦 Sort Area 不足,則會使用臨時空間進(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.臨時 LOB 對象:
LOB 對象包括 BLOB、CLO B、NCLOB、和 BFILE。在 PLSQL 程序塊中,如果定義了 LOB 變量,
則這些 LOB 變量就是臨時 LOB 對象。臨時 LOB 對象被創(chuàng)建在臨時表空間上,直到 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ù)開始時,oracle 會自動為其指定下一個可用的回滾段。事務(wù)中任何數(shù)據(jù)變化都被寫入回滾段
中。如果事務(wù)回滾,Oracle 根據(jù)回滾段中的回滾記錄將 buffer cache 中的“臟”數(shù)據(jù)恢復(fù),釋放回滾段空間。
當(dāng)事務(wù)被提交,由于要保證一致性讀,Oracle 并不會立即釋放回滾段中的數(shù)據(jù),而是會保留一段時間。
2.1.6. Archive Log
當(dāng) Oracle 的 Archive Log 模式被激活后,所有 Redo Log 數(shù)據(jù)都會被寫入 Archive Log 文件中以便日后進(jìn)行
恢復(fù)。當(dāng)發(fā)生日志組切換時,ARCn(Arc hive 進(jìn)程,可以存在多個)進(jìn)程就會將 Redo Log 文件拷貝到指
定存儲目錄中去,成為 Archive Log 文件。