天天看點

《循序漸進Oracle:資料庫管理、優化與備份恢複》一一1.4 使用模闆建立資料庫

本節書摘來自異步社群出版社《循序漸進oracle:資料庫管理、優化與備份恢複》一書中的第1章,第1.4節,作者:蓋國強,更多章節内容可以通路雲栖社群“異步社群”公衆号檢視。

循序漸進oracle:資料庫管理、優化與備份恢複

前面提到,除了定制資料庫之外,還可以使用模闆來建立資料庫,接下來就讓我們一起來了解一下使用模闆建立資料庫的過程。

在1.1節中,我們提到可以通過指令行啟動dbca工具,可能更多的朋友是通過“開始”菜單中oracle建立的快捷菜單來啟動dbca的,如圖1-25所示,右圖則是快捷方式的具體指向。

《循序漸進Oracle:資料庫管理、優化與備份恢複》一一1.4 使用模闆建立資料庫

注意到這個快捷項的目标執行的是以下指令:

此處的dbca.cl檔案和前面的dbca.bat批處理檔案執行的功能是一緻的:

那麼dbca為什麼指向這個目錄呢?這個目錄又是做什麼用的呢?

實際上這個目錄是oracle的預設模闆目錄,當使用模闆來建立資料庫時,就用到了這個目錄下的檔案。

下面來看一下使用模闆建立資料庫的過程。

使用模闆和前面的過程主要不同之處在于第二個步驟,在這裡選擇“定制資料庫”之外的選項,就都使用了模闆,并且包含了資料檔案(eygle模闆是我們之前儲存的),如圖1-26左圖所示;使用模闆建立資料庫通常速度都會很快,原因就在于資料檔案是從種子資料庫中恢複出來的,而不需要建立檔案及字典對象等資訊,右圖展示建立過程的第一個步驟就是“複制資料庫檔案”。

這裡通過腳本說明一下通過模闆建立資料庫和定制資料庫的不同。

首先eygle.sql腳本記錄如下内容:

《循序漸進Oracle:資料庫管理、優化與備份恢複》一一1.4 使用模闆建立資料庫

該腳本首先調用的是clonermanrestore.sql腳本,該腳本記錄如下内容:

這個腳本首先啟動執行個體到nomount模式,然後調用rmanrestoredatafiles.sql來恢複檔案。

rmanrestoredatafiles.sql腳本是通過系統包dbms_backup_restore來恢複備份集中的檔案,進而實作資料恢複,其主要内容如下:

[oracle@jumper conner] $ sqlplus "/ as sysdba"

connected to an idle instance.

sql> startup nomount;

oracle instance started.

sql> declare

 2  devtype varchar2(256);

 3  done boolean;

 4  begin

 5  devtype:=sys.dbms_backup_restore.deviceallocate (type=>'',ident=>'t1');

 6  sys.dbms_backup_restore.restoresetdatafile;

 7  sys.dbms_backup_restore.restoredatafileto(dfnumber=>01,

          toname=>'/opt/oracle/oradata/conner/system01.dbf');

 8  sys.dbms_backup_restore.restoredatafileto(dfnumber=>02,

          toname=>'/opt/oracle/oradata/conner/undotbs01.dbf');

 9  sys.dbms_backup_restore.restoredatafileto(dfnumber=>03,

          toname=>'/opt/oracle/oradata/conner/users01.dbf');

10  sys.dbms_backup_restore.restorebackuppiece(done=>done,

          handle=>'/opt/oracle/product/9.2.0/dbs/0ggmiabq_1_1', params=>null);

11  sys.dbms_backup_restore.devicedeallocate;

12 end;

13 /

pl/sql procedure successfully completed.

sql> alter database backup controlfile to trace;

database altered.

可以找到trace檔案,編輯、執行重建控制檔案的需要部分:

sql> set echo on

sql> @ctl.sql

sql> create controlfile reuse database "conner" resetlogs archivelog

 2 -- set standby to maximize performance

 3   maxlogfiles 5

 4   maxlogmembers 3

 5   maxdatafiles 100

 6   maxinstances 1

 7   maxloghistory 1361

 8 logfile

 9  group 1 '/opt/oracle/oradata/conner/redo01.log' size 10m,

10  group 2 '/opt/oracle/oradata/conner/redo02.log' size 10m,

11  group 3 '/opt/oracle/oradata/conner/redo03.log' size 10m

