天天看點

Oracle GoldenGate Oracle—Oracle 雙向複制

Oracle GoldenGate支援兩種雙向複制配置,一種是active-passive模式,這種模式一般被用來實作live standby,做主備庫,還有一種是active-active模式,這種模式被用來實作HA高可用、分攤負載壓力。

Active-passive for a live standby

首先先介紹一下active-passive模式的部署以及主備庫的切換。配置active-passive模式的目的是為了主庫因計劃和非計劃的中斷後可以失敗轉移到一個完整複制主庫資料的備份資料庫上,業務架構如下:

在這種配置中,備庫擁有一個不活動的Extract group和一個data pump。這些程序組在使用者應用因switchover或failover切換到這個live standby系統前都應保持stopped狀态。當使用者活動切換到standby時,這些程序組開始捕獲事務并将其寫入到本地的trail中,這些資料存儲在磁盤上直到主庫恢複使用。

在主庫失敗的案例中,Oracle GoldenGate的Manager和Replicat程序與一個資料庫協同工作,在主系統恢複後從備庫将資料恢複到主庫,使兩個系統相等。在适當的時候,将使用者移回主系統,Oracle GoldenGate再一次被配置為準備模式,以準備将來的failover。

配置一個live standby需要考慮以下問題:

Duplicate standby

在大多數的live standby的實作中,備庫與主庫的内容和結構應該是相同的,data mapping、conversion和filtering在這種配置中是不合适的,但是如果你的業務模型要求的話,Oracle GoldenGate也是支援這些功能的,使用MAP和TABLE參數選項可以實作這些功能。

備用系統上的DML操作

如果你的應用允許,你可以将live standby用作保镖和查詢,但是不要有DML操作。如果在live standby系統上會有活動的事務應用影響對象的話,你應該把它配置為active-active模式。

Oracle GoldenGate processes

在普通的操作模式下,你應該讓live standby上的primary extract程序和data pump保持stopped狀态,讓active source上的replicat程序保持stopped狀态。這防止了任何偶爾發生在備用系統上的DML操作被傳播到active source。隻有将資料從active source傳送到standby的Extract程序、data pump程序和replicat程序是被激活的。

備份檔案

定期備份主系統和備用系統的Oracle GoldenGate工作目錄。這個備份必須包含Oracle GodenGate安裝目錄下的所有檔案以及所有的子目錄。有了這個Oracle GoldenGate環境的備份意味着你不需要再去重建程序組和參數檔案。

為Failover做好準備

請確定在一個計劃的switchover或者非計劃的source failure事件中主備系統能夠立即通路。以下的一些高可用計劃的元件應便于每台系統可供使用:

賦予insert、update和delete權限的腳本

啟用live standby上trigger和cascaded delete的腳本

切換應用服務、啟動應用和複制不在複制環境中複制的必要的檔案的腳本

一個當source系統發生故障後移動使用者到備用系統的故障轉移過程

由資料庫生成的序列值

如果由資料庫生成的值作為鍵值的一部分,那麼這個值在每台系統上的範圍必須為不同以使其沒有機會重疊。如果應用允許,你也可以為這個值添加一個本地辨別以強制其唯一。

對于Oracle資料庫,你可以通過配置Oracle GoldenGate使其複制sequence來確定其在每個系統上唯一。使用SEQUENCE和MAP參數來複制SEQUENCE。

Oracle GoldenGate配置live standby的原理架構圖:

配置active-passive模式其實就是在原先單向複制的基礎上在target端建立一個extract和data pump指向source,而在source上建立一個replicat執行target傳過來的trail的應用,隻是這些程序組不啟動而已。配置單向複制的方法請參照我的另一篇文章Goldengate Oracle–Oracle 單向複制Change Synchronization安裝部署,要注意的是source端由于要複制,是以也同樣需要建立checkpointtable,而target端由于要作為今後的source端進行挖掘,是以它也需要啟用DDL支援,但是ddl_enable.sql和ddl_pin.sql不需要執行,而在切換為source時再執行,因為作為target端目前還不需要捕獲ddl操作,source建立checkpointtable和target啟用ddl支援需要在配置初期完成,不能待完成單向複制配置後再回過頭來在source端建立checkpointtable,因為有DDL複制,是以在source建立checkpointtable後會傳播到target,而target已存在相同的表,這會導緻複制報錯,replicat會abend,如果使用不同的表名則不會報錯,當然也可以在replicat用ddlerror 955 ignore參數來處理忽略這個錯誤,955是error号,ignore表示忽略它。

