『OGG 02』Win7 配置 Oracle GoldenGate Adapter Java 踩坑指南

來源:互聯網
上載者:User

標籤:eclipse   14.   update   配置環境   package   基礎   尾碼   兩台   現在   

上一文章 《__Win7 配置OGG(Oracle GoldenGate).docx》定下了 兩個目標:

  • 目標1:

給安裝的Oracle_11g 建立 兩個使用者 admin 和 root 。

admin 對應了 ADMIN 結構,建立了一個 TB_ TEST表。

root 對應了 ROOT 結構,也建立一個 TB_ TEST (表結構一摸一樣)。

當 admin.TBTEST 中的表資料 變化時,root.TB TEST 的表資料 自動同步(備份)

PS. 實際的 容災備份,肯定是 兩個 Oracle 伺服器,通過網路傳輸 備份資料 —— 各位可以想象 admin 和 root 在兩台不同伺服器 上。

  • 目標2:

當 admin.TB_ TEST 表資料發生變化時,把這種變化 傳遞給 Java、C# 程式。

當 Java、C# 程式得到 資料變化訊息時,把 資料的變化 記錄到日誌中(或者其他動作)。

其中,目標1 已經完成,我們開始嘗試 目標2

下載 OGG Adapter Java:

http://www.oracle.com/technetwork/cn/middleware/goldengate/downloads/index.html

開始配置 Java運行環境:
  • 我開始後悔了,我的系統是 64位Win7。

  • 我後悔自己安裝的是 32位的 Oracle。

  • 我後悔自己安裝了兩套 JDK: C:\Program Files\Java\jdk1.8.0121 和 C:\Program Files (x86)\Java\jdk1.8.0121。

  • 我後悔自己的OGG目錄 取了這麼長的 一個名字: D:\oracle\product\11.1.0\x86_ogg4oracle\

  • 接下來的文章:這些坑將導致各種詭異的問題 —— 填坑指南,作者帶著你 一起踩坑一起填,在失敗中積累厚重經驗、在填坑中收穫絕對穩定。

配置環境變數:

我的電腦 64位Win7,安裝了 64位、32位 位兩種 JDK。Oracle_11g 32位,OGG 32位。

進行如下操作:

  • 找到 64位 JDK目錄 —— 右鍵,“360強力刪除” —— 沒錯,強力粉碎,這源自我踩坑踩出的仇恨,粉碎,粉碎。 案頭>電腦>右鍵>屬性>進階系統設定>“進階”選項卡>環境變數。

CLASSPATH : .;%JAVAHOME%\lib\tools.jar;%JAVAHOME%\lib\dt.jar;%JAVA_HOME%\bin;

JAVAHOME : C:\Program Files (x86)\Java\jdk1.8.0121

JREHOME : C:\Program Files (x86)\Java\jre1.8.0121

Path : %JAVA_HOME%\bin;

驗證環境變數:

開啟cmd (不詳述了,cmd 都打不開,這篇文章你也不用看了)

建議重啟電腦,好像有時候,JAVA的環境變數 要重啟後 才生效 —— 重啟保平安。

開始考驗 JAVA基礎的時候了:

開啟 eclipse,建立一個 hello world 項目。匯出 jar 包。

再次驗證 java 運行環境:

你以為 這個 hello.jar 有啥用? —— 沒用!

玄學懂不懂?

安裝SQL Server 你不去上個廁所,你還想安裝成功?【上廁所,減少人為磁碟操作,SQLServer安裝程式更穩定】

你不寫個 hello word,你還想把OGG Adapter Java 配成?【就是為了驗證 java 運行環境,配置者的java基礎】

開始配置 OGG Adapter Java 【正式代碼在下面,我們要先驗證 OGG-Java 的配置環境】

回顧一下:針對 ADMIN.TB_TEST 表 —— 當資料變化時,我們的Java外掛程式要能夠 捕獲到資料變化。

產生表結構 定義檔案。【目標:得到一個 .def 尾碼的檔案(過程中的其他檔案都可以刪除)】

在 D:\Temp\ 檔案夾建立一個 文字檔 source.prm 內容如下:

運行 cmd,通過 source.prm 產生 source.def 檔案。

找到 D:\oracle\product\11.1.0\x86ogg4oracletarget\ 【目標端】雙擊運行 ggsci.exe 程式。 添加 javaue

配置 javaue

javaue.prm如下:

Extract JAVAUE

SourceDefs dirprm/source.def

