本文主要介紹如何完成以DB2 為基礎的PHP 應用系統從AIX 平台到Linux 平台的移植過程。文中包含了底層的DB2 資料庫移植、上層的PHP 應用系統移植的詳細步驟以及移植過程中可能遇到的問題和解決方法。
任務概述
系統遷移的工作主要分為以下幾個面向:
1.DB2 資料庫系統的跨平台遷移
2.Apache 伺服器與php 應用系統的安裝與設定
下面我們就分2 個面向分別介紹遷移與設定的具體步驟。
DB2 資料庫系統的跨平台遷移
資料庫環境
來源環境:AIX+DB2 v8.1
目標環境:Linux+DB2 v8.1
其中來源資料庫中包含了2 個資料庫Instance:SRCDB1 與SRCDB2。在SRCDB1/SRCDB2 資料庫中,均包含了上百張資料庫表,並且有很多的索引、外鍵約束、觸發器、預存程序以及一些含有自增欄位的表(含有GENERATED ALWAYS AS IDENTITY 定義欄位的表) 。更困難的是,我們並沒有關於這些資料庫物件的準確建立腳本。
遷移方案的選擇
如果遷移的來源系統與目的系統屬於同一類型作業系統,例如Linux 之間的遷移,或者AIX 系統之間的遷移,則情況相對簡單,DB2 本身已經提供相關的實用工具來實現這種同類型平台之間的資料庫移植,如: BACKUP 和RESTORE 指令。當然,根據不同的情況也需要對實用工具所提供的參數有比較清楚的了解,譬如來源系統與目標系統使用不同的表空間,就會涉及到表空間重定向的問題。由於本文的重點在於跨平台的移植,這種方案顯然無法滿足需求,在此不再熬述。
那麼,如何處理跨平台的資料庫遷移問題呢?是不是可以使用實用工具db2move 呢? db2move 只能遷移表中的數據,而無法對索引、外鍵約束、觸發器和預存程序等資料庫物件也實現遷移操作,而且對於包含自增欄位資料的表來說,db2move 也有一定的限制。而db2move 只能把資料匯入到已存在的資料庫的表中,無法顯示指定表空間的位置。由於在資料庫的系統遷移過程中,不僅需要遷移表中的數據,還有索引、外鍵約束、觸發器和預存程序等資料庫對象,與本文所選方案相比,還是後者更具優勢。可以將db2move 僅作為遷移表資料的一種備用方案。
而對於export 和import 來說,一次只能針對一張表進行導出導入操作,並且需要手動輸入export 和import 的命令以及需要導入導出的數據表名,在數據庫表的數量不多的情況下,這種方案也許還可以考慮,但也不併是最佳的方案。而在資料庫中表格數量眾多的情況下,這種做法則是基本上不切實際的,而且import 指令並不能保證自增欄位的資料與原來的表格資料一致。
本文根據DB2 對資料庫物件的處理機制,採用將db2look 與DDL、DML 腳本結合的方式,並針對原始資料庫中的觸發器、預存程序以及外鍵約束等分別處理,給出了一種跨平台DB2資料庫系統移植的可行方案。
以下我們以SRCDB1 為例介紹一下這種情況下的資料庫整體遷移過程。 SRCDB1 資料庫中有SRCDB1、ASN、DB2DBG 和SQLDBA 這四個資料庫模式。假設SRCDB1 資料庫的使用者名稱為user_srcdb1,密碼:pw_srcdb1。
在來源系統(AIX) 上的相關操作
1.使用db2look 指令抽取產生資料庫物件的DDL 腳本
清單1. db2look 指令及參數
# db2look -d SRCDB1 -e -o srcdb1.ddl -a -i user_srcdb1 -w pw_srcdb1
db2look :產生DDL 以便重新建立在資料庫中定義的物件
語法: db2look -d DBname [-e] [-u Creator] [-z Schema]
[-t Tname1 Tname2...TnameN] [-tw Tname] [-h] [-o Fname] [-a]
[- m] [-c] [-r] [-l] [-x] [-xd] [-f] [-fd] [-td x]
[-noview] [-i userID] [-w password]
[ -v Vname1 Vname2 ... VnameN] [-wrapper WrapperName]
[-server ServerName] [-nofed]
-d : 資料庫名稱,必選參數
-e : 抽取複製資料庫所需的DDL 文件,此選項將產生包含DDL語句的腳本
-o : 將輸出重定向到給定的檔案名,如果未指定-o 選項,則輸出預設轉到stdout
-a : 為所有建立程式產生統計訊息,如果指定了此選項,則將忽略-u 選項
-i : 指定登入資料
庫所在伺服器時所使用的使用者識別碼-w : 指定登入資料庫所在伺服器時所使用的密碼
2.根據不同類型對象,分化資料庫對象DDL 腳本
由於來源資料庫中的各個表資料已經是經過觸發器、預存程序等資料庫對象處理過的數據,為確保資料庫中資料的一致性與完整性,這些資料庫對象應該在匯入資料後再創建,以防止在匯入表格資料時重複執行觸發器和預存程序等資料庫物件產生錯誤資料。使用文字編輯器編輯由db2look 產生的srcdb1.ddl,將建立表格及索引的DDL 語句,建立外鍵約束的DDL 語句以及建立觸發器和建立儲存程序的語句分為四組,分別儲存為下面四個DDL 腳本:
srcdb1_tables.ddl srcdb1_foriegnkeys.ddl
srcdb1_triggers.ddl srcdb1_procedures.ddl
srcdb1_tables.ddl :包含建立SEQUENCE,UDF,TABLE,VIEW 等資料庫物件的ddl 語句。
清單2. srcdb1_tables.ddl 語句
CREATE SEQUENCE
"SRCDB1"."SAMPLE_SEQ_1" AS INTEGER
MINVALUE 1 MAXVALUE 9999999999
START WITH 1 INCREMENT BY 1;
CREATEFLE] SCHARNP
),
VARCHAR(254)
) RETURNS VARCHAR(254)
SPECIFIC SAMPLE _FUNC_1 …;
CREATE
TABLE " SRCDB1"." SAMPLE _TAB_1" (
"TAB_COL1" CHAR(20) NOT NULL ,
"TAB_OL20" VABE
" SRCDB1"." SAMPLE _TAB_2" (……);
……
CREATE TABLE " SRCDB1"." SAMPLE _TAB_N" (…);
CREATE VIEW SRCDB1.SAMPLE_VIEW_1 (VIEW_COL1,VIEW_COL2) ASLESECTLE_VIEW_1 (VIEW_COL1,VIEW_COL2) ASLE_ECT
COL2) …;
CREATE VIEW SRCDB1.SAMPLE_VIEW_2 ……;
……
CREATE VIEW SRCDB1.SAMPLE_VIEW_N …;
srcdb1_foriegnkeys.ddl :包含建立外鍵約束的ddl 語句。
清單3. srcdb1_foriegnkeys.ddl 語句
ALTER TABLE " SRCDB1"."SAMPLE_FK_1"
ADD CONSTRAINT "SQL030903143850120" FOREIGN KEY
(
"FK_COL1")
REFERENCES "SRCD3S.
"SAMPLE_FK_2 " ADD ……;
……
ALTER TABLE " SRCDB1"."SAMPLE_FK_N" ADD ……;
srcdb1_triggers.ddl :包含建立觸發器的ddl 語句。
清單4. srcdb1_triggers.ddl 語句
CREATE TRIGGER SRCDB1.SAMPLE_TRIG_1 AFTER UPDATE OF col1 ON SRCDB1.SAMPLE_TAB
REFERENCING NEW AS n FOR EACH ROW MODE DB2SQL WHEN ( n.col1 > 3)
BEGIN ATOMIC
update SAMPLE_TAB
set(col2) = 'anotherValue' where col1 = n.col1 ;--
END
;
CREATE TRIGGER SRCDB1.2… TRIG_AMP;
CREATE TRIGGER SRCDB1. SAMPLE_TRIG_N …;
srcdb1_procedures.ddl :包含建立SQL 預存程序以及java 預存程序的ddl 語句。
清單5.
srcdb1_procedures.ddl語句
CREATE PROCEDURE " SRCDB1"." JAVA_PROCEDURE_1" (
OUT
SQLSTATE CHARACTER(5),
OUT
ROWS_SUBMITED INTEGER,
IN BATCH_ID INTEGER,
IN LEVEL '
Submit_batch! submit_batch'
LANGUAGE JAVA
PARAMETER STYLE JAVA
NOT DETERMINISTIC
FENCED THREADSAFE
MODIFIES SQL DATA
NO DBINFO;
CREATE PROCEDURE " SRCDB1"
."JAVA_PROCEDURE_2"
…。
SET CURRENT SCHEMA = " SRCDB1";
SET CURRENT PATH = "SYSIBM","SYSFUN"," SRCDB1";
CREATE
PROCEDURE SRCDB1.SQL_PROCEDURE_1
(
IN
.
.SQL_PROCEDURE_1
LANGUAGE SQL
---------------------------------------------- ---
-- SQL Stored Procedure
------------------------------------------ -------
P1: BEGIN
……
END P1 ;
CREATE PROCEDURE SRCDB1.SQL_PROCEDURE_2 ……;
……
CREATE PROCEDURE SRCDB1.SQL_PROCEDURE_N ……;
需要注意的是,db2 v6 版本的db2look 尚未實現抽取如UDF,TRIGGER ,UserSpace,NodeGroup,BufferPool 等資料庫物件的ddl 語句。從db2 v7 開始,db2look 可以抽取上述物件的DDL,但仍無法抽取建立預存程序物件的ddl 語句。從db2 v8.2 開始,完善了對db2look 功能的支持,實現了預存程序ddl 語句的抽取功能。由於本文所涉及的來源資料庫系統的版本較低(DB2 v8.1),因此需要採取上述方案獲取所有資料庫物件的DDL 資訊:
1). 從某個DB2 v8.2 系統對SRCDB1(DB2 v8.1版本)執行CATALOG 操作:
db2 catalog db SRCDB1 as SRCDB1;
2
). 從DB2 v8.2 系統對SRCDB1 進行db2look 抽取過程:
db2look -d SRCDB1 -e -o srcdb1.ddl -a -i user_srcdb1 -ww pw_srcdb1;
對象DDL 資訊。
3.產生資料匯出export腳本
使用shell 腳本產生並匯出所有資料的DML 腳本,並將其重定向到srcdb1_export.sql 檔案中。對於熟悉DB2 的使用者來說,應該知道資料庫中建立的每個資料表、檢視、別名皆對應SYSCAT.TABLES 中一行記錄。因此可以透過對應的資料庫select 語句就可以獲得所有需要的資料庫表格資訊。根據需要,下述shell 腳本將從系統表SYSCAT.TABLES 中根據tabname 欄位選出SRCDB1 中所有tabschema 表模式是SRCDB1,ASN,SQLDBA,DB2DBG 的表名字,並根據它們的名字產生對應的export 匯出語句,到達批量導出的目的。 rtrim 函數用於移除tabname 欄位資料的右邊的空格。
清單6. 產生export腳本
# db2 "select 'export to ' rtrim(tabname) '.ixf of ixf select * from '
rtrim(tabname) ';' from syscat.tables
where tabschema in('SRCDB1', 'ASN', 'SQLDBA', 'DB2DBG')" > srcdb1_export.sql ;
編輯產生的srcdb1_export.sql,刪除頭部和尾部所顯示的統計信息,只保留必要的export 語句。透過修改上述腳本中所包含的tabschema 訊息,可以指定需要匯出的表的範圍,也即遷移過程中所需的所有表名。所產生的export 匯出語句有以下的指令形式:
db2 export to tablename.ixf of ixf select * from tablename;
4.產生資料匯入load 腳本
使用shell 腳本產生load 腳本用於將資料匯入目標系統:srcdb1_load.sql
清單7.產生load 腳本
# db2 "select 'load from ' rtrim(tabname) '.ixf of ixf insert into '
rtrim( tabname) ';' from syscat.tables
where tabschema in ('SRCDB1', 'ASN', 'SQLDBA', 'DB2DBG')" > srcdb1_load.sql;
編輯產生的srcdb1_load.sql,刪除頭部和尾部的統計資料,只保留必要的load 語句。與export 匯出語句類似,上述shell 腳本從系統表中選出SRCDB1 中所有表格的名字,並根據它們的名字產生對應的import 匯入語句,到達批次匯入的目的。所產生的import 導入語句指令形式如下:
db2 load from tablename.ixf of ixf insert into tablename;