95、oracle物理讀和邏輯讀
1.物理讀即是把數據從磁盤讀入到buffer catch的過程。
通常情況下是,如果需要數據的時候發現不存在於buffer catch當中,即oracle就會執行物理讀。
例子如下:
C:/Documents and Settings/Administrator>sqlplus jenny/jenny
SQL> set autotrace traceonly;
SQL> select * from t_test1;
----------------------------------------------------------
Plan hash value: 1883417357
...........
----------------------------------------------------------
0 recursive calls
0 db block gets
11 consistent gets
3 physical reads --發生了3次物理讀寫
0 redo size
10632 bytes sent via SQL*Net to client
451 bytes received via SQL*Net from client
8 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
97 rows processed
SQL> select * from t_test1;
----------------------------------------------------------
Plan hash value: 1883417357
........
----------------------------------------------------------
0 recursive calls
0 db block gets
11 consistent gets
0 physical reads --這裏沒有發生物理讀取,因爲這時數據已存在buffer catche中
0 redo size
10632 bytes sent via SQL*Net to client
451 bytes received via SQL*Net from client
8 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
97 rows processed
如果重新清掉緩存,再執行以上查詢語句,又會重新把數據從磁盤讀入數據,即會發生物理讀取
SQL> alter session set events 'immediate trace name flush_cache';
SQL> select * from t_test1;
----------------------------------------------------------
Plan hash value: 1883417355
........
----------------------------------------------------------
0 recursive calls
0 db block gets
11 consistent gets
3 physical reads --重新發生物理讀取
0 redo size
10632 bytes sent via SQL*Net to client
451 bytes received via SQL*Net from client
8 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
97 rows processed
2.邏輯讀取
邏輯讀指的就是從(或者視圖從)Buffer Cache中讀取數據塊。按照訪問數據塊的模式不同,可以分爲即時讀(Current Read)和一致性讀(Consistent Read)。
1)即時讀
即時讀即讀取數據塊當前的最新數據。任何時候在Buffer Cache中都只有一份當前數據塊。即時讀通常發生在對數據進行修改、刪除操作時。
這時,進程會給數據加上行級鎖,並且標識數據爲“髒”數據。
SQL> select * from t_test1 for update;
----------------------------------------------------------
Plan hash value: 3323170753
------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 97 | 8536 | 3 (0)| 00:00:01 |
| 1 | FOR UPDATE | | | | | |
| 2 | TABLE ACCESS FULL| T_TEST1 | 97 | 8536 | 3 (0)| 00:00:01 |
----------------------------------------------------------
1 recursive calls
99 db block gets --即時讀取
15 consistent gets
0 physical reads
19608 redo size
9123 bytes sent via SQL*Net to client
451 bytes received via SQL*Net from client
8 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
97 rows processed
2)一致性讀
Oracle是一個多用戶系統。當一個會話開始讀取數據還未結束讀取之前,可能會有其他會話修改它將要讀取的數據。如果會話讀取到修改後的數據,就會造成數據的不一致。
一致性讀就是爲了保證數據的一致性。在Buffer Cache中的數據塊上都會有最後一次修改數據塊時的SCN。
如果一個事務需要修改數據塊中數據,會先在回滾段中保存一份修改前數據和SCN的數據塊,然後再更新Buffer Cache中的數據塊的數據及其SCN,並標識其爲“髒”數據。
當其他進程讀取數據塊時,會先比較數據塊上的SCN和自己的SCN。如果數據塊上的SCN小於等於進程本身的SCN,則直接讀取數據塊上的數據;
如果數據塊上的SCN大於進程本身的SCN,則會從回滾段中找出修改前的數據塊讀取數據。通常,普通查詢都是一致性讀。
SQL> select * from t_test1
----------------------------------------------------------
Plan hash value: 1883417357
-----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 97 | 8536 | 3 (0)| 00:00:01 |
| 1 | TABLE ACCESS FULL| T_TEST1 | 97 | 8536 | 3 (0)| 00:00:01 |
-----------------------------------------------------------------------------
----------------------------------------------------------
1 recursive calls
0 db block gets
11 consistent gets --一致性讀取,這是沒有讀取回滾段情況下
0 physical reads
0 redo size
10632 bytes sent via SQL*Net to client
451 bytes received via SQL*Net from client
8 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
97 rows processed
打開另一個session執行同一個表的update或者delete並且是在沒有commit的情況下(只有這種情況纔會去讀回滾段),再執行sql
SQL> select * from t_test1;
----------------------------------------------------------
Plan hash value: 1883417357
-----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 97 | 8536 | 3 (0)| 00:00:01 |
| 1 | TABLE ACCESS FULL| T_TEST1 | 97 | 8536 | 3 (0)| 00:00:01 |
-----------------------------------------------------------------------------
----------------------------------------------------------
0 recursive calls
0 db block gets
12 consistent gets --需要讀回滾段的數據,所以會增加consistent gets
0 physical reads
0 redo size
10632 bytes sent via SQL*Net to client
451 bytes received via SQL*Net from client
8 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
97 rows processed
這上面只是簡單的邏輯讀和物理讀。如果能聯繫表的block分佈及HWM來看應該會明瞭一些。
通常情況下是,如果需要數據的時候發現不存在於buffer catch當中,即oracle就會執行物理讀。
例子如下:
C:/Documents and Settings/Administrator>sqlplus jenny/jenny
SQL> set autotrace traceonly;
SQL> select * from t_test1;
----------------------------------------------------------
Plan hash value: 1883417357
...........
----------------------------------------------------------
0 recursive calls
0 db block gets
11 consistent gets
3 physical reads --發生了3次物理讀寫
0 redo size
10632 bytes sent via SQL*Net to client
451 bytes received via SQL*Net from client
8 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
97 rows processed
SQL> select * from t_test1;
----------------------------------------------------------
Plan hash value: 1883417357
........
----------------------------------------------------------
0 recursive calls
0 db block gets
11 consistent gets
0 physical reads --這裏沒有發生物理讀取,因爲這時數據已存在buffer catche中
0 redo size
10632 bytes sent via SQL*Net to client
451 bytes received via SQL*Net from client
8 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
97 rows processed
如果重新清掉緩存,再執行以上查詢語句,又會重新把數據從磁盤讀入數據,即會發生物理讀取
SQL> alter session set events 'immediate trace name flush_cache';
SQL> select * from t_test1;
----------------------------------------------------------
Plan hash value: 1883417355
........
----------------------------------------------------------
0 recursive calls
0 db block gets
11 consistent gets
3 physical reads --重新發生物理讀取
0 redo size
10632 bytes sent via SQL*Net to client
451 bytes received via SQL*Net from client
8 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
97 rows processed
2.邏輯讀取
邏輯讀指的就是從(或者視圖從)Buffer Cache中讀取數據塊。按照訪問數據塊的模式不同,可以分爲即時讀(Current Read)和一致性讀(Consistent Read)。
1)即時讀
即時讀即讀取數據塊當前的最新數據。任何時候在Buffer Cache中都只有一份當前數據塊。即時讀通常發生在對數據進行修改、刪除操作時。
這時,進程會給數據加上行級鎖,並且標識數據爲“髒”數據。
SQL> select * from t_test1 for update;
----------------------------------------------------------
Plan hash value: 3323170753
------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 97 | 8536 | 3 (0)| 00:00:01 |
| 1 | FOR UPDATE | | | | | |
| 2 | TABLE ACCESS FULL| T_TEST1 | 97 | 8536 | 3 (0)| 00:00:01 |
----------------------------------------------------------
1 recursive calls
99 db block gets --即時讀取
15 consistent gets
0 physical reads
19608 redo size
9123 bytes sent via SQL*Net to client
451 bytes received via SQL*Net from client
8 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
97 rows processed
2)一致性讀
Oracle是一個多用戶系統。當一個會話開始讀取數據還未結束讀取之前,可能會有其他會話修改它將要讀取的數據。如果會話讀取到修改後的數據,就會造成數據的不一致。
一致性讀就是爲了保證數據的一致性。在Buffer Cache中的數據塊上都會有最後一次修改數據塊時的SCN。
如果一個事務需要修改數據塊中數據,會先在回滾段中保存一份修改前數據和SCN的數據塊,然後再更新Buffer Cache中的數據塊的數據及其SCN,並標識其爲“髒”數據。
當其他進程讀取數據塊時,會先比較數據塊上的SCN和自己的SCN。如果數據塊上的SCN小於等於進程本身的SCN,則直接讀取數據塊上的數據;
如果數據塊上的SCN大於進程本身的SCN,則會從回滾段中找出修改前的數據塊讀取數據。通常,普通查詢都是一致性讀。
SQL> select * from t_test1
----------------------------------------------------------
Plan hash value: 1883417357
-----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 97 | 8536 | 3 (0)| 00:00:01 |
| 1 | TABLE ACCESS FULL| T_TEST1 | 97 | 8536 | 3 (0)| 00:00:01 |
-----------------------------------------------------------------------------
----------------------------------------------------------
1 recursive calls
0 db block gets
11 consistent gets --一致性讀取,這是沒有讀取回滾段情況下
0 physical reads
0 redo size
10632 bytes sent via SQL*Net to client
451 bytes received via SQL*Net from client
8 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
97 rows processed
打開另一個session執行同一個表的update或者delete並且是在沒有commit的情況下(只有這種情況纔會去讀回滾段),再執行sql
SQL> select * from t_test1;
----------------------------------------------------------
Plan hash value: 1883417357
-----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 97 | 8536 | 3 (0)| 00:00:01 |
| 1 | TABLE ACCESS FULL| T_TEST1 | 97 | 8536 | 3 (0)| 00:00:01 |
-----------------------------------------------------------------------------
----------------------------------------------------------
0 recursive calls
0 db block gets
12 consistent gets --需要讀回滾段的數據,所以會增加consistent gets
0 physical reads
0 redo size
10632 bytes sent via SQL*Net to client
451 bytes received via SQL*Net from client
8 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
97 rows processed
這上面只是簡單的邏輯讀和物理讀。如果能聯繫表的block分佈及HWM來看應該會明瞭一些。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.