getEnv (JAVA_HOME)

-- getEnv (LDLIBRARYPATH)

getEnv (PATH)

CUserExit ggjava_ue.dll CUSEREXIT PassThru IncludeUpdateBefores

GetUpdateBefores

Table ADMIN.*;

javaue.properties 如下:

gg.handlerlist=sample.SampleHandler

java.naming.provider.url=tcp://localhost:61616

java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory

gg.handler.sample.type=sample.SampleHandler

goldengate.userexit.timestamp=utc

goldengate.userexit.nochkpt=true

嘗試啟動 javaue

PS.

如果出現 “不出錯”的錯誤(rpt 檔案沒有任何異常資訊),但 start javaue 視窗一閃而過,死活無法啟動。

記住如下方式:用命令列 參數模式 啟動 javaue,可以顯示 “不出錯”錯誤。

extract paramfile D:\oracle\product\11.1.0\x86_ogg4oracle_target\dirprm\javaue.prm

正式編寫 OGG Adapter Java 外掛程式代碼

建立項目 custom,添加 jar包 引用。

建立 Java檔案 SampleHandler,源碼如下:

注意:OGG 12 和 OGG 11 的代碼是完全不同的。

//---------------------------------------------------------------------------------------------------package sample;    //包名稱 sample,類名稱 SampleHandler —— 有沒有讓你想到什嗎? javaue.propertiesimport java.io.*;//這是 OGG 11 的 import import com.goldengate.atg.datasource.AbstractHandler;import com.goldengate.atg.datasource.DsConfiguration;import com.goldengate.atg.datasource.DsEvent;import com.goldengate.atg.datasource.GGDataSource.Status;import com.goldengate.atg.datasource.meta.DsMetaData;import com.goldengate.atg.datasource.test.DsTestUtils.Logger;import com.goldengate.atg.datasource.meta.*;import com.goldengate.atg.datasource.*;//這是 OGG 12 的 import //import org.slf4j.Logger;//import org.slf4j.LoggerFactory;//import oracle.goldengate.datasource.AbstractHandler;//import oracle.goldengate.datasource.DsConfiguration;//import oracle.goldengate.datasource.DsEvent;//import oracle.goldengate.datasource.DsTransaction;//import oracle.goldengate.datasource.conf.DsHandler.Handler.Status;//import oracle.goldengate.datasource.meta.DsMetaData;//import oracle.goldengate.datasource.GGDataSource;public class SampleHandler extends AbstractHandler {        //OGG 11 和 OGG 12 的 日誌好像不一樣, OGG 12 似乎要寫 LoggerFactory.getLogger(SampleHandler.class);    private final Logger logger = com.goldengate.atg.datasource.test.DsTestUtils.Log4jLogger.getLogger(SampleHandler.class);    @Override    public void init(DsConfiguration conf, DsMetaData metaData) {        super.init(conf, metaData);        logger.info("init!");        WriteStringToFile("D:\\SampleHandler。log", "SampleHandler.init(*)");    }    @Override    public Status transactionCommit(DsEvent e, DsTransaction tx) {        logger.info("transactionCommit!");        WriteStringToFile("D:\\SampleHandler。log", "SampleHandler.transactionCommit(*)");         return Status.OK;    }    @Override    public void destroy() {        super.destroy();        WriteStringToFile("D:\\SampleHandler。log", "SampleHandler.destroy(*)");         logger.info("destroy!");    }    @Override    public String reportStatus() {        WriteStringToFile("D:\\SampleHandler。log", "SampleHandler.reportStatus(*)");         return "reportStatus";    }      public void WriteStringToFile(String filePath, String text) {          try {              System.out.println(text);             File file = new File(filePath);              PrintStream ps = new PrintStream(new FileOutputStream(file));              //ps.println(text);// 往檔案裡寫入字串              ps.append(text);// 在已有的基礎上添加字串          } catch (FileNotFoundException e) {              e.printStackTrace();          }      }  }//---------------------------------------------------------------------------------------------------

編譯通過,匯出 jar包:

再次啟動 javaue:

視窗再次一閃而過,啟動失敗,繼續查錯。

參考:49300853

重裝 Java環境,重新修改 4個環境變數,驗證 java 安裝環境。

java -jar D:\hello.jar

重啟電腦(或者關掉所有 cmd, ggsci 視窗),重新開啟 \x86ogg4oralcetarget\ggsci.exe 輸入命令: start mgr start javaue

