安裝Oracle:
安裝 Oracle_11g 32位【Oracle 32位的話,OGG 也必須是 32位,否則會有0xc000007b無法正常啟動 錯誤】
安裝目錄為 D:\oracle\product\11.1.0\db1 【這個目錄要設置為 環境變量 ORACLEHOME】
設置環境變量:
JAVAHOME C:\Program Files\Java\jdk1.8.0121
ORACLEHOME D:\oracle\product\11.1.0\db1
ORACLE_SID ORCL
驗證環境變量:
獲取 ORACLESID : 打開 SQLPlus,登錄 SYS 賬戶,執行 select instancename from v$instance;
獲取 ORACLEHOME : 查找 Oracle安裝目錄,這個目錄有個特征:有一個子目錄名叫 RDBMS。就是說: %ORACLEHOME%\RDBMS\ 這個路徑要能正常打開即為配置成功。
Oracle數據庫創建用戶,授予 DBA權限
略(參見 《__Win7 配置 Oracle GoldenGate 踩坑指南》中的配置)
Oracle啟用日志存檔模式
略(參見 《__Win7 配置 Oracle GoldenGate 踩坑指南》中的配置)
安裝 OGG
安裝 32位的 OGG 11.1,用於數據庫之間的 同步 (和 Oracle 數據庫版本、位數一致)
安裝 64位的 OGG Adapter Java 12,用於Java程序適配(11.1 的版本會崩潰)
安裝 64位的 JDK 1.8 (OGG Adapter Java 因為是64位的)
http://www.oracle.com/technetwork/cn/middleware/goldengate/downloads/index.html
拖到頁面最后面
搜索 需要下載的 OGG
單擊“購物車”,選擇需要下載的版本
點擊 右下角的 “下載”,把OGG文件 放到 D盤
先說一下目標:
Oracle 數據庫中 有 兩個用戶(結構) ADMIN 和
每個用戶(結構) 都有結構完全一樣的 表: TB_TEST
目標1:我們要配置OGG,當 ADMIN.TBTEST 的數據變化時,ROOT.TBTEST 能自動同步這種變化(實現容災備份)
目標2:我們要配置OGG,當 ADMIN.TB_TEST 的數據變化時,Java程序可以捕獲到這種變化。
部署 OGG
上面4個目錄的意思:
dirdat 目標端的 Trail 文件目錄
s 源端(ADMIN.TB_TEST 的OGG服務,數據抽取)
t 目標端(ROOT.TB_TEST 的 OGG服務,數據備份)
javaue 目標端(從 D:\dirdat\ 中,將 Trail文件變化 交給Java程序處理)
編輯配置
源端配置:一個管理服務、兩個抽取進程
ext1.prm
extract ext1
userid admin,password oracle
rmthost 127.0.0.1, mgrport 7909
rmttrail D:/ogg/dirdat/r1
grouptransops 1
maxtransops 1
flushsecs 0
eofdelay 0
dynamicresolution
gettruncates
table admin.*;
ext2
extract ext2
userid admin,password oracle
rmthost 127.0.0.1, mgrport 7909
rmttrail D:/ogg/dirdat/r2
grouptransops 1
maxtransops 1
flushsecs 0
eofdelay 0
dynamicresolution
gettruncates
table admin.*;
mgr.prm
PORT 7809
DYNAMICPORTLIST 7840-7850
目標端配置:一個管理服務、一個同步進程
rep1.prm
replicat rep1
userid root,password oracle
assumetargetdefs
reperror default,discard
grouptransops 1
maxtransops 1
discardfile D:/ogg/dirdat/repsz.dsc,append
map admin.*, target root.*;
mgr.prm
PORT 7909
DYNAMICPORTLIST 7940-7950
Javaue配置:一個管理服務、一個Javaue進程
javaue.prm
Extract JAVAUE
SetEnv (GGS_USEREXIT_CONF = "dirprm/javaue.properties")
SourceDefs dirprm/source.def
--getEnv (JAVA_HOME)
--getEnv (LD_LIBRARY_PATH_12) --邊境變量 LD_LIBRARY_PATH_12 指向的是 D:\ogg\javaue12\ggjava\resources\lib
--getEnv (PATH)
CUserExit ggjava_ue.dll CUSEREXIT PassThru IncludeUpdateBefores
GetUpdateBefores
-- NoCompressDeletes
-- NoCompressUpdates
Table ADMIN.*;
javaue.properties
### java.naming.provider.url=tcp://localhost:61616
### java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory
gg.handlerlist=sample
gg.handler.sample.type=sample.SampleHandler
# com.goldengate.atg.datasource.handler.ConsoleHandler
goldengate.userexit.timestamp=utc
goldengate.userexit.nochkpt=true
goldengate.userexit.writers=javawriter
goldengate.log.logname=cuserexit
goldengate.log.level=INFO
goldengate.log.tofile=true
javawriter.stats.display=TRUE
javawriter.stats.full=TRUE
# javaue.prm 我們之所以注釋掉了 getEnv (LD_LIBRARY_PATH_12) 是因為:我們手動把路徑配置在了下面代碼中
javawriter.bootoptions=-Djava.class.path=.;dirprm;ggjava/resources/classes;ggjava/resources/lib;ggjava/ggjava.jar;dirprm/fastjson-1.2.7.jar;dirprm/custom.jar -Dlog4j.configuration=log4j.properties
mgr.prm
PORT 7509
DYNAMICPORTLIST 7540-7550
生成 source.def 文件(Javaue 運行需要)
在 D:\Temp\創建一個 source.prm 文件
D:\Temp\source.prm
defsfile D:\Temp\source.def, purge
userid admin,password oracle
table admin.*;
運行命令行:
用Eclipse 編寫Java插件:
打開 Eclipse 新建“Java項目”custom12,新建一個包 sample,新建一個類 SampleHandler.java 將如下代碼 復制到 SampleHandler.java 中
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());
}
}
}
*下面截圖的包名 sample 錯寫成了 simple *
添加外部jar包引用,具體包括
ggjava\ggjava.jar
ggjava\resources\lib 目錄下的全部 jar 包
至此,OGG整個配置環節,需要准備的 文件都已經准備完成,接下來准備啟動 OGG。
啟動源端OGG:
啟動源端OGG:
進入 D:\ogg\s\ 目錄,雙擊 ggsci.exe,運行如下命令
> create subdirs
> dblogin userid admin,password oracle
> add trandata admin.*
> add extract ext1, tranlog, begin now
> add rmttrail D:/ogg/dirdat/r1 extract ext1
> add extract ext2, tranlog, begin now
> add rmttrail D:/ogg/dirdat/r2 extract ext2
> start mgr
> start ext1
> start ext2
啟動目標端OGG:
進入 D:\ogg\t\ 目錄,雙擊 ggsci.exe,運行如下命令
> create subdirs
> add replicat rep1 exttrail D:/ogg/dirdat/r1, nodbcheckpoint
> start mgr
> start rep1
驗證 源端>目標端 的同步:
如果 ext1 ext2 因為 rep1 沒有啟動而自動停止,則需要 重新啟動一次 源端的 ext1 ext2
我們向 ADMIN.TBTEST 插入一行記錄,理論上 ROOT.TBTEST 也會對應的 同步一行記錄
啟動OGG Javaue:
進入 D:\ogg\javaue12\ 目錄,雙擊 ggsci.exe,運行如下命令
最后的話:
至此:OGG(Oracle GoldenGate)同步配置 和 Adaper Java 程序適配 已經全部完成。
建議:嚴格按照上面的步驟,所有名稱 都盡量不要變化 —— 先把第一次 全部跑通。
等全部跑通后,你再試着修改 其中的 各個部分的名稱 —— 對照 prm 文件配置,試着理解 OGG配置原理。
如果配置過程中,出現任何詭異BUG,
歡迎參考
《__Win7 配置 Oracle GoldenGate 踩坑指南》 和 《__Win7 配置 Oracle GoldenGate Adapter Java 踩坑指南》 兩篇踩坑文章。
—— 事實上,OGG配置的坑很多,總有一款適合你,兩篇《踩坑指南》 你逃不掉的。
舒小龍 2018-06-04