Switchover–

在配置完active-passive模式後我們嘗試進行switchover,目前source端與target端的OGG下的程序狀态如下:

source端

[email protected] ogg]$ ggsci

Oracle GoldenGate Command Interpreter for Oracle

Version 11.2.1.0.14 17547423 OGGCORE_11.2.1.0.0OGGBP_PLATFORMS_131022.0605_FBO

Linux, x64, 64bit (optimized), Oracle 11g on Oct 22 2013 11:03:39

Copyright (C) 1995, 2013, Oracle and/or its affiliates. All rights reserved.

GGSCI (gc.yxd.com) 1> info all

Program Status Group Lag at Chkpt Time Since Chkpt

MANAGER RUNNING

EXTRACT RUNNING EXT1 00:00:05 00:00:00

EXTRACT RUNNING PUMP1 00:00:00 00:00:05

REPLICAT STOPPED REP1 00:00:00 00:04:38

target端

[[email protected] ogg]$ ggsci

Oracle GoldenGate Command Interpreter for Oracle

Version 11.2.1.0.14 17547423 OGGCORE_11.2.1.0.0OGGBP_PLATFORMS_131022.0605_FBO

Linux, x64, 64bit (optimized), Oracle 11g on Oct 22 2013 11:03:39

Copyright (C) 1995, 2013, Oracle and/or its affiliates. All rights reserved.

GGSCI (gc2.yxd.com) 1> info all

Program Status Group Lag at Chkpt Time Since Chkpt

MANAGER RUNNING

EXTRACT STOPPED EXT1 00:00:00 00:19:31

EXTRACT STOPPED PUMP1 00:00:00 00:07:13

REPLICAT RUNNING REP1 00:00:00 00:00:05

1. source端停止使用者應用,但是保持extract與data pump運作以捕獲積壓的資料。

2. source端釋出lag extract ext1確定捕獲完成。

GGSCI (gc.yxd.com) 2> lag extract ext1

Sending GETLAG request to EXTRACT EXT1 …

Last record lag: 8 seconds.

3. source停止extract

GGSCI (gc.yxd.com) 7> stop extract ext1

Sending STOP request to EXTRACT EXT1 …

Request processed.

GGSCI (gc.yxd.com) 8> info all

Program Status Group Lag at Chkpt Time Since Chkpt

MANAGER RUNNING

EXTRACT STOPPED EXT1 00:00:05 00:00:08

EXTRACT RUNNING PUMP1 00:00:00 00:00:09

REPLICAT STOPPED REP1 00:00:00 00:10:51

4. source禁用trigger和cascaded delete(如果有的話),收回使用者的insert、update和delete權限

[[email protected] ~]$ cd /ogg/

[[email protected] ogg]$ sqlplus ogg/000000 as sysdba

SQL*Plus: Release 11.2.0.4.0 Production on Fri Nov 29 15:44:01 2013

Copyright (c) 1982, 2013, Oracle. All rights reserved.

Connected to:

Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 – 64bit Production

With the Partitioning, OLAP, Data Mining and Real Application Testing options

SQL> @ddl_disable.sql

Trigger altered.

SQL> revoke resource from yxd;

Revoke succeeded.

5. source端釋出lag extract pump1,直到出現“At EOF, no more records to process.”表明捕獲的資料都已經發送到target了。

GGSCI (gc.yxd.com) 9> lag extract pump1

Sending GETLAG request to EXTRACT PUMP1 …

Last record lag: 8 seconds.

At EOF, no more records to process.

6. source端停止pump1

GGSCI (gc.yxd.com) 10> stop pump1

Sending STOP request to EXTRACT PUMP1 …

Request processed.

GGSCI (gc.yxd.com) 11> info all

Program Status Group Lag at Chkpt Time Since Chkpt

MANAGER RUNNING

EXTRACT STOPPED EXT1 00:00:05 00:04:11

EXTRACT STOPPED PUMP1 00:00:00 00:00:03

REPLICAT STOPPED REP1 00:00:00 00:14:54