現代詩:《OGG的迷惘》

那一刻,

晶瑩的淚水滑過臉龐,

我似乎,

看到了成功的希望。

蹉跎與掙紮,

糾結與迷惘。

在折騰中,我終究能走向想要的遠方。

—— 再給我一次機會,讓我再配置一次OGG。

—— 不!我選擇 死亡(罵娘)~

打油詩:《神坑OGG》

神坑最多OGG,

坑得勞資沒脾氣。

坑得勞資沒脾氣~

神坑最多OGG~

開始測試 javaue 外掛程式是否成功:

程式這次崩潰了,對比一下 兩種配置:

在下面的配置(崩潰)中,我們看到了一個路徑 dirlib/custom.jar。

我們嘗試將 eclipse 匯出的 jar 檔案 D:\Temp\custom.jar,複製到 \x86ogg4oracletarget\dirlib\ 檔案夾(dirlib 要手動建立)

再次運行,還是崩潰,還是相同的錯誤資訊:

雖然不報錯了,但為什麼 我在 insert 時,外掛程式代碼沒有執行呢???

我們刪除 javaue,然後重建一下:

再次啟動 start javaue —— 記住我的ID,再不成功,我直播倒立寫代碼 ~

結果我又失望了:外掛程式似乎沒有執行 —— 外掛程式的代碼會產生一個 D:\ SampleHandler.log 的記錄檔的,但結果沒有。

我似乎又打臉了 —— 啪啪的疼~

我整個人都不好了,日子本已如此艱難,真心快要過不下去了。

 

就在我一籌莫展時,我有事沒事的 翻看 \x86ogg4oracletarget\ 的幾個 6個字母的 檔案夾。

意外發現了一個檔案,我好奇的將檔案開啟。

我看到了 一個路徑:沒錯啊!就是我配置的 資料檔案夾 路徑。

確實沒錯啊!難道非要驗證一下 路徑嗎?我雖然吃路徑的虧 上了 5次當了。

—— 但這個路徑確實沒錯啊,還不信,我複製給你看看。

整個人都不好了,文本配置最大的弊端就是:你敲幾百幾千個字母,一點手誤都不能有(尼瑪路徑錯了還沒提示)

 

再次重建 javaue,插入資料 —— 我這次也沒抱啥希望了,被折磨哭了都,不想被打臉了。

我看到了 一個 路徑: \dirdat\r1000000 —— 感覺很奇怪:

源端 ext1 >>> 目標端 rep1,這種資料檔案 都已經到了 r1000005 了 —— 為什麼 javaue 還在找 r1000000

—— 要不,在源端 重建一個 ext2,使用 r2,讓 javaue 從 r2 找資料?

 

開啟源端 OGG 目錄:建立 ext2

源端 添加、啟動 ext2,啟動成功(我都已經駕輕就熟了) :

開啟目標端,重建 javaue,使用 r2:

這次,我們看到了一段之前沒有出現過的代碼:

開啟 dirdat 目錄:

再次執行 insert 指令碼,插入資料的那一刻,javaue 崩潰了:

一臉懵逼,整個人都不好了。 就在我手足無措時,我意外看到 D:\ SampleHandler.log 檔案被建立了 —— 雖然程式崩潰了,但是Java代碼執行了。

FlagFile 意外配置成功了(本文不多說了,就截了個圖)

心累了,又折騰了一天時間。直接說結果吧:

 

OGG Adapter Java,只和 /dirdat/r2000000 這種資料有關【和 版本無關、和 x86 x64 無關,和 源端、目標端 無關。】

整個OGG 所有涉及到的所有路徑,都必須使用 反斜線 /。【如果寫成 D:\AAA\x86\ 程式可能會識別為亂碼而詭異崩潰。】

尤其注意:添加 javaue 時,路徑一定要用 反斜線 /

其實直到現在,

OGG Adapter Java 11 x86 版本 每次都會崩潰。就是前兩個步驟的BUG:資料變化捕獲到了,Java代碼執行了,但是程式崩潰了。

OGG Adapter Java 12 x64 版本,我把 /dirprm/javaue.prm 和 /dirprm/javaue.properties 和 /dirprm/source.def 三個檔案 從 11 拷貝到 12, 執行 add extract javaue —— 程式卻能正常運行,捕獲到資料。

OGG 源端 必須和 Oracle 版本、32\64 位元保持一致。