12 -- standby logfile

13 datafile

14  '/opt/oracle/oradata/conner/system01.dbf',

15  '/opt/oracle/oradata/conner/undotbs01.dbf',

16  '/opt/oracle/oradata/conner/users01.dbf'

17 character set zhs16gbk

18 ;

control file created.

sql> recover database using backup controlfile until cancel;

ora-00279: change 240560269 generated at 06/09/2005 17:33:48 needed for thread 1

ora-00289: suggestion : /oradata/conner/archive/1_7.dbf

ora-00280: change 240560269 for thread 1 is in sequence #7

specify log: {=suggested | filename | auto | cancel}

auto

ora-00279: change 240600632 generated at 06/10/2005 10:42:26 needed for thread 1

ora-00289: suggestion : /oradata/conner/archive/1_8.dbf

ora-00280: change 240600632 for thread 1 is in sequence #8

ora-00278: log file '/oradata/conner/archive/1_7.dbf' no longer needed for this recovery

ora-00279: change 240620884 generated at 06/10/2005 10:45:42 needed for thread 1

ora-00289: suggestion : /oradata/conner/archive/1_9.dbf

ora-00280: change 240620884 for thread 1 is in sequence #9

ora-00278: log file '/oradata/conner/archive/1_8.dbf' no longer needed for this recovery

ora-00283: recovery session canceled due to errors

ora-00600: internal error code, arguments: [3020], [4242465], [1], [9], [314], [272], [], []

