瘋狂

          STANDING ON THE SHOULDERS OF GIANTS
          posts - 481, comments - 486, trackbacks - 0, articles - 1
            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

          Oracle 數據塊

          Posted on 2011-08-16 15:13 瘋狂 閱讀(2375) 評論(0)  編輯  收藏 所屬分類: database

          Oracle數據塊原理深入剖析-入門基礎時間:

          數據塊(Oracle Data Blocks),本文簡稱為“塊”,是Oracle最小的存儲單位,Oracle數據存放在“塊”中。一個塊占用一定的磁盤空間。特別注意的是,這里的“塊”是Oracle的“數據塊”,不是操作系統的“塊”。

            Oracle每次請求數據的時候,都是以塊為單位。也就是說,Oracle每次請求的數據是塊的整數倍。如果Oracle請求的數據量不到一塊,Oracle也會讀取整個塊。所以說,“塊”是Oracle讀寫數據的最小單位或者最基本的單位。

            塊的標準大小由初始化參數DB_BLOCK_SIZE指定。具有標準大小的塊稱為標準塊(Standard Block)。塊的大小和標準塊的大小不同的塊叫非標準塊(Nonstandard Block)。同一數據庫中,Oracle9i及以上版本支持同一數據庫中同時使用標準塊和非標準塊。Oracle允許指定5種非標準塊(Nonstandard Block)

            操作系統每次執行I/O的時候,是以操作系統的塊為單位;Oracle每次執行I/O的時候,都是以Oracle的塊為單位。

            Oracle數據塊大小一般是操作系統塊的整數倍。

            數據塊的格式(Data Block Format)

            塊中存放表的數據和索引的數據,無論存放哪種類型的數據,塊的格式都是相同的,塊由塊頭(header/Common and Variable),表目錄(Table Directory),行目錄(Row Directory),空余空間(Free Space)和行數據(Row Data)五部分組成,

            如下圖所示。

           

            塊頭(header/Common and Variable):存放塊的基本信息,如:塊的物理地址,塊所屬的段的類型(是數據段還是索引段) 表目錄(Table Directory):存放表的信息,即:如果一些表的數據被存放在這個塊中,那么,這些表的相關信息將被存放在“表目錄”中。

            行目錄(Row Directory):如果塊中有行數據存在,則,這些行的信息將被記錄在行目錄中。這些信息包括行的地址等。

            行數據(Row Data):是真正存放表數據和索引數據的地方。這部分空間是已被數據行占用的空間。

            空余空間(Free Space):空余空間是一個塊中未使用的區域,這片區域用于新行的插入和已經存在的行的更新。

            頭部信息區(Overhead):我們把塊頭(header/Common and Variable),表目錄(Table Directory),行目錄(Row Directory)這三部分合稱為頭部信息區(Overhead)。頭部信息區不存放數據,它存放的整個塊的信息。頭部信息區的大小是可變的。一般來說,頭部信息區的大小介于84字節(bytes)107字節(bytes)之間。

            數據塊中自由空間的使用

            當往數據庫中插入(INSERT)數據的時候,塊中的自由空間會減少;當對塊中已經存在的行進行修改(UPDATE)的時候(使記錄長度增加),塊中的自由空間也會減少。

            DELETE語句和UPDATE語句會使塊中的自由空間增加。當使用DELETE語句刪除塊中的記錄或者使用UPDATE語句把列的值更改成一個更小值的時候,Oracle會釋放出一部分自由空間。釋放出的自由空間并不一定是連續的。通常情況下,Oracle不會對塊中不連續的自由空間進行合并。因為合并數據塊中不連續的自由空間會影響數據庫的性能。只有當用戶進行數據插入(INSERT)或者更新(UPDATE)操作,卻找不到連續的自由空間的時候,Oracle才會合并數據塊中不連續的自由空間。

            對于塊中的自由空間,Oracle提供兩種管理方式:自動管理,手動管理

            行鏈接和行遷移(Row Chaining and Migrating)

            行鏈接(Row Chaining):如果我們往數據庫中插入(INSERT)一行數據,這行數據很大,以至于一個數據塊存不下一整行,Oracle就會把一行數據分作幾段存在幾個數據塊中,這個過程叫行鏈接(Row Chaining)。如下圖所示:

           

            如果一行數據是普通行,這行數據能夠存放在一個數據塊中;如果一行數據是鏈接行,這行數據存放在多個數據塊中。

            行遷移(Row Migrating):數據塊中存在一條記錄,用戶執行UPDATE更新這條記錄,這個UPDATE操作使這條記錄變長,這時候,Oracle在這個數據塊中進行查找,但是找不到能夠容納下這條記錄的空間,無奈之下,Oracle只能把整行數據移到一個新的數據塊。原來的數據塊中保留一個“指針”,這個“指針”指向新的數據塊。被移動的這條記錄的ROWID保持不變。行遷移的原理如下圖所示:

           

           

            無論是行鏈接還是行遷移,都會影響數據庫的性能。Oracle在讀取這樣的記錄的時候,Oracle會掃描多個數據塊,執行更多的I/O

            塊中自由空間的自動管理

            Oracle使用位圖(bitmap)來管理和跟蹤數據塊,這種塊的空間管理方式叫“自動管理”。自動管理有下面的好處:

            ◆易于使用

            ◆更好地利用空間

            ◆可以對空間進行實時調整

            塊中自由空間的手動管理

            用戶可以通過PCTFREE, PCTUSED來調整塊中空間的使用,這種管理方式叫手動管理。相對于自動管理,手動管理方式比較麻煩,不容易掌握,容易造成塊中空間的浪費。

            PCTFREE參數用于指定塊中必須保留的最小空閑空間百分例。之所以要預留這樣的空間,是因為UPDATE時,需要這些空間。如果UPDATE時,沒有空余空間,Oracle就會分配一個新的塊,這會產生行遷移(Row Migrating)

            PCTUSED也是用于設置一個百分比,當塊中已使用的空間的比例小于這個百分比的時候,這個塊才被標識為有效狀態。只有有效的塊才被允許插入數據。

           

          文章轉載自網管網:http://www.bitscn.com/pdb/oracle/200904/160356.html

           

          ORACLE塊的分析
          (一)
          一直以來對“塊”的概念總是含混不清,從字面意義理解,只知道這是ORACLE存放數據的最小單位,然而它的內部世界如何呢,本人打算從今天開始連載幾篇文檔,對它進行深度分析。
          通過很多文檔、資料,了解到了數據庫基本結構魚刺圖:
          基本上每個對象對應一個段( Segment),只有分區對應多個段,這里的對象包括tableindexpartition等等,段可以跨越多個數據文件。
          每個段又有多個區(extent)來組成,這些區不能跨越多個數據文件,同時在系統使用過程中自動擴展。
          最后是塊(block),所有的數據都是存放在塊中。為了適應操作系統,每個塊在創建數據庫的時候默認了一個大小,這個大小一般是8K,同時在9I及其以 后的版本中增加了不同大小的塊參數,這將在以后的實驗中體現。先說說這個8K大小的塊,一般來說,為了使得oracle運行讀寫數據文件的時候有一個合理 的吞吐量,這里的塊大小,都跟操作系統塊大小設為整數倍,例如ntfs格式化的磁盤文件,每個物理塊大小為4,這里oracle的塊大小為8,即是代表每 讀取一個oracle塊,其實物理上也就是讀取了兩個操作系統塊。 這里主要指的是數據文件存放在塊設備上,在實際的生產環境中,大部分情況都是將數據庫安裝在裸設備(RAW)也叫做原始分區之上。關于RAW將在以后進行 講解。
            
          通過上面這段文字,我們可以了解到ORACLE基本的存儲結構,下一篇將針對塊的大小與存放數據大小來做實驗。
          (二)
          上一節了解到了ORACLE的存儲結構,這節講一講塊的大小與數據存放之間的關系。
          大家都知道了在ORACLE環境中,所有的對象都是存放在塊中,這個塊大小與存放的記錄之間到底存在怎樣的關系呢?
          做一個實驗看看:
          創建一個表空間test
          create tablespace test datafile '/oracle/oradata/test.dbf' size 100m;
          創建一個用戶
          create user test identified by test default tablespace test;
          創建一個表
          create table test.t1 (a1 number,a2 varchar2(100));
          檢查段,可以發現在這個視圖中出現了名稱為T的段,段類型為TABLE,這個段里面分配了1個區,其中包含8個塊,大小為64K字節。
          select segment_name,blocks,extents,bytes,segment_type,tablespace_name from dba_segments where owner='TEST';
          SEGMENT_NAME     BLOCKS    EXTENTS      BYTES SEGMENT_TYPE       TABLESPACE_NAME
          ---------- ---------- ---------- ---------- ------------------ ----------
          T                   8          1      65536 TABLE              TEST
          檢查區,可以發現在這個視圖中出現了一個區,區號為0,包含8個塊,大小為64K字節。
          select segment_name,segment_type,extent_id,blocks,bytes from dba_extents where owner='TEST';
          SEGMENT_NAME SEGMENT_TYPE        EXTENT_ID     BLOCKS      BYTES
          ---------- ------------------ ---------- ---------- ----------
          T          TABLE                       0          8      65536        
          檢查塊,可以發現這里沒有載入到內存的塊,由此斷定,在數據未寫入的時候,內存中并沒有存放數據的塊。
          select file#,block#,class#,status,xnc,objd from v$bh where ts#=12;
          未選定行
          插入10行數據,進行測試。
          SQL> declare
            2  i number
            3  ;
            4  begin
            5  for i in 1..10 loop
            6  execute immediate 'insert into test.t values (:x,:y)' using i,i;
            7  end loop;
            8  end;
            9  /
          PL/SQL
          過程已成功完成。
          再次查看v$bh視圖,檢查內存中是否使用到了塊。
          select file#,block#,class#,status,xnc,objd from v$bh where ts#=12;
               FILE#     BLOCK#     CLASS# STATU        XNC       OBJD
          ---------- ---------- ---------- ----- ---------- ----------
                   1      28089          4 xcur           0      11038
                   1      28090          1 xcur           0      11038
          哈哈,果然出現了數據,說明在數據插入的表的時候在內存中已經載入了分配的塊,同時在這些塊中寫入了數據,這里占用了兩個塊,塊號分別為2808928090,其中我們可以根據CLASS#來判斷出他們屬于不同類型。
          (三)
          這一節緊接著上一節來說。
          上一節通過實驗,我們了解到,塊的創建和讀取流程,不過只是針對一個會話的,現在我們來看看在一個會話中插入數據之后,同時在另外一個會話查詢數據,這樣的情況會對塊有什么影響。
          打開一個新的會話, 然后執行如下命令:
          查詢表,由于插入數據的事務沒有提交,這里在另外的會話中就看不到任何數據,深深體現了ORACLE的多版本一致性
          select * from test_gao.t;
          未選定行
          查詢視圖v$bh,看是否有了變化
          select file#,block#,class#,status,xnc,objd from v$bh where ts#=12;
                FILE#     BLOCK#     CLASS# STATU        XNC       OBJD
          ---------- ---------- ---------- ----- ---------- ----------
                   1      28089          4 xcur           0      11038
                   1      28090          1 cr             0      11038
                   1      28090          1 cr             0      11038
                   1      28090          1 xcur           0      11038
          果然和上一節查詢出來的結果不同,多了紅色字體標識出來的兩行,大家可以看到這兩行的STATUS字段值為cr,什么是cr呢?它是Consistency Read(一致性讀取)的縮寫。從這里可以看出28090這個塊被兩個會話進行了操作。
          在第一個會話中回滾事務會發生什么呢?看下面的操作:
          會話1:執行rollback
          SQL> rollback;
          回退已完成。
          再次查詢v$bh視圖,看看什么情況
            select file#,block#,class#,status,xnc,objd from v$bh where objd=11038;
               FILE#     BLOCK#     CLASS# STATU        XNC       OBJD
          ---------- ---------- ---------- ----- ---------- ----------
                   1      28089          4 xcur           0      11038
                   1      28090          1 cr             0      11038
                   1      28090          1 cr             0      11038
                   1      28090          1 xcur           0      11038
          結果還是一樣,說明在事務回滾之后,塊還是處于一致讀取的狀態。
          (四)
          我們繼續上一節的話題。
          關閉數據庫實例
          SQL> shutdown immediate
          數據庫已經關閉。
          已經卸載數據庫。
          重新打開數據庫
          SQL>startup
          ORACLE
          例程已經啟動。

          Total System Global Area  253214492 bytes
          Fixed Size                   454428 bytes
          Variable Size             117440512 bytes
          Database Buffers          134217728 bytes
          Redo Buffers                1101824 bytes
          數據庫裝載完畢。
          數據庫已經打開。
          檢查v$bh視圖
          select file#,block#,class#,status,xnc,objd from v$bh where objd=11038;
          未選定行
          說明在沒有進行塊中數據的相關操作的時候,并沒有從物理文件中提取塊到內存。
          執行查詢或者插入、更新的SQL語句
          SQL> insert into test.t values (200,200);
          已創建 1 行。
          再次檢查v$bh視圖
          SQL> select file#,block#,class#,status,xnc,objd from v$bh where objd=11038;
               FILE#     BLOCK#     CLASS# STATU        XNC       OBJD
          ---------- ---------- ---------- ----- ---------- ----------
                   1      28089          4 xcur           0      11038
                   1      28090          1 xcur           0      11038
          總結:在沒有進行物理I/O的時候,v$bh視圖中不會出現相關的塊信息,同時證明此視圖中存放的乃是數據文件塊放到內存中的“塊”信息。

          實例講解Oracle 9i數據壞塊的處理

          筆者在一臺生產用測試庫上SELECT一個表時出現ORA-01578,一個塊損壞,以前學習過塊損壞怎么處理,到還真沒遇到過,今天總算讓我遇到了,還是一臺生產用測試庫,就不用很緊張了。

          數據庫版本是9.2.0.4Oracle9iRMAN有一個blockrecover命令,可以在線修復壞塊,以下就是使用RMAN修復壞塊的過程。

          SQL> conn owi/owi
          Connected.
          SQL> select * from dpa_history;
          select * from dpa_history
          *
          ERROR at line 1:
          ORA-01578: ORACLE data block corrupted (file # 15, block # 18)
          ORA-01110: data file 15: '/d01/app/oracle/oradata/dpa/dpa01.dbf'

          ORA-01578數據塊損壞,以下使用RMAN命令查詢是否可以使用blockrecover命令恢復以及怎樣恢復

          使用rman登錄catalog數據庫

          [ora9@rmanserver ~]$ rman target sys/oracle@dpa catalog rman/rman

           

          Recovery Manager: Release 9.2.0.8.0 - Production

           

          Copyright (c) 1995, 2002, Oracle Corporation. All rights reserved.

           

          connected to target database: DPA (DBID=843495022)
          connected to recovery catalog database

           

          查找最近datafile 15的全備份,今天下午剛做了一次RMAN的全備份

          RMAN> list backup of datafile 15;

           


          List of Backup Sets
          ===================

           

          BS Key Type LV Size       Device Type Elapsed Time Completion Time
          ------- ---- -- ---------- ----------- ------------ ---------------
          643    Full    64K        DISK        00:00:27     16-MAR-09     
          BP Key: 650   Status: AVAILABLE   Tag: TAG20090316T154352
          Piece Name: /d02/fullbackup/20090316_data_24_1
          List of Datafiles in backup set 643
          File LV Type Ckp SCN    Ckp Time Name
          ---- -- ---- ---------- --------- ----
          15      Full 11856250905 16-MAR-09 /d01/app/oracle/oradata/dpa/dpa01.dbf

           

          查找SCN 11856250905 以后的archivelog是否有備份

          RMAN> list backup of archivelog scn from 11856250905
          List of Backup Sets
          ===================
          BS Key Size       Device Type Elapsed Time Completion Time
          ------- ---------- ----------- ------------ ---------------
          680     265K       DISK        00:00:00     16-MAR-09     
          BP Key: 681   Status: AVAILABLE   Tag: TAG20090316T154731
          Piece Name: /d02/fullbackup/20090316_arch_28
          List of Archived Logs in backup set 680
          Thrd Seq     Low SCN    Low Time Next SCN   Next Time
          ---- ------- ---------- --------- ---------- ---------
          1    109     11856250805 16-MAR-09 11856251483 16-MAR-09
          1    110     11856251483 16-MAR-09 11856251487 16-MAR-09

          查找sequence 110 以后的archivelog是否有備份

          RMAN> list copy of archivelog from sequence 110;

           

          List of Archived Log Copies
          Key     Thrd Seq     S Low Time Name
          ------- ---- ------- - --------- ----
          694     1    111     A 16-MAR-09 /d02/arch/1_111.dbf
          695     1    112     A 16-MAR-09 /d02/arch/1_112.dbf

           

          查詢online archive log

           

          SQL> select sequence#,members,archived,status from v$log;

           

          SEQUENCE#    MEMBERS ARC STATUS
          ---------- ---------- --- ----------------
          113          1 NO CURRENT
          111          1 YES INACTIVE
          112          1 YES INACTIVE

          從以上查詢中可以看出datafile 15有一次最近的全備份,有全備份以來的所有archivelogonline redo log
          下面開始blockreocver,其實命令很簡單

          RMAN> blockrecover datafile 15 block 18;

           

          Starting blockrecover at 16-MAR-09
          allocated channel: ORA_DISK_1
          channel ORA_DISK_1: sid=16 devtype=DISK

           


          channel ORA_DISK_1: restoring block(s)
          channel ORA_DISK_1: specifying block(s) to restore from backup set
          restoring blocks of datafile 00015
          channel ORA_DISK_1: restored block(s) from backup piece 1
          piece handle=/d02/fullbackup/20090316_data_24_1 tag=TAG20090316T154352 params=NULL
          channel ORA_DISK_1: block restore complete

           

          starting media recovery

           

          archive log thread 1 sequence 111 is already on disk as file /d02/arch/1_111.dbf
          archive log thread 1 sequence 112 is already on disk as file /d02/arch/1_112.dbf
          channel ORA_DISK_1: starting archive log restore to default destination
          channel ORA_DISK_1: restoring archive log
          archive log thread=1 sequence=109
          channel ORA_DISK_1: restoring archive log
          archive log thread=1 sequence=110
          channel ORA_DISK_1: restored backup piece 1
          piece handle=/d02/fullbackup/20090316_arch_28 tag=TAG20090316T154731 params=NULL
          channel ORA_DISK_1: restore complete
          media recovery complete
          Finished blockrecover at 16-MAR-09

          SELECT一下表DPA_HISTORY

          SQL> select * from dpa_history;

           

          PRODLINEID BARCODE                        PA
          ---------- ------------------------------ --
          7          S*33040-D8311050149512B        03
          7          S*33040-D8311050143512B        03
          7          S*33040-D8311050140512B        03

           

           

          主站蜘蛛池模板: 丰宁| 平安县| 富裕县| 松江区| 大城县| 西峡县| 扎囊县| 台北市| 翼城县| 洪湖市| 通山县| 许昌市| 泊头市| 吴桥县| 垫江县| 邻水| 武宁县| 临夏市| 临湘市| 吴桥县| 松滋市| 同仁县| 常州市| 赤壁市| 舟曲县| 昆山市| 株洲市| 澄江县| 班戈县| 吉林市| 松溪县| 梓潼县| 加查县| 岚皋县| 安顺市| 吉首市| 佳木斯市| 南涧| 新龙县| 苍南县| 二手房|