但是 OGG Adapter 沒那麼多限制。OGG Adapter 只針對 /dirdat/r1 或 /dirdat/r2 這類 Trail 檔案。

最終方案如下:

仔細看 右下角: 我增加了一個 OGG 12 x64 —— 由這個 OGG 啟動 javaue。

而 javaue 只只要對接 磁碟檔案 dirdat\r2000001

雖然 有兩個 OGG 11 x86,但是 好在 磁碟 Trail檔案 是互連的。

放一個成功啟動並執行:

我寫了一個 C#程式,每隔一秒 就向 ADMIN.TB_TEST 寫入一行記錄。

理論上 ROOT.TB_TEST 會同步這些資料。

理論上 javaue 能捕獲到 資料變化。

至此,第二目標完成。

最後放出 最終成功的配置:

或者參見 下一篇文章 《OGG Adapter Java一次性成功》

dirprm 檔案夾:

javaue.prm 配置:

javaue.properties 配置:

Source.def 是產生的(產生方式看文章前面),手寫無效:

custom.jar 是編譯後 匯出的 jar包:
//---------------------------------------------------------------------------------------package sample;import java.io.*;import java.util.ArrayList;import java.util.List;import java.util.Set;//這是 OGG 11 的 import //import com.goldengate.atg.datasource.AbstractHandler;//import com.goldengate.atg.datasource.DsConfiguration;//import com.goldengate.atg.datasource.DsEvent;//import com.goldengate.atg.datasource.GGDataSource.Status;//import com.goldengate.atg.datasource.handler.*;//import com.goldengate.atg.datasource.meta.DsMetaData;//import com.goldengate.atg.datasource.test.DsTestUtils.Logger;//import com.goldengate.atg.datasource.meta.*;//import com.goldengate.atg.datasource.*;//這是 OGG 12 的 import import org.slf4j.Logger;import org.slf4j.LoggerFactory;import oracle.goldengate.datasource.AbstractHandler;import oracle.goldengate.datasource.DsColumn;import oracle.goldengate.datasource.DsConfiguration;import oracle.goldengate.datasource.DsEvent;import oracle.goldengate.datasource.DsOperation;import oracle.goldengate.datasource.DsOperation.OpType;import oracle.goldengate.datasource.DsTransaction;import oracle.goldengate.datasource.GGTranID;import oracle.goldengate.datasource.meta.ColumnMetaData;import oracle.goldengate.datasource.meta.DsMetaData;import oracle.goldengate.datasource.meta.TableMetaData;import oracle.goldengate.datasource.meta.TableName;import oracle.goldengate.datasource.GGDataSource.Status;public class SampleHandler extends AbstractHandler {        //OGG 11 和 OGG 12 的 日誌好像不一樣, OGG 12 似乎要寫 LoggerFactory.getLogger(SampleHandler.class);    //private final Logger logger = Log4jLogger.getLogger(SampleHandler.class);    private final Logger logger = LoggerFactory.getLogger(SampleHandler.class);    @Override    public void init(DsConfiguration conf, DsMetaData metaData) {        super.init(conf,  metaData);        logger.info("init!");        WriteStringToFile("D:\\SampleHandler.log", "SampleHandler.init(*)");    }    @Override    public Status transactionCommit(DsEvent e, DsTransaction tx) {//      DsMetaData meta = e.getMetaData();//      //System.out.println(meta);//      //      Set<TableName> tableNames = meta.getTableNames();//      for(TableName tableName : tableNames){//          String tableStr = "";//          tableStr = tableStr + tableName+" : ";////          TableMetaData metaData = meta.getTableMetaData(tableName);//          ArrayList<ColumnMetaData> columns = metaData.getColumnMetaData();//          for(ColumnMetaData column : columns){               //              tableStr = tableStr + "\r\n   " + column.getColumnName() + " | "+column.getDataType().toString();//          }//          //          System.out.println(tableStr+"\r\n");            //          //System.out.println(metaData);//      }//      //        //GGTranID tranId = e.getTargetCheckpointInfo();//        //System.out.println(tranId);//      //      System.out.println(tx.getSize());//      System.out.println(tx.getTotalOps());//      System.out.println(tx.getReadTime());//      System.out.println(tx.getTransactionBeginTime());//      //      //      Object eventSource = e.getEventSource();//      System.out.println(eventSource);//      //      DsOperation lastOp = tx.getLastOperation();//      System.out.println(lastOp);//      //      //      List<DsOperation> listOp = tx.getOperations();//      System.out.println(listOp.size());//      //System.out.println(listOp.get(0).getColumn(0).getBeforeValue());//      for(DsOperation op : listOp){//          System.out.println(op.getTableName());//      }        Status  superResult = super.transactionCommit(e, tx);        logger.info("transactionCommit!");        WriteStringToFile("D:\\SampleHandler.log", "SampleHandler.transactionCommit(*) => "+superResult);         return superResult;    }    @Override    public Status operationAdded(DsEvent e, DsTransaction tx, DsOperation dsOperation) {        DsMetaData meta = e.getMetaData();        //System.out.println(meta);//      Set<TableName> tableNames = meta.getTableNames();//      for(TableName tableName : tableNames){//          String tableStr = "";//          tableStr = tableStr + tableName+" : ";////          TableMetaData metaData = meta.getTableMetaData(tableName);//          ArrayList<ColumnMetaData> columns = metaData.getColumnMetaData();//          for(ColumnMetaData column : columns){               //              tableStr = tableStr + "\r\n   " + column.getColumnName() + " | "+column.getDataType().toString();//          }//          //          System.out.println(tableStr+"\r\n");            //          //System.out.println(metaData);//      }        System.out.println("---------------------------------------");        OpType opType = dsOperation.getOperationType();        System.out.println(opType);        TableName tableName = dsOperation.getTableName();        System.out.println(tableName.getFullName());        TableMetaData metaData = meta.getTableMetaData(tableName);        ArrayList<ColumnMetaData> columnMetas = metaData.getColumnMetaData();        List<DsColumn> columns = dsOperation.getColumns();        for(int i=0; i<columnMetas.size(); i++){                            ColumnMetaData columnMeta = columnMetas.get(i);            DsColumn column = columns.get(i);            System.out.println("    " + columnMeta.getColumnName() + "\t | \t"+ column.getAfterValue() + (column.isChanged()? "\t >>> \t" +column.getAfterValue():""));        }        System.out.println("---------------------------------------");        Status superResult = super.operationAdded(e, tx, dsOperation);        logger.info("operationAdded!");        WriteStringToFile("D:\\SampleHandler.log", "SampleHandler.operationAdded(*) => "+superResult);         return superResult;    }    //@Override      //public DataSourceListener.State   getState() {    //  return super.getState();    //}    @Override    public void destroy() {        super.destroy();        WriteStringToFile("D:\\SampleHandler.log", "SampleHandler.destroy(*)");         logger.info("destroy!");    }    @Override    public String reportStatus() {        String superResult = "OK"; //super.reportStatus(); 調用父類函數,程式就會崩潰。        WriteStringToFile("D:\\SampleHandler.log", "SampleHandler.reportStatus(*) => "+superResult);        return superResult;        //return "status report...===";    }      public static void WriteStringToFile(String filePath, String text) {           try {                 System.out.println("AAAAAAAAAAAAAAAAA :" + text);             FileWriter writer = new FileWriter(filePath, true);                 writer.write("\r\n"+text);                   writer.close();             } catch (IOException e) {                 //e.printStackTrace();              System.out.println(e.getMessage());         }     }     }//---------------------------------------------------------------------------------------