ora-10567: redo is inconsistent with data block (file# 1, block# 48161)

ora-10564: tablespace system

ora-01110: data file 1: '/opt/oracle/oradata/conner/system01.dbf'

ora-10560: block type 'data segment header - unlimited'

ora-01112: media recovery not started

ora-00279: change 240620949 generated at 06/10/2005 10:45:44 needed for thread 1

ora-00280: change 240620949 for thread 1 is in sequence #9

cancel

media recovery cancelled.<code>`</code>

恢複到最後可用日志後,通過resetlogs方式打開資料庫:

至此恢複完成。這是一次正常恢複,dbms_backup_restore的功能遠不止于此,還可以通過該包恢複備份集中的控制檔案、歸檔日志等檔案。

繼續前面的讨論,rmanrestoredatafiles.sql腳本通過dbms_backup_restore包從種子檔案seed_database.dfb恢複出資料檔案,來看一下模闆目錄中存放的模闆和種子資料庫(自定義的模闆也存放在這個目錄中):

seed_database.dfb檔案就是包含種子檔案的一個備份集。

資料檔案具備了,接下來是通過這些檔案“克隆”一個資料庫,這個工作由clonedbcreation.sql腳本繼續執行,這個腳本更為複雜,下面分開介紹一下。

首先根據指定的資料庫名稱(測試資料庫指定的名稱為eygle)建立一個控制檔案:

然後通過dbms_backup_restore包清空dbid等資訊:

看到這裡再次使用到了dbms_backup_restore包,zerodbid是包中的一個過程,用于清空資料檔案頭的部分資訊,新的dbid在之後的控制檔案建立時可以被計算,對于資料庫克隆,這是必須的。

zerodbid有一個輸入參數,即檔案号:

當fno==0時,控制檔案中包含的所有資料檔案頭都将被清零,zerodbid主要用于清除資料檔案頭的3類資訊:database id資訊、checksum資訊和checksum符号位資訊。

繼續看這個腳本,清零完成之後,資料庫重新啟動,控制檔案被重新建立,此時新的dbid被計算并最終寫入所有資料檔案:

注意,在啟動資料庫時oracle使用了一個臨時的參數檔案initeygletemp.ora,在這個參數檔案的最後一行設定了一個内部參數:

_no_recovery_through_resetlogs這個參數的作用是什麼呢?可以從資料庫中找到一點說明:

這個參數用于限制恢複能否跨越resetlogs,對于資料庫的恢複來說,resetlogs通常意味着不完全恢複,在資料庫resetlogs打開之後,控制檔案中的很多資訊被改寫,在oracle 10g之前,如果資料庫resetlogs打開,那麼将不再能夠通過目前的控制檔案再次進行resetlogs點之前的恢複,而oracle 10g改變了這個曆史。

在oracle 10g中,即使通過resetlogs方式打開了資料庫,oracle仍然支援再次從resetlogs時間點之前進行恢複;在clone資料庫時,oracle設定這個參數為true,意思就是不允許再次進行跨越resetlogs時間點的恢複。關于這部分内容,我們将在後面章節進行更為詳細的介紹。

繼續解讀這個腳本,接下來oracle設定restricted session模式,resetlogs打開資料庫:

至此,種子資料庫已經按照使用者的意圖脫胎換骨得以重生。

在很多oracle文檔中,可能大家都注意過oracle用來進行測試的一個表空間,這個表空間中有一系列預置的使用者和資料,可以用于資料庫或bi的很多測試實驗。

這個表空間在使用模闆建庫時是可以選擇的,在如圖1-27所示的這個界面中,可以選擇建庫時包含這個範例表空間(預設是未選擇的)。

如果選擇了包含示例方案,則clonedbcreation.sql腳本将會有所改變,主要增加了如下語句:

《循序漸進Oracle:資料庫管理、優化與備份恢複》一一1.4 使用模闆建立資料庫

看到這裡,再次引用了模闆目錄中的檔案:

通過mkplug.sql腳本來加載這個範例表空間,來看一下這個腳本的主要内容。

同樣,最重要的是通過dbms_backup_restore包從example01.dfb檔案中恢複資料檔案:

這個恢複完成之後,接下來最重要的部分就是通過傳輸表空間技術将example表空間導入到目前的資料庫。

考慮一下這種情況,當進行跨資料庫遷移時,需要将一個使用者表空間中的資料遷移到另外一個資料庫,應該使用什麼樣的方法呢?

最正常的做法可能是通過exp工具将資料全部導出,然後在目标資料庫上imp導入,可是這種方法可能會比較緩慢。exp工具同時還提供另外一種技術——可傳輸表空間技術,可以用于加快這個過程。

在exp -help的幫助中,可以看到這樣一個參數:

通過這個選項,我們可以對一組自包含、隻讀的表空間隻導出中繼資料,然後在作業系統層将這些表空間的資料檔案拷貝至目标平台,并将中繼資料導入資料字典(這個過程稱為插入,plugging),即完成遷移。但是注意,傳輸表空間技術不能應用于system表空間或sys使用者擁有的對象。

對于可傳輸表空間有一個重要概念:自包含(self-contained)。

在表空間傳輸中,要求表空間集為自包含的,自包含表示用于傳輸的内部表空間集沒有引用指向外部表空間集。自包含分為兩種:一般自包含表空間集和完全(嚴格)自包含表空間集。

常見的以下情況是違反自包含原則的。

boll 索引在内部表空間集,而表在外部表空間集(相反地,如果表在内部表空間集,而索引在外部表空間集,則不違反自包含原則)。

boll 分區表一部分區在内部表空間集,一部分在外部表空間集(對于分區表,要麼全部包含在内部表空間集中,要麼全不包含)。

boll 如果在傳輸表空間時同時傳輸限制,則對于引用完整性限制,限制指向的表在外部表空間集,則違反自包含限制;如果不傳輸限制,則與限制指向無關。

boll 表在内部表空間集,而lob列在外部表空間集,則違反自包含限制。

通常可以通過系統包dbms_tts來檢查表空間是否自包含,驗證可以以兩種方式執行:非嚴格方式和嚴格方式。

以下是一個簡單的驗證過程,假定在eygle表空間存在一個表eygle,其上存在索引存儲在users表空間:

以sys使用者執行非嚴格自包含檢查(full_check=false):

執行嚴格自包含檢查(full_check=true):

反過來對于users表空間來說,非嚴格檢查也是無法通過的:

但是,可以對多個表空間同時傳輸,則一些自包含問題就可以得到解決:

表空間自包含确認之後,進行表空間傳輸就很友善了,一般包含如下幾個步驟。

(1)将表空間設定為隻讀。

(2)導出表空間。在作業系統提示符下執行:

此處的導出檔案隻包含中繼資料,是以導出檔案很小,導出速度也會很快。

(3)轉移。将導出的中繼資料檔案(此處是exp_users.dmp)和傳輸表空間的資料檔案(此處是users表空間的資料檔案user01.dbf)轉移至目标主機(轉移過程如果使用ftp方式,應該注意使用二進制方式)。

(4)傳輸。在目标資料庫将表空間插入到資料庫中,完成表空間傳輸。在作業系統指令提示符下執行以下語句:

了解了oracle的可傳輸表空間技術後,來看一下example表空間的插入,以下腳本仍然來自mkplug.sql腳本:

完成plugging之後,這個表空間就被包含在了建立的資料庫之中。

需要注意的是,在oracle 10g之前,資料檔案是不能夠跨平台傳輸使用的,從oracle 10g開始,oracle支援跨平台的表空間傳輸,這極大地增強了資料遷移的便利性。

1.位元組順序和平台

資料檔案是以不能跨平台,主要是由于不同平台的位元組順序不同,這是計算機領域由來已久的問題之一,在各種計算機體系結構中,由于對于字、位元組等的存儲機制有所不同,通信雙方交流的資訊單元(比特、位元組、字、雙字等)應該以什麼樣的順序進行傳送就成了一個問題,如果不達成一緻的規則,通信雙方将無法進行正确的編/譯碼進而導緻通信失敗。

目前在各種體系的計算機中通常采用的位元組存儲機制主要有兩種:big-endian和little-endian。

一些作業系統(包括windows)在低位記憶體位址中存放二進制資料的最低有效位元組,是以這種系統被稱為little endian;一些作業系統(包括solaris)将最高有效位元組存儲在低位記憶體位址中,是以這種系統被稱為big endian。

舉一個簡單點的例子,假如1122這樣一個資料要存入不同系統,對于little endian的系統,存儲的順序就是2211,小頭在前;而對于big endian的系統來說,存儲順序就是1122,大頭在前,顯然big endian更符合我們通常的語言習慣。

那麼跨平台的問題就出現了,當一個little endian的系統試圖從一個big endian的系統中讀取資料時,就需要通過轉換,否則不同的位元組順序将導緻資料不能被正确讀取。

說明:

據考證,endian這個詞來源于jonathan swift在1726年寫的諷刺小說《gulliver's travels》(《格利佛遊記》)。該小說在描述gulliver暢遊小人國時碰到了如下的一個場景。在小人國裡的小人因為非常小(身高6英寸)是以總是碰到一些意想不到的問題。有一次因為對水煮蛋該從大的一端(big-end)剝開還是小的一端(little-end)剝開的争論而引發了一場戰争,并形成了兩支截然對立的隊伍:支援從big-end剝開的人swift就稱作big-endians,而支援從little-end剝開的人就稱作little-endians(字尾ian表明的就是支援某種觀點的人)。endian這個詞由此而來。

清楚了這個問題,接下來就可以來看看oracle是如何處理這種情況的。

2.源平台和目标平台

首先在遷移之前,需要确認一下源平台和目标平台的平台資訊,這些資訊可以通過視圖v$transportable_platform和v$database視圖聯合查詢得到。

以下是源平台的資訊:

查詢目标資料庫平台資訊:

看到windows平台和solaris平台的位元組順序是不同的,windows平台是little-endian,而solaris平台是big-endian的。

可以通過資料庫查詢oracle 10g支援的平台轉換:

3.源平台的導出及轉換

接下來開始我們的測試,建立一個獨立的自包含表空間,并建立一個測試表:

将表空間設定為隻讀:

導出要傳輸的表空間:

使用rman的convert指令轉換檔案格式:

确認導出檔案已生成:

4.檔案傳輸

通過ftp獲得兩個檔案,注意應該使用二進制方式傳輸(bin模式):

注意:

此處也可以在imp時通過fromuser/touser參數将資料導入其他使用者下。

現在這個表空間已經被插入到新的資料庫中,并且資料全部傳輸過來:

導入後的表空間還處于read only狀态,确認後可以更改為讀寫模式:

表空間已更改。

同樣,傳輸表空間也可以通過資料泵來完成,以下是oracle 10gr1中插入表空間的簡單示例:

6.同位元組序檔案的跨平台

前面說過,當一個little endian的系統試圖從一個big endian的系統中讀取資料時,就需要通過轉換,否則不同的位元組順序将導緻資料不能被正确讀取。那麼另外一個問題出現了,如果位元組序相同的平台進行檔案互動,資料能否被正确讀取呢?

理論上的确是可以的,但是由于在不同的平台上作業系統會在資料檔案頭寫上系統資訊,這部分資訊無法跨越平台,是以仍然會導緻跨平台的檔案無法被資料庫正确識别(oracle10g中同位元組序平台資料檔案頭不再存在跨平台的遷移問題)。

接下來讓我們通過windows和linux平台來進行一個跨平台測試,相信通過這個測試可以對以上提出的問題作出一個很好的回答。

實驗環境一:windows xp + oracle10g 10.2.0.1。

實驗環境二:red hat enterprise linux as release 3 + oracle 9ir2 9.2.0.4。

看一下linux平台,檔案頭被作業系統保留了8192位元組:

windows平台上資料檔案頭同樣保留了8192位元組:

可以通過linux和windows平台來進行一個小測試實驗,這兩個平台都是little endian的系統:

首先在linux下oracle 9204中建立一個測試表空間:

建立測試使用者并建立一個測試表:

壓縮檔案以友善傳輸:

導出表空間:

傳輸檔案到windows平台:

在windows上建立新使用者:

其中“參數:[krhcvt_filhdr_v10_01]”提示檔案頭無法正确識别。

可以通過對這個檔案進行一個特殊操作,為檔案更換一個windows下資料檔案的檔案頭,則資料檔案就應該能夠被資料庫識别。以下是這個“小手術”操作的過程。

首先提取一個windows資料檔案頭:

然後去除linux下的資料檔案頭:

最後将這兩個檔案合二為一:

d:oradataeygledatafile&gt;copy /b header.dbf+eyglee.dbf eygleee.dbf

header.dbf

eyglee.dbf

已複制     1 個檔案。

現在擁有的新檔案eygleee.dbf就具有了一個windows平台的檔案頭以及linux下的“檔案身”。至此這個檔案就能夠被windows上的oracle識别了,可以執行導入操作:

經由正常路徑由 export:v09.02.00 建立的導出檔案

即将導入可傳輸的表空間中繼資料...

已經完成 zhs16gbk 字元集和 al16utf16 nchar 字元集中的導入

. 正在将 sys 的對象導入到 sys

. 正在将 eyglee 的對象導入到 eyglee

. . 正在導入表            "eyglee"

成功終止導入, 沒有出現警告。

此時資料已經能夠被正确識别:

最後将表空間更改為讀寫模式,可以進行正常的資料操作:

通過這個實驗,還可以得出另外一個結論,oracle 9i的資料檔案可以通過表空間傳輸遷移到oracle 10g中使用。

7.oracle10g同位元組序跨平台遷移

在oracle10g中,同位元組序跨平台的檔案頭資訊oracle會自動改寫,不再需要轉換。我們看以下測試:

導出中繼資料,準備表空間遷移:

然後我們可以直接将這兩個檔案傳輸到windows平台上,在資料庫中執行必要的準備步驟:

接下來執行導入:

boll 重做日志檔案和控制檔案不會傳輸,遷移之後需要重建控制檔案使用resetlogs方式打開資料庫;臨時檔案不會被傳輸。

boll bfiles、外部表和directories、密碼檔案等不會被傳輸。

我們通過linux平台到windows平台的遷移來看一下這一技術的實作。

(1)确認平台及版本。

首先要确定源平台和目标平台具有相同的位元組序:

然後需要确定源平台及目标平台的資料庫版本,通常需要這兩者具有相同的資料庫版本,本例的情況有所不同,linux平台的資料庫版本為10.2.0.1,windows平台的資料庫版本為10.2.0.3,資料庫版本不同将使情況稍微複雜一點,而且需要注意的是,通常高版本的資料庫不能向低版本遷移。

(2)确認遷移是否支援。

跨平台遷移需要資料庫處于read only模式打開,使用dbms_tdb.check_db進行檢查:

如果以上過程成功執行,并沒有其他相關警告輸出,則說明資料庫可以支援跨平台轉移。

(3)檢查外部對象。

使用dbms_tdb.check_external來識别外部表、directories或bfiles等,這些對象所指向的外部資料不能被rman自動轉移。

如果資料庫中存在外部表、directories等,則以上過程執行後的輸出與以上類似。

(4)使用rman進行跨平台檔案遷移。

執行跨平台遷移首先要通過rman對資料檔案進行轉換,rman執行過程如下:

最後rman還自動生成一個參數檔案,這個檔案是init_00il1i4r_1_0.ora,這個參數檔案裡包含了一些重要的初始化參數,可以根據需要進行相應的更改,由于平台以及路徑的不同,很多涉及路徑的參數都需要進行變更,這個參數檔案的内容大緻分為3個部分。

第一部分列出需要修改的參數:

第二部分列出了建議review的參數:

第三部分列出了來自于源資料庫的一些特殊設定,這些參數可以酌情修改:

參數檔案的内容我們可以在新的平台上重新建立,這個參數檔案可以作為參考。

(5)轉移檔案到目标平台。

源平台的工作完成之後,資料檔案可以通過ftp等方式轉移到目标平台,部署到相應目錄,我的操作步驟如下:

(6)建立基礎環境。

首先建立相關目錄:

建立windows資料庫服務:

執行個體已建立。

修改參數檔案,參數檔案可以從前面自動生成的參數檔案進行修改得到,其中目錄結構需要依據新平台的具體設定進行修改,和存儲主要相關的兩個參數修改如下:

如果我們計劃使用omf管理,可以暫時注釋這一參數,在建立控制檔案後再将控制檔案的名稱路徑追加到參數檔案中。

(7)遷移步驟。

準備工作完成之後,我們可以進行新平台的資料庫加載等工作,這些工作還可以參考在源平台生成的transport.sql腳本。

這個腳本的第一部分給出了使用參數檔案啟動執行個體及重新建立控制檔案的文法參考,當然我們還需要修改才能使用這段腳本:

由于我們已經編輯好了新的參數檔案,可以使用這個參數檔案啟動執行個體:

接下來建立控制檔案:

然後将控制檔案的名稱等資訊追加到參數檔案中:

sql&gt; host "echo &amp;ctl_files &gt;&gt;c:oracle10.2.0databaseinitjulia.ora";

執行完以上指令後,需要檢查參數檔案的格式,如果控制檔案名稱未正确添加,可以手工調整一下。

完成了以上工作後,可以關閉資料庫,再次啟動資料庫到mount狀态,這時候新的控制檔案已經發揮作用:

(8)完成資料庫恢複。

接下來再參考一下transport.sql中的推薦步驟:

現在我們需要通過resetlogs方式來重新生成日志檔案,然後手工添加臨時檔案。

注意,在遷移過程中如果兩個平台的資料庫版本完全一緻,則以上步驟可以順利執行,參考transport.sql可以順利完成遷移。而本例的測試平台由于linux平台的資料庫版本為10.2.0.1,windows平台版本為10.2.0.3,是以實際操作中還會有所不同,在執行resetlogs過程中,資料庫會發生中斷:

第 1 行出現錯誤:

ora-01092: oracle 執行個體終止。強制斷開連接配接

檢查日志我們發現以下提示:

mon jun 25 10:03:19 2007

errors in file c:oracleadminjuliaudumpjulia_ora_3596.trc:

ora-00704: 引導程式程序失敗

ora-39700: 必須用 upgrade 選項打開資料庫

oracle要求以upgrade選項打開資料庫,對資料庫執行跨版本遷移。

我們繼續參考transport.sql的最後部分:

再次啟動資料庫到upgrade模式,由于之前的資料庫中斷,現在這些需要進行一點恢複工作:

執行腳本?/rdbms/admin/utlirp.sql,這個腳本執行完成之後會有如下提示:

也就是說,這個腳本的作用是使資料庫中的pl/sql對象invalid,然後通過utlrp.sql的重新編譯,消除跨平台的相容性影響。

按照transport.sql腳本提示的步驟,我們可以重新啟動資料庫來執行utlrp.sql腳本(由于本例涉及版本遷移,需要再次啟動資料庫到upgrade模式,如果資料庫版本相同,則可以直接啟動資料庫,執行utlrp.sql腳本完成最後的編譯工作):

這個腳本調用catlog.sql和catproc.sql來重建字典對象等,在執行完這個腳本之後,我們可以關閉資料庫後,正常打開資料庫:

catupgrd.sql腳本可能會使部分字典對象失效,我們可以再次運作utlrp.sql腳本來進行編譯,編譯完成後,不要忘記為資料庫添加臨時檔案:

至此,同位元組序的跨平台遷移全部完成,當然由于版本的不同,整個過程稍微複雜了一些,不過,這個過程對于跨平台的遷移及版本更新是一個很好的參考。

9.實作資料遷移的高可用性

通過以上測試實際上可以确認,對于可傳輸表空間,可以很容易從oracle 9i向oracle 10g遷移。那麼這種方法對于可用性要求極高的環境進行資料遷移或資料庫遷移具有極大的便利。

如果進行資料庫更新,通常的方法是通過dbua(database upgrade assistant,oracle 10g引入的新工具)進行,但是dbua存在的問題在于,操作過程過長,而且如果更新過程中出現問題,資料檔案可能不能重新被使用,這就需要從備份中進行恢複,這使得業務連續性要求高的企業很難采用這種方法進行更新。

另外一種常見的遷移方法是通過邏輯導出導入(exp/imp),但是這種方法對于不斷變化的資料無能為力,是以通常也不可行。那麼現在,可傳輸表空間就成了一個可以考慮的快速遷移或更新方法。

oracle有一個小組,專注于設計高可用性架構的實作,以幫助使用者最大限度的提高系統可用性,oracle有一個專有名詞用來命名這類技術——maa(maximum availability architecture ,maa)。otn上maa部分有一個amadeus公司的實踐案例,通過可傳輸表空間從oracle 9i向oracle 10g實作快速資料遷移。

當然,這種方法的使用要考慮的還有很多,通過各種技術和方法的結合使用才能最終地達到快速遷移的目标。

amadeus公司的遷移是在同類型平台不同主機之間進行的,其實作步驟大緻如下:

(1)在更新主機安裝oracle 9i版本,并建立生産庫的dataguard資料庫,這個工作可以線上進行,不影響主節點的工作。

(2)在更新主機安裝oracle 10gr2資料庫軟體,建立資料庫;此時更新主機上存在了2個資料庫。

(3)整理不能通過transport tablespace處理的内容,如sequence、synonyms、grants等。

(4)在更新割接時間,将主庫置為隻讀,将日志全部應用到備機,業務影響從此時開始。

(5)将備機的資料檔案通過可傳輸表空間遷移至oracle 10gr2資料庫,并建立sequencee、synonyms、grants等對象,檢查驗證。

(6)如果沒有問題,則即可将業務切換至新的oracle 10gr2資料庫運作,業務恢複正常運作。

在這個遷移過程中,如果遷移失敗,那麼直接讀寫打開主庫即可恢複業務的正常運作,回退非常友善。

使用這種方法,業務影響僅發生在以上(4)~(6)步,在otn的案例中,amadeus公司在實際操作中,10分鐘之内就将一個大型資料庫遷移到oracle 10gr2,這種方式是一種非常有新意的創新性應用。在熟悉了oracle的各項技術之後,通過不斷實踐和探索,我們就能夠不斷發現充滿價值的oracle應用。

在進行表空間遷移時,如果是從檔案系統到檔案系統的遷移很容易實作,但是如果是從檔案系統到asm則需要多一點步驟。類似前面的測試,如果在asm環境中執行同樣的導入指令:

則簡單的導入之後會出現如下的效果,新導入的檔案位于檔案系統之上,這顯然是不希望看到的,我們需要将檔案系統檔案轉移到asm磁盤組上去:

檔案轉移可以通過rman來進行,但是首次嘗試遇到了rman-20201錯誤:

這個錯誤是由于trans表空間剛剛導入到資料庫中,處于隻讀狀态,并未被catalog記錄感覺,通過對這個檔案進行特定操作,如讀寫變更,則可以消除此錯誤:

rman中的schema資訊尚未記錄該表空間:

在資料庫内部對該表空置讀寫通路:

接下來将表空間狀态再改為隻讀:

通過rman進行鏡像拷貝:

切換之前需要将表空間離線,否則會出現錯誤:

将表空間離線:

現在轉換後的表空間已經被轉移到了asm磁盤組中,此時可以将表空間online,如果操作期間有過事務變更,還可能需要恢複:

從oracle 10g開始,oracle提供了dbms_file_transfer程式包,可以很友善地在本地資料庫和遠端資料庫,asm和檔案系統間傳輸資料庫檔案。

有了dbms_file_transfer,資料庫檔案的傳輸就友善了許多,尤其是在傳輸基于asm存儲的資料檔案時,不再局限于利用rman來進行傳輸,為我們提供了更多的選擇。

注意,dbms_file_transfer具備一定的限制,單個資料庫檔案必須是512位元組的整數倍,并且檔案大小必須小于或者等于2tb,但是這基本上算不上什麼弱點,我們的絕大多數需求都可以被滿足。

dbms_file_transfer包一共包含了3個存儲過程,分别提供本機之間拷貝(copy_file)、本機從遠端主機擷取(get_file)以及本機上傳至遠端主機(put_file)3種傳輸資料庫檔案的功能。

以上過程的參數中,除了檔案名稱外,最關鍵的是directory目錄參數,這個目錄需要預先設定,并且要求傳輸使用者對相應的目錄具有讀或者寫的權限。

看以下測試,首先通過asmcmd在datadg下建立一個asmbk目錄:

現在dbms_file_transfer就可以大顯身手,快速地幫助我們解決檔案傳輸的問題:

看一下asm磁盤組上的内容,實際上檔案的位置是在datafile下,asmbk下存放的是一個别名:

首先在遠端資料庫建立測試使用者及目錄,并進行授權:

接下來在本地資料庫配置tnsnames.ora檔案,并建立db link:

接下來就可以通過db link進行遠端的檔案操作了,put_file可以将檔案傳輸至遠端主機:

遠端節點可以立刻檢查到這個檔案的存在:

進一步的,可以将遠端檔案讀取到本地:

本地asm存儲中,馬上獲得了這個檔案:

而進一步的,将表空間置于熱備模式下,可以通過dbms_file_transfer包将資料庫熱備到遠端主機,甚至可以基于此來建立遠端的dataguard資料庫,有時在資料庫巨大,備份恢複空間不足時,通過這種方式進行資料傳輸與備庫建立未嘗不是一種妙解:

dbms_file_transfer為我們提供了多一個選擇和靈活性,很多時候,oracle一個小小的增強如果能夠得到恰如其分的利用,就能夠發揮巨大的優勢。了解了oracle的種種可能之後,我們才能夠靈活運用,如臂使指。

在oracle database 11g的建立腳本中,存在如下一個名為lockaccount.sql的腳本,該腳本在完成資料庫建立之後,将部分使用者賬号鎖定。一個簡單的for循環完成了這個安全加強的工作:

1.4.10 最後的腳本

在完成了主要腳本的工作之後,剩下的是一些最後的維護工作。

這裡還有兩個腳本需要執行,首先執行的是postscripts.sql腳本,這個腳本主要對部分使用者及部分資料庫選件進行維護:

最後執行的腳本是postdbcreation.sql,在這個腳本中将建立spfile,解鎖sysman、dbsnmp使用者,編譯失效對象并配置db control:

看到在最後部分,通過emca.bat批處理檔案,配置了db control,這裡通過一條完整的指令快速地完成了db control的建立等工作,也可以通過手工方式對db control進行維護,關于這部分的内容請參考“第2章 從oem到grid control”。

此外,需要注意的是以下幾句指令:

在oracle 9i的postdbcreation.sql的腳本中,這部分的内容如下:

其實兩者是相同的,utlrp.sql中主體部分與oracle 10g中是相同的:

oracle在utlrp.sql腳本的注釋中說得很明确:這是一個通用腳本,可以在任意時候運作,以重新編譯資料庫失效對象。

通常我們會在oracle的更新指導中看到這個腳本,oracle強烈推薦在migration / upgrade / downgrade之後,通過運作此腳本編譯失效對象。但是注意,此腳本需要用sql*plus以sysdba身份運作,并且當時資料庫中最好不要有活動事物或ddl操作,否則極容易導緻死鎖的出現。

這樣使用模闆建立資料庫就完成了。

1.4.11 使用模闆建庫注意事項

當使用模闆建立資料庫時,有一點需要特别注意,那就是種子資料庫的版本。因為種子資料庫通常來自軟體的初始分布版本,如安裝oracle database 9.2.0,則種子資料庫就是随軟體釋出的初始版本。如果我們安裝了9.2.0再安裝patch 9.2.0.8,那麼此後若使用模闆種子資料庫建立資料庫,則資料庫可能并不會自動更新為9.2.0.8的版本。

如此建立的資料庫其banner顯示為oracle 9i enterprise edition release 9.2.0.8.0:

而如果查詢注冊的元件會發現,大部分元件仍然是9.2.0.1的版本:

已選擇15行。

在這樣的模式下運作,資料庫的狀況是不可靠的,在某些條件下,因為這些元件的不完備,可能會出現錯誤。在以上的資料庫環境中,當drop使用者時可能會遇到如下錯誤:

解決該問題的方法就是運作一個更新重要腳本catpatch.sql,按照以下步驟操作:

之後可以檢視patch.log日志檔案來确認更新是否成功,如果成功完成,該日志末尾會顯示相關元件版本:

是以在使用模闆建立資料庫時,一定要注意更新問題。