1.實體讀(physical read)
當資料塊第一次讀取到,就會緩存到buffer cache 中,而第二次讀取和修改該資料塊時就在記憶體buffer cache 了 以下是例子:
1.1 第一次讀取:
C:"Documents and Settings"Paul Yi>sqlplus "/as sysdba"
SQL*Plus: Release 9.2.0.4.0 - Production on Thu Feb 28 09:32:04 2008
Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.
Connected to:
Oracle9i Enterprise Edition Release 9.2.0.4.0 - Production
With the Partitioning, OLAP and Oracle Data Mining options
JServer Release 9.2.0.4.0 - Production
SQL> set autotrace traceonly
SQL> select * from test;
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT ptimizer=CHOOSE (Cost=2 Card=4 Bytes=8)
1 0 TABLE ACCESS (FULL) OF 'TEST' (Cost=2 Card=4 Bytes=8)
Statistics
175 recursive calls
0 db block gets
24 consistent gets
9 physical reads --9個實體讀
0 redo size
373 bytes sent via SQL*Net to client
503 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
2 sorts (memory)
0 sorts (disk)
1 rows processed
1.2 第二次讀取
0 recursive calls
7 consistent gets
0 physical reads --沒有發生實體讀了,直接從buffer cache 中讀取了
0 sorts (memory)
1.3 資料塊被重新讀入buffer cache ,這種發生在
如果有新的資料需要被讀入Buffer Cache中,而Buffer Cache又沒有足夠的空閑空間,Oracle就根據LRU算法将LRU連結清單中LRU端的資料置換出去。當這些資料被再次通路到時,需要重新從磁盤讀入。
SQL> alter session set events 'immediate trace name flush_cache';--清空資料緩沖區
Session altered.
6 physical reads --又重新發生了實體讀
2.邏輯讀(buffer read)
邏輯讀指的就是從(或者視圖從)Buffer Cache中讀取資料塊。按照通路資料塊的模式不同,可以分為即時讀(Current Read)和一緻性讀(Consistent Read)。注意:邏輯IO隻有邏輯讀,沒有邏輯寫。
即時讀
即時讀即讀取資料塊目前的最新資料。任何時候在Buffer Cache中都隻有一份目前資料塊。即時讀通常發生在對資料進行修改、删除操作時。這時,程序會給資料加上行級鎖,并且辨別資料為“髒”資料。
SQL> select * from test for update;
1 0 FOR UPDATE
2 1 TABLE ACCESS (FULL) OF 'TEST' (Cost=2 Card=4 Bytes=8)
1 db block gets
14 consistent gets
0 physical reads
252 redo size
386 bytes sent via SQL*Net to client
SQL>
一緻性讀
Oracle是一個多使用者系統。當一個會話開始讀取資料還未結束讀取之前,可能會有其他會話修改它将要讀取的資料。如果會話讀取到修改後的資料,就會造成資料的不一緻。一緻性讀就是為了保證資料的一緻性。在Buffer Cache中的資料塊上都會有最後一次修改資料塊時的SCN。如果一個事務需要修改資料塊中資料,會先在復原段中儲存一份修改前資料和SCN的資料塊,然後再更新Buffer Cache中的資料塊的資料及其SCN,并辨別其為“髒”資料。當其他程序讀取資料塊時,會先比較資料塊上的SCN和自己的SCN。如果資料塊上的SCN小于等于程序本身的SCN,則直接讀取資料塊上的資料;如果資料塊上的SCN大于程序本身的SCN,則會從復原段中找出修改前的資料塊讀取資料。通常,普通查詢都是一緻性讀。
下面這個例子幫助大家了解一下一緻性讀:
會話1中:
ID
----------
1000
SQL> update test set id=2000;
1 row updated.
會話2中:
SQL> set autotrace on
SQL> select * from test;
----------
9 consistent gets 沒有事物做update時 是 7 consistent gets 說明多了2個 consistent gets 這2個是要從復原段中擷取的
52 redo size