7. target釋出lage replicat rep1,直到出現“At EOF, no more records to process.”表明資料都已被應用

GGSCI (gc2.yxd.com) 3> lag replicat rep1

Sending GETLAG request to REPLICAT REP1 …

Last record lag: 10 seconds.

At EOF, no more records to process.

8. target停止replicat

GGSCI (gc2.yxd.com) 4> stop rep1

Sending STOP request to REPLICAT REP1 …

Request processed.

GGSCI (gc2.yxd.com) 5> info all

Program Status Group Lag at Chkpt Time Since Chkpt

MANAGER RUNNING

EXTRACT STOPPED EXT1 00:00:00 00:34:16

EXTRACT STOPPED PUMP1 00:00:00 00:21:58

REPLICAT STOPPED REP1 00:00:00 00:00:03

9. target端運作賦予使用者insert、update、delete權限的腳本,啟用trigger和cascaded delete的腳本。

[[email protected] ogg]$ sqlplus ogg/000000 as sysdba

SQL*Plus: Release 11.2.0.4.0 Production on Fri Nov 29 15:46:48 2013

Copyright (c) 1982, 2013, Oracle. All rights reserved.

Connected to:

Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 – 64bit Production

With the Partitioning, OLAP, Data Mining and Real Application Testing options

SQL> @ddl_enable.sql

Trigger altered.

SQL> @ddl_pin.sql ogg

PL/SQL procedure successfully completed.

PL/SQL procedure successfully completed.

PL/SQL procedure successfully completed.

SSQL> grant resource to yxd;

Grant succeeded.

10. 拷貝不在複制環境中複制的檔案到target live standby

11. 修改target的extract ext1為begin now,讓他從現在這個時間點開始挖據

GGSCI (gc2.yxd.com) 6> alter extract ext1,begin now

EXTRACT altered.

12. 啟動target的extract ext1

GGSCI (gc2.yxd.com) 7> start ext1

Sending START request to MANAGER …

EXTRACT EXT1 starting

GGSCI (gc2.yxd.com) 8> info all

Program Status Group Lag at Chkpt Time Since Chkpt

MANAGER RUNNING

EXTRACT RUNNING EXT1 00:00:10 00:00:08

EXTRACT STOPPED PUMP1 00:00:00 00:37:07

REPLICAT STOPPED REP1 00:00:00 00:15:12

13. 啟動target的extract pump1

GGSCI (gc2.yxd.com) 12> start pump1

Sending START request to MANAGER …

EXTRACT PUMP1 starting

GGSCI (gc2.yxd.com) 13> info all

Program Status Group Lag at Chkpt Time Since Chkpt

MANAGER RUNNING

EXTRACT RUNNING EXT1 00:00:03 00:00:02

EXTRACT RUNNING PUMP1 00:00:00 00:39:01

REPLICAT STOPPED REP1 00:00:00 00:17:06

GGSCI (gc2.yxd.com) 14> info all

Program Status Group Lag at Chkpt Time Since Chkpt

MANAGER RUNNING

EXTRACT RUNNING EXT1 00:00:03 00:00:05

EXTRACT RUNNING PUMP1 00:00:00 00:39:04

REPLICAT STOPPED REP1 00:00:00 00:17:09

GGSCI (gc2.yxd.com) 15> info all

Program Status Group Lag at Chkpt Time Since Chkpt

MANAGER RUNNING

EXTRACT RUNNING EXT1 00:00:03 00:00:07

EXTRACT RUNNING PUMP1 00:00:00 00:39:06

REPLICAT STOPPED REP1 00:00:00 00:17:11

GGSCI (gc2.yxd.com) 16> info all

Program Status Group Lag at Chkpt Time Since Chkpt

MANAGER RUNNING

EXTRACT RUNNING EXT1 00:00:03 00:00:09

EXTRACT RUNNING PUMP1 00:00:00 00:00:00

REPLICAT STOPPED REP1 00:00:00 00:17:13

14. source端啟動replicat rep1開始複制

GGSCI (gc.yxd.com) 14> start rep1

Sending START request to MANAGER …

REPLICAT REP1 starting

GGSCI (gc.yxd.com) 15> info all

Program Status Group Lag at Chkpt Time Since Chkpt

MANAGER RUNNING