至此,OGG 兩大目標 全部完成。幾乎把能踩的坑都踩了一遍。

雖然,我會再寫一篇文章 《OGG Adapter Java一次性成功》

—— 但是,不要想太多:你還是得乖乖的回到 這篇文章,學習如何從坑中逃出來。

—— 此篇OGG踩坑文章,踩的各種坑 不下十幾種,從配置到代碼、從編碼格式到反斜線,從版本到位元,從環境變數到筆誤。

—— 作者著實不容易。

最後還是以一首打油詩結尾:現代詩:《OGG的迷惘》

那一刻,

晶瑩的淚水滑過臉龐,

我似乎,

看到了成功的希望。

蹉跎與掙紮,

糾結與迷惘。

在折騰中,我終究能走向想要的遠方。

—— 再給我一次機會,讓我再配置一次OGG。

—— 不!我選擇 死亡(罵娘)~

打油詩:《神坑OGG》

神坑最多OGG,

坑得勞資沒脾氣。

坑得勞資沒脾氣~

神坑最多OGG~

兩首詩把 OGG 批了一頓,還能怎樣呢?當然是選擇 原諒他啊。

舒小龍 2018-05-31 20:02

『OGG 02』Win7 配置 Oracle GoldenGate Adapter Java 踩坑指南

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.