DB2
表復(fù)制方法介紹
Version:v1.0.0
Author
:
xiedd
Mail:xiedd@icss.com.cn
CreateDate:2006-08-29
LastEditDate:2006-08-30
???????
說明
本文描述如何將DB2數(shù)據(jù)庫中的一些表復(fù)制到另一個數(shù)據(jù)庫中,適用于表中的數(shù)據(jù)量比較大(如1萬條記錄以上)的情況。當(dāng)表中的數(shù)據(jù)量較少,并且表的數(shù)量不多時,可直接使用db2控制中心的表復(fù)制功能實現(xiàn)。
???????
適用條件
n
???????
DB2
中表的跨庫復(fù)制,兩個數(shù)據(jù)庫可以在一臺機(jī)器上,也可以在不同的機(jī)器上。(以下假設(shè)兩個數(shù)據(jù)庫位于不同的機(jī)器上。)
n
???????
單一表中的數(shù)據(jù)量較大,通常在1萬條記錄數(shù)以上;
n
???????
表的個數(shù)比較多;
???????
術(shù)語定義
n
???????
源數(shù)據(jù)庫:需要復(fù)制的表存在的數(shù)據(jù)庫;
n
???????
目標(biāo)數(shù)據(jù)庫:需要復(fù)制的表復(fù)制后存在的數(shù)據(jù)庫;
n
???????
DDL:
數(shù)據(jù)定義語言,
用于建立和刪除數(shù)據(jù)庫以及數(shù)據(jù)庫實體的命令。
???????
總體說明
表的復(fù)制一般情況下用到了db2的以下幾個命令:
1.
?????
EXPORT:
導(dǎo)出表中的數(shù)據(jù)到數(shù)據(jù)文件中。
2.
?????
IMPORT:
導(dǎo)入數(shù)據(jù)文件中的數(shù)據(jù)到表中。
3.
?????
LOAD
:同IMPORT。區(qū)別是IMPORT需要寫日志,而LOAD不需要,因此可以極大的提高數(shù)據(jù)的裝載速度。
本文數(shù)據(jù)復(fù)制的思想是:首先通過DDL語言將源數(shù)據(jù)庫中的表結(jié)構(gòu)復(fù)制到目標(biāo)數(shù)據(jù)庫上,再通過批處理命令將源數(shù)據(jù)庫中需要復(fù)制的表export成數(shù)據(jù)文件(IXF集成交換格式),然后將數(shù)據(jù)文件復(fù)制到目標(biāo)數(shù)據(jù)庫所在的機(jī)器上,通過load命令將數(shù)據(jù)文件裝載到目標(biāo)數(shù)據(jù)庫中。
此過程主要使用了load命令以及避免了網(wǎng)絡(luò)傳輸,可以極大提高數(shù)據(jù)的復(fù)制速度。而腳本的方式也提供了更好的擴(kuò)展性,可對任意個數(shù)的表進(jìn)行復(fù)制。同時針對某些復(fù)雜情況可使用程序支持對這些腳本的自動生成。
???????
具體步驟
以下步驟假設(shè):
l????????
源數(shù)據(jù)庫為yndc
l????????
目標(biāo)數(shù)據(jù)庫為htdc
?
一、???
創(chuàng)建生成DLL文件的批處理文件
本步驟創(chuàng)建文件dll.bat。
其內(nèi)容語法示例如下:
db2look -d <dbname> -t? <table1> <table2> <tableN>? -e -nofed -o dll.sql
將<dbname>替換成源數(shù)據(jù)庫的名稱,<tableN>替換成具體的表名,多個表之間用空格分隔。如以下示例導(dǎo)出yndc數(shù)據(jù)庫中的2個表DIM_GROUP和DIM_PJ_MACH的庫表結(jié)構(gòu)。
db2look -d yndc -t? DIM_GROUP DIM_PJ_MACH? -e -nofed -o dll.sql
?
二、???
執(zhí)行DLL批處理文件,生成DLL文件
本步驟執(zhí)行dll.bat
將dll.bat復(fù)制到源數(shù)據(jù)庫所在的機(jī)器上,在db2cmd環(huán)境中執(zhí)行dll.bat,生成dll.sql。
?
三、???
執(zhí)行DLL文件
本步驟執(zhí)行dll.sql
執(zhí)行之前,更改dll.sql中目標(biāo)數(shù)據(jù)庫名稱,并輸入用戶名和密碼。同時必要情況下,更改表所在的表空間。
--
此 CLP 文件是使用 DB2LOOK 版本創(chuàng)建的 8.2
--
時間戳記: 2006-7-10 11:28:02
--
數(shù)據(jù)庫名稱: YNDC??????????
--
數(shù)據(jù)庫管理器版本: DB2/NT Version 8.2.4?????????
--
數(shù)據(jù)庫代碼頁: 1386
--
數(shù)據(jù)庫整理順序為: UNIQUE
?
?
CONNECT TO HTDC user db2admin using db2password;
?
------------------------------------------------
--
表的 DDL 語句 "DB2ADMIN"."BC_FACCIGTEMPLATE"
------------------------------------------------
?
?CREATE TABLE "DB2ADMIN"."BC_FACCIGTEMPLATE"? (
????
? "CITYID" VARCHAR(30) NOT NULL ,
????
? "CIGID" VARCHAR(30) NOT NULL ,
????
? "CIGNAME" VARCHAR(50) NOT NULL ,
????
? "ISUPLOAD" SMALLINT )??
????
?
IN "HTDC"
;
--
表上的索引的 DDL 語句 "DB2ADMIN"."BC_FACCIGTEMPLATE"
?
CREATE INDEX "DB2ADMIN"."PK__BC_FACCIGTEMP1" ON "DB2ADMIN"."BC_FACCIGTEMPLATE"
???? ("CITYID" ASC,
????
?"CIGID" ASC) CLUSTER ;
?
?
--
表上主鍵的 DDL 語句 "DB2ADMIN"."BC_FACCIGTEMPLATE"
?
ALTER TABLE "DB2ADMIN"."BC_FACCIGTEMPLATE"
ADD CONSTRAINT "SQL051107160756210" PRIMARY KEY
???? ("CITYID",
????
?"CIGID");
?
COMMIT WORK;
CONNECT RESET;
TERMINATE;
?
然后進(jìn)入db2cmd環(huán)境,切換到dll.sql所在的目錄,執(zhí)行以下命令:
注意查看執(zhí)行結(jié)果是否正確。
?
四、???
創(chuàng)建導(dǎo)出數(shù)據(jù)的EXPORT腳本
本步驟創(chuàng)建腳本export.bat
內(nèi)容格式示例如下:
db2 connect to <dbname> user <username> using <password>
db2 "export to aa1.ixf of ixf select * from <table1>"
db2 "export to aa2.ixf of ixf select * from <table2>"
db2 "export to aa3.ixf of ixf select * from <table3>"
…
db2 connect reset
替換數(shù)據(jù)庫名稱、用戶名、密碼、表名。注意事項:多個表之間的集成交換格式文件按需要遞增,如aa1.ixf,aa2.ixf,aa3.ixf...,并且要和后續(xù)的load腳本對應(yīng)。
?
以下樣例導(dǎo)出2個表的數(shù)據(jù),樣例如下:
db2 connect to yndc user db2admin using db2password
db2 "export to aa1.ixf of ixf select * from DIM_GROUP"
db2 "export to aa2.ixf of ixf select * from DIM_PJ_MACH"
db2 connect reset
?
五、???
執(zhí)行export腳本
本步驟執(zhí)行export.bat
在源數(shù)據(jù)庫所在的機(jī)器上,在db2cmd環(huán)境中執(zhí)行export.bat。N個表將生成N個集成交換格式數(shù)據(jù)文件(后綴名.ixf)。
?
六、???
將導(dǎo)出的數(shù)據(jù)壓縮復(fù)制到目標(biāo)數(shù)據(jù)庫所在機(jī)器,并解壓縮
將數(shù)據(jù)文件打成rar或zip包,復(fù)制到目標(biāo)機(jī)器上,并解壓縮。
?
七、???
構(gòu)建導(dǎo)入數(shù)據(jù)的LOAD腳本
本步驟在數(shù)據(jù)文件(IXF)所在的目錄中創(chuàng)建load.bat。
內(nèi)容格式示例如下:
db2 connect to <dbname> user <username> using <password>
db2 "load from aa1.ixf of ixf? replace into <table1>? COPY NO? without prompting " > 1_<table1>.log
db2 "load from aa2.ixf of ixf? replace into <table2> COPY NO? without prompting " > 2_<table2>.log
…
db2 connect reset
替換數(shù)據(jù)庫名稱、用戶名、密碼、表名。注意事項:集成交換格式文件(ixf)對應(yīng)的表名要和export時導(dǎo)出的表名對應(yīng)。
?
以下樣例導(dǎo)入2個表的數(shù)據(jù),樣例如下:
db2 connect to yndc user db2admin using db2password
db2 "load from aa1.ixf of ixf? replace into DIM_GROUP? COPY NO? without prompting " > 1_DIM_GROUP.log
db2 "load from aa2.ixf of ixf? replace into DIM_PJ_MACH? COPY NO? without prompting " > 2_DIM_PJ_MACH.log
db2 connect reset
???
???
八、???
執(zhí)行load腳本,檢查執(zhí)行結(jié)果
本步驟執(zhí)行export.bat
在db2cmd環(huán)境中切換到load.bat所在的目錄,執(zhí)行load.bat。
執(zhí)行完成之后N個表將生成N個log文件,逐一檢查這些log文件,以確定數(shù)據(jù)load是否正常。
所有步驟結(jié)束!
?
???????
附錄1:重命名表的名稱
如果需要將表復(fù)制到目標(biāo)數(shù)據(jù)庫時使用不同的名稱,可在以上步驟完成之后,再編輯一個腳本,執(zhí)行表的重命名操作。示例如下:
db2 connect to <dbname> user <username> using <password>
db2 rename <table1_old> to <table2_new>
db2 rename <table2_old> to <table3_new>
...
db2 connect reset
???????
附錄2:使用程序生成腳本
當(dāng)表的數(shù)量較多,手工編輯腳本比較復(fù)雜時,可通過java程序生成dll.bat,export.bat和load.bat。
示例如下:
/**
?* <p>Title:
數(shù)據(jù)庫集成服務(wù)類,支持對yndc等數(shù)據(jù)庫進(jìn)行集成</p>
* @version 1.0
?*/
public class DBEAIService {
??? /**
???? *
數(shù)據(jù)文件存放目錄
???? */
??? private String DEST_DIR = Globals.ManagerHome + "/output";
?
??? /**
???? *
日志記錄器
???? */
??? private static Logger log = Logger.getLogger(DBEAIService.class);
?
??? public DBEAIService() {
?
??? }
?
?
??? /**
???? *
創(chuàng)建導(dǎo)出腳本
???? * @param conn
???? * @param creator
表創(chuàng)建者
???? * @param filePath
???? */
??? private void createExportFile(Connection conn, String creator,
????????????????????????????????? String filePath) throws Exception {
??????? DBBase dbBase = new DBBase(conn);
??????? String selectTableSql =
??????????????? "select name from sysibm.systables where creator = '"
??????????????? + creator + "' and type='T' order by name";
??????? try {
????
???????dbBase.executeQuery(selectTableSql);
??????? } catch (Exception ex) {
??????????? throw ex;
??????? } finally {
??????????? dbBase.close();
??????? }
??????? DBResult result = dbBase.getSelectDBResult();
??????? List list = new ArrayList();
??????? while (result.next()) {
??????????? String table = result.getString(1);
??????????? list.add(table);
??????? }
??????? StringBuffer sb = new StringBuffer();
??????? String enterFlag = "\r\n";
??????? for (int i = 0; i < list.size(); i++) {
??????????? String tableName = (String) list.get(i);
??????????? sb.append("db2 \"export to aa" + String.valueOf(i + 1)
????????????????????? + ".ixf of ixf select * from " + tableName + "\"");
??????????? sb.append(enterFlag);
??????? }
??????? String str = sb.toString();
??????? FileUtility.saveStringToFile(filePath, str, false);
??? }
?
??? /**
???? *
創(chuàng)建裝載腳本
???? * @param conn
???? * @param creator
表創(chuàng)建者
???? * @param filePath
???? */
??? private void createLoadFile(Connection conn, String creator,
??????????????????????
?????????String filePath) throws
??????????? Exception {
??????? DBBase dbBase = new DBBase(conn);
??????? String selectTableSql =
??????????????? "select name from sysibm.systables where creator = '"
??????????????? + creator + "' and type='T' order by name";
??????? try {
??????????? dbBase.executeQuery(selectTableSql);
??????? } catch (Exception ex) {
??????????? throw ex;
??????? } finally {
??????????? dbBase.close();
??????? }
??????? DBResult result = dbBase.getSelectDBResult();
??????? List list = new ArrayList();
??????? while (result.next()) {
??????????? String table = result.getString(1);
??????????? list.add(table);
??????? }
??????? StringBuffer sb = new StringBuffer();
??????? String enterFlag = "\r\n";
??????? for (int i = 0; i < list.size(); i++) {
??????????? String tableName = (String) list.get(i);
??????????? sb.append("db2 \"load from aa" + String.valueOf(i + 1)
????????????????????? + ".ixf of ixf into " + tableName
????????????????????? + "? COPY NO? without prompting \"");
??????????? sb.append(enterFlag);
??????? }
??????? String str = sb.toString();
??????? FileUtility.saveStringToFile(filePath, str, false);
??? }
?
??? /**
???? *
獲取某個數(shù)據(jù)庫表明的列表
???? * @param conn
???? * @param creator
表創(chuàng)建者
???? * @return
???? * @throws Exception
???? */
??? private List getTableList(Connection conn, String creator) throws Exception {
??????? DBBase dbBase = new DBBase(conn);
??????? String selectTableSql =
??????????????? "select name from sysibm.systables where creator = '"
??????????????? + creator + "' and type='T' order by name";
??????? try {
??????????? dbBase.executeQuery(selectTableSql);
??????? } catch (Exception ex) {
??????????? throw ex;
??????? } finally {
??????????? dbBase.close();
??????? }
??????? DBResult result = dbBase.getSelectDBResult();
??????? List list = new ArrayList();
??????? while (result.next()) {
??????????? String table = result.getString(1);
??????????? list.add(table);
??????? }
??????? return list;
??? }
?
??? /**
???? *
將列表寫入到文本文件中
???? * @param list
???? * @param filePath
???? */
??? public void saveListToFile(List list, String filePath) throws Exception {
??????? StringBuffer sb = new StringBuffer();
??????? for (int i = 0; i < list.size(); i++) {
??????????? String value = (String) list.get(i);
??????????? sb.append(value);
??????????? sb.append("\r\n");
??????? }
??????? String str = sb.toString();
??????? FileUtility.saveStringToFile(filePath, str, false);
??? }
?
posted on 2006-09-14 09:55
水煮三國 閱讀(2231)
評論(0) 編輯 收藏 所屬分類:
Database