EXTRACT STOPPED EXT1 00:00:05 00:28:55

EXTRACT STOPPED PUMP1 00:00:00 00:24:47

REPLICAT RUNNING REP1 00:00:00 00:00:02

15. 切換應用服務,啟動應用,移動使用者到target端,切換完成。

16. 測試target端同步資料到source

target端建立表、插入資料、使用sequence

[[email protected] ogg]$ cd

[[email protected] ~]$ sqlplus yxd/000000

SQL*Plus: Release 11.2.0.4.0 Production on Fri Nov 29 16:02:12 2013

Copyright (c) 1982, 2013, Oracle. All rights reserved.

Connected to:

Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 – 64bit Production

With the Partitioning, OLAP, Data Mining and Real Application Testing options

SQL> create table oo (id number,name varchar2(20));

Table created.

SQL> insert into oo values(33,'sdfsdf');

1 row created.

SQL> /

1 row created.

SQL> /

1 row created.

SQL> /

1 row created.

SQL> /

1 row created.

SQL> commit;

Commit complete.

SQL> select * from oo;

        ID NAME

———- —————————————-

        33 sdfsdf

        33 sdfsdf

        33 sdfsdf

        33 sdfsdf

        33 sdfsdf

SQL> select * from tab;

TNAME TABTYPE

———————————————————— ————–

 CLUSTERID

———-

II TABLE

KK TABLE

OO TABLE

TNAME TABTYPE

———————————————————— ————–

 CLUSTERID

———-

TT TABLE

XX TABLE

SQL> select seq.nextval from dual;

   NEXTVAL

———-

        15

SQL> /

   NEXTVAL

———-

        16

SQL> /

   NEXTVAL

———-

        17

SQL> /

   NEXTVAL

———-

        18

SQL> select last_number from user_sequences;

LAST_NUMBER

———–

         19

檢視source端是否資料同步

[[email protected] ogg]$ sqlplus yxd/000000

SQL*Plus: Release 11.2.0.4.0 Production on Fri Nov 29 16:05:30 2013

Copyright (c) 1982, 2013, Oracle. All rights reserved.

Connected to:

Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 – 64bit Production

With the Partitioning, OLAP, Data Mining and Real Application Testing options

SQL> select * from oo;

        ID NAME

———- —————————————-

        33 sdfsdf

        33 sdfsdf

        33 sdfsdf

        33 sdfsdf

        33 sdfsdf

SQL> select * from tab;

TNAME TABTYPE

———————————————————— ————–

 CLUSTERID

———-

II TABLE

KK TABLE

OO TABLE

TNAME TABTYPE

———————————————————— ————–

 CLUSTERID

———-

TT TABLE

XX TABLE

SQL> select last_number from user_sequences;

LAST_NUMBER

———–

         19

資料完全一緻,同步成功,要切換回去使用相同的步驟即可。

Failover–

Failover由于source失敗已經不可用,是以對與source的步驟也就沒有了,使用switchover中的步驟7-13以及步驟15即可完成failover。

Active-Active for high availability

Active-Active模式通常用來解決一些分攤負載提高高可用性的需求,這種配置在兩個系統上擁有相同的資料集,并且應用使用者可以在任意一台機器上進行資料更改。Oracle GoldenGate複制每一台的事務資料變化到其他的節點來保持所有的資料集一緻。

在這種雙向配置中,在每一台系統上都有一個完整的激活的Oracle GoldenGate程序組集合。在一台系統上由Extract程序捕獲的資料會傳播到其他系統上用作Replicat的複制應用。

這種配置可以支援負載共享,它可以用作容災如果每個節點的業務應用是一緻的話。雙向同步支援所有Oracle GoldenGate所支援的資料庫類型。

Active-Active同步的實作原理與架構圖:

從架構上可以看出Active-Active模式與Active-Passive模式的差別隻在于在兩個系統上的所有的extract、data pump和replicat程序都是激活的,是以它在架設上與Active-Passive相似,無非是将所有的程序都開啟而已,具體的配置不再過多讨論。由于兩邊都可以修改資料庫,是以必定會有一些沖突的問題産生,下面着重了解一下可能産生的沖突與解決方法。

TRUNCATES–

在這個配置中TRUNCATE的複制是不支援的,但是你可以配置這些操作總是向一個方向複制,而資料是雙向複制的。在Active-Active配置中,TRUNCATE必須隻能從一個源資料庫發起,并且每次都隻能是同一個資料庫。

你需要按照以下來配置環境:

配置所有的資料庫角色無法執行TRUNCATE操作,除了那台用作TRUNCATE源的資料庫。

在允許TRUNCATE的系統上,配置Extract和Replicat參數檔案去包含GETTRUNCATES參數。

在其他系統上,配置Extract和Replicat參數檔案去包含IGNORETRUNCATES參數。作為Oracle GoldenGate配置的一部分,在這些系統上的應用不應該執行TRUNCATE操作。

DDL–

在Active-Active配置中,DDL的複制是支援的。

應用的設計–

Active-Active配置不建議使用商業化可用的已打包了的業務應用,除非這些應用是為Active-Active配置設計的。這些應用可能會出現以下障礙:

已打包的應用可能會包含Oracle GoldenGate不支援的對象和資料類型。

這些應用可能會自動執行一些你不能控制的DML操作,當這些操作被複制給Replicat應用時可能會導緻沖突。

你可能無法控制資料結構修改它以達到Active-Active複制的要求。

鍵–

為了準确的偵測沖突,所有的記錄應該有一個唯一的、非空的辨別。如果可能,建立一個主鍵,如果不可能就建立一個唯一鍵或者使用MAP和TABLE參數中的KELCOL選項來建立一個替代鍵。如果缺失了這個唯一鍵,那麼Oracle GoldenGate将使用WHERE子句中所有有效的字段,但是這會降低性能如果這個表包含很多字段的話。

為了維護資料的完整性和防止error發生,你使用的所有給出的表的鍵必須要滿足以下條件:

在所有駐留的資料庫中這張表必須包含相同的字段。

在所有資料庫中每個相應行的集合的值必須相同。

Triggers and cascaded deletes–

由Trigger和ON DELETE CASCADE限制産生的DML操作是能夠被複制的。為了防止本地的DML與由這些操作複制的DML沖突,你需要做以下事:

修改Trigger,忽略由複制應用的DML操作。對于某些Oracle資料庫版本,你可以使用DBOPTIONS參數的SUPPRESSTRIGGERS選項來禁止複制會話的trigger。

禁用ON DELETE CASCADE限制而使用父表上的trigger去執行删除子表資料的要求。建立一個BEFORE trigger用來在父表執行删除前删除子表。這反轉了級聯删除的邏輯規則,但是對于避免在target端由複制操作而産生“table not found”錯誤是很有必要的。

Database-generated values–

在active-active的雙向複制中不要複制資料庫生成的序列值,在active-passive模式中我們是通過複制sequence來實作序列一緻的,這樣在切換後序列值能夠延續下去,但是雙向複制是需要同時操作資料的,是以sequence是不能複制的,否則會引起沖突。我們需要讓序列在每個系統上的取值範圍必須是不同的以使他們不會重疊。例如:在兩個資料庫的環境中,你可以在一台系統上生成奇數值而另一個系統生成偶數值。對于一個多資料庫的環境,每一個key的起始值是不同的,增長的步長是系統個數,比如4個資料庫的環境,那麼每個資料庫上的起始值分别是1、2、3、4,步長為資料庫的總數4,那麼他們就沒有重疊的機會。由于沒有了重疊的機會,也不需要保持一緻,是以此時的sequence是可以被cache的。但是這種方法可能并不是對所有類型的應用或資料庫有效。如果應用允許,你可以添加一個本地辨別使其強制唯一。

沖突處理–

所有的系統上必須統一沖突處理規則用來處理當在分離的系統上的相同的資料集同時(或者幾乎同時)發生修改時的沖突。在active-active環境中,沖突應該立即被辨別并且盡可能自動的被處理,然而,不同的業務應用在這個領域會有他們自己的獨特的要求。Oracle GoldenGate對于insert、update和delete沖突提供内建的沖突處理支援。

防止資料環回–

在active-active雙向複制中,從一台系統複制到另一台系統的SQL改變必須防止被複制回第一台系統。否則,它會向前向後移動無限循環,例如:

1. 一個使用者應用在A系統上update了一行資料。

2. Extract從系統A提取這行資料然後發送到系統B。

3. Replicat在系統B上更新了這行資料。

4. 在系統B上的Extract提取了這行資料發送回系統A。

5. 這行資料第二次在系統A上被應用。

6. 這個會無限循環下去。

為了防止資料環回,你也許需要提供以下指令:

防止捕獲由Replicat程序産生的SQL操作,但是捕獲包含了在Extract參數檔案中指定的對象的由業務應用生成的SQL操作。

辨別本地Replicat事務,使Extract程序可以忽略它們。

防止捕獲Replicat操作–

依賴你使用的資料庫,你也許需要也許不需要提供明确的指令來防止Replicat操作的捕獲。

Teradata資料庫–

對于Teradata資料庫防止捕獲Replicat應用的SQL需要設定Replicat會話重寫複制。在根的Replicat的參數檔案中使用以下SQLEXEC:

SQLEXEC "SET SESSION OVERRIDE REPLICATION ON;"

SQLEXEC "COMMIT;"

這些SQLEXEC語句會在啟動時執行以自動設定Replicat會話。

其他資料庫–

其他資料庫使用以下參數防止不會Replicat産生的SQL操作:

GETAPPLOPS|IGNOREAPPLOPS:控制除去Extract程序寫到一個指定Trail或檔案中Replicat包含的内容外是否還包含了業務應用的資料操作。

GETREPLICATES|IGNOREREPLICATES:控制是否包含了Replicat産生的DML操作内容到Extract程序所寫的那個Trail或檔案中。

在啟動Extract程序前,要確定這些參數要麼不寫,要麼就設定GETAPPLOPS和IGNOREREPLICATES。

辨別Replicat事務–

配置Extract去識别Replicat事務,究竟哪些資料會被捕獲可以用以下指令:

DB2 on z/OS and LUW,在Extract參數檔案中使用以下參數來辨別複制使用者名:

TRANLOGOPTIONS EXCLUDEUSER <user name>

這個參數語句标記了所有由這個使用者座位複制事務産生的資料事務。這個使用者包含在事務記錄中由Extract讀取。

MySQL和NonStop SQL/MX,在Extract參數檔案中用以下參數語句來辨別Replicat checkpoint table的名字:

TRANLOGOPTIONS FILTERTABLE <table_name>

在每個事務的終點,Replicat寫一個checkpoint到checkpoint表座位它的checkpoint過程的一部分(這個表就是用ADD CHECKPOINTTABLE指令建立的那個)。因為每一個複制事務要寫這張表,它能夠在active-active雙向複制中用來識别複制事務。FILTERTABLE辨別了checkpoint table的名字,以至于Extract能夠忽略這張表上的任何操作。

Oracle資料庫使用以下的一種語句來辨別Replicat使用者。所有的由這個使用者生成的事務将被捕獲忽略。在事務記錄中的這些資訊對Extract是有效地。

在Extract參數檔案中使用以下參數通過名稱來辨別Replicat資料庫使用者:

TRANLOGOPTIONS EXCLUDEUSER <user name>

在Extract參數檔案中使用Oracle user-id(uid)在以下參數語句中來辨別Replicat資料庫使用者:

TRANLOGOPTIONS EXCLUDEUSERID <user-id>

Sqlserver中通過使用以下Extract參數檔案中的參數語句來辨別Replicat事務名:

TRANLOGOPTIONS EXCLUDETRANS <transaction name>

這個參數語句隻在Replicat事務名被定義為其他的名稱而不是預設的ggs_repl才被要求。

Sybase使用以下任意一種方式:

在Extract參數檔案中使用以下參數語句來辨別一個Replicat事務名:

TRANLOGOPTIONS EXCLUDETRANS <transaction name>

在Extract參數檔案中使用以下參數語句來辨別一個Replicat使用者名:

TRANLOGOPTIONS EXCLUDEUSER <user name>

EXCLUDEUSER标記了所有由這個複制事務使用者生成的事務。這個使用者名包含在事務記錄中由Extract來讀取。

什麼都不做,并允許Replicat使用預設的事務名ggs_repl。

Teradata,你不需要去辨別應用到一個teradata資料庫的複制事務。

原文連結:http://www.knowwinter.com/2013/12/03/oracle-goldengate-oracle-mdash-oracle-shuang-xiang-fu-zhi/