手动冲突检测和解决
了解如何使用特定参数手动配置冲突检测和解决 (Conflict Detection and Resolution,CDR)。在主动 - 主动配置中,需要进行冲突检测和解决,Oracle GoldenGate 必须在包含相同数据集的多个数据库之间保持数据同步。
Oracle GoldenGate CDR 功能概览
Oracle GoldenGate 冲突检测和解决 (Conflict Detection and Resolution,CDR) 有两个部分:冲突检测和冲突解决。在开始解决冲突之前,必须进行调查并完成冲突检测。
Oracle GoldenGate 冲突检测和解决 (Conflict Detection and Resolution,CDR) 提供以下基本冲突解决例程:
-
解决
INSERT的唯一性冲突。 -
当行存在时,解决
UPDATE的“未找到数据”冲突,但一个或多个列的先前映像与数据库中的当前值不同。 -
当行不存在时,解决
UPDATE的“未找到数据”冲突。 -
当行存在时,解决
DELETE的“未找到数据”冲突,但一个或多个列的先前映像与数据库中的当前值不同。 -
当行不存在时,解决
DELETE的“未找到数据”冲突。
要使用冲突检测和解决 (CDR),目标数据库必须位于 Windows、Linux 或 UNIX 系统上。NonStop 平台上的数据库不支持该功能。
CDR 支持标量数据类型,例如:
-
NUMERIC -
BOOLEAN -
DATE -
TIMESTAMP -
CHAR/NCHAR -
VARCHAR/ NVARCHAR
这意味着这些列类型可以与 COMPARECOLS 参数一起使用,也可以作为 RESOLVECONFLICT 参数的 USEMIN 和 USEMAX 选项中的解析列。只能将 NUMERIC 列用于 RESOLVECONFLICT 的 USEDELTA 选项。对于 USEMAX、USEMIN,仅支持 TIMESTAMP 和 NUMBER。
当 Replicat 在 BATCHSQL 模式下运行时,不会执行冲突解决。如果在 BATCHSQL 模式下发生冲突,Replicat 将恢复为 GROUPTRANSOPS 模式,然后恢复为单事务模式。冲突检测在所有三种模式中发生。
配置 Oracle GoldenGate 参数文件以解决冲突
以下参数是支持冲突检测和解决的必需参数。
-
在 Replicat 参数文件中,使用
MAP参数的COMPARECOLS选项指定要与 ReplicatWHERE子句中的之前值一起使用的列。将前面值与目标数据库中的当前值进行比较,以检测更新和删除冲突。(默认情况下,复制仅使用WHERE子句中的主键;这可能不足以检测冲突)。 -
使用
MAP参数的RESOLVECONFLICT选项为不同的操作和冲突类型指定冲突解决例程。可以在MAP语句中多次使用RESOLVECONFLICT,以便为不同的冲突类型指定不同的解决方法。但是,不能多次将RESOLVECONFLICT用于同一类型的冲突。在所有数据库上使用相同的冲突解决过程,以便相同的冲突产生相同的最终结果。一种解决冲突的方法可能无法解决可能发生的每场冲突。您可能需要创建多个例程,这些例程可以按优先级的逻辑顺序进行调用,以便最大程度地降低失败的风险。
注:表具有主键和附加唯一索引或唯一键时,应考虑其他事项。随 COMPARECOLS 和 RESOLVECONFLICT 参数提供的自动化例程需要一种一致的方式来唯一标识每行。如果无法一致地标识行,则在解决冲突期间将导致错误。在这些情况下,应禁用其他唯一键,或者可以使用 SQLEXEC 功能来处理引发的错误并解决冲突。
有关这些参数的详细信息,请参阅 Parameters and Functions Reference for Oracle GoldenGate 。有关这些参数的更多信息,请参见 CDR Example 1:All Conflict Types with USEMAX,OVERWRITE,DISCARD 。
使必需的列值可供提取
要使用 CDR,必须记录以下列值,以便 Extract 可以将它们写入线索。
-
每个记录之前的完整图像。某些数据库在日志记录中未提供之前的映像,必须对其进行配置以使用补充日志记录。对于大多数支持的数据库,可以使用
ADD TRANDATA命令实现此目的。 -
使用
LOGALLSUPCOLS参数确保将调度列的映像之前和之后的完整映像写入线索。计划列是主键、唯一索引和外键列。LOGALLSUPCOLS使 Extract 在线索记录中包括UPDATE操作的之前映像和UPDATE和DELETE操作的所有补充记录的列的之前映像。
有关这些参数和命令的详细信息,请参见《 Parameters and Functions Reference for Oracle GoldenGate 》。有关这些参数如何与 CDR 配合使用的更多信息,请参见 CDR 示例 1:All Conflict Types with USEMAX,OVERWRITE,DISCARD 。
查看 CDR 统计信息
CDR 功能提供了以下方法来查看冲突解决结果。
下面是可用于查看 CDR 统计信息的不同技术。
报表文件
Replicat 将 CDR 统计信息写入到报告文件:
Total CDR conflicts 7
CDR resolutions succeeded 6
CDR resolutions failed 1
CDR INSERTROWEXISTS conflicts 1
CDR UPDATEROWEXISTS conflicts 4
CDR UPDATEROWMISSING conflicts
CDR DELETEROWEXISTS conflicts 1
CDR DELETEROWMISSING conflicts 1
命令行
通过使用带有 REPORTCDR 选项的 STATS REPLICAT 命令,可以从命令行查看 CDR 统计信息:
STATS REPLICAT *group*, REPORTCDR
列转换函数
可以检索以下 CDR 统计信息并将其映射到异常表,也可以在接受列转换函数输入的其它 Oracle GoldenGate 参数中使用。
-
检测到复制的冲突数
-
Replicat 解析的解析数
-
复制无法解析的解析数
要检索这些统计信息,请将 @GETENV 列转换函数与 STATS 或 DELTASTATS 信息类型结合使用。结果基于当前复制会话。如果 Replicat 停止并重新启动,则会重置统计信息。
可以为特定表或一组通配符表返回这些统计信息:
@GETENV ('STATS','TABLE','SCHEMA.TABLNAME','CDR_CONFLICTS')
@GETENV ('STATS','TABLE','SCHEMA.TABLNAME','CDR_RESOLUTIONS_SUCCEEDED')
@GETENV ('STATS','TABLE','SCHEMA.TABLNAME','CDR_RESOLUTIONS_FAILED')
可以为复制参数文件中的所有 MAP 语句中的所有表返回这些统计信息:
@GETENV ('STATS','CDR_CONFLICTS')
@GETENV ('STATS','CDR_RESOLUTIONS_SUCCEEDED')
@GETENV ('STATS','CDR_RESOLUTIONS_FAILED')
上述示例中的 'STATS' 信息类型可以替换为 'DELTASTATS',以返回自上次执行 'DELTASTATS' 以来的请求计数。有关 @GETENV 的更多信息,请参见 @GETENV
CDR 示例 1:使用 USEMAX、OVERWRITE 和 DISCARD 的所有冲突类型
此示例通过使用 USEMAX、OVERWRITE 和 DISCARD 解析来解决所有冲突类型。
本示例中使用的表
这些示例假定相同的 Oracle 数据库。
CREATE TABLE hr.emp_tgt(
name varchar2(30) primary key,
phone varchar2(10),
address varchar2(100),
salary number,
balance number,
comment varchar2(100),
last_mod_time timestamp);
在源数据库上,将补充记录所有列:
ADD TRANDATA hr.emp_src, COLS (name, phone, address, salary, balance, comment, last_mod_time);
具有冲突解决规范的 MAP 语句
MAP fin.src, TARGET fin.tgt,
COMPARECOLS (ON UPDATE ALL, ON DELETE ALL),
RESOLVECONFLICT (UPDATEROWEXISTS, (DEFAULT, USEMAX (last_mod_time)),
RESOLVECONFLICT (INSERTROWEXISTS, (DEFAULT, USEMAX (last_mod_time)),
RESOLVECONFLICT (DELETEROWEXISTS, (DEFAULT, OVERWRITE)),
RESOLVECONFLICT (UPDATEROWMISSING, (DEFAULT, OVERWRITE)),
RESOLVECONFLICT (DELETEROWMISSING, (DEFAULT, DISCARD)),
);
MAP 语句的说明
下面介绍了 MAP 语句:
-
根据
COMPARECOLS,使用复制WHERE子句中线索记录中所有列的上一个映像进行更新和删除。 -
根据
DEFAULT,将所有列用作所有冲突类型的列组;因此,解决方法适用于所有列。 -
对于
INSERTROWEXISTS冲突,请使用USEMAX解析:如果行在插入期间存在,请使用last_mod_time列作为解析列来确定哪个值更大:线索中的值或数据库中的值。如果线索中的值更大,则应用记录,但将插入更改为更新。如果数据库值较高,则忽略该记录。 -
对于
UPDATEROWEXISTS冲突,请使用USEMAX解析:如果行在更新期间存在,请使用last_mod_time列作为解析列:如果线索中的值更大,则应用更新。 -
如果使用
USEMIN或USEMAX,且值完全相同,则不会触发RESOLVECONFLICT,并且会忽略传入行。如果使用USEMINEQ或USEMAXEQ,且值完全相同,则会触发解析。 -
对于
DELETEROWEXISTS冲突,请使用OVERWRITE解决方法:如果删除操作期间存在该行,请应用删除。 -
对于
UPDATEROWMISSING冲突,请使用OVERWRITE解析:如果该行在更新期间不存在,请将更新更改为插入并应用它。 -
对于
DELETROWMISSING冲突,请使用DISCARD解决方法:如果删除操作期间该行不存在,则放弃线索记录。注:作为
USEMAX的替代方法,您可以使用USEMAXEQ解析来应用>=条件。有关详细信息,请参阅 Oracle GoldenGate 的参数和函数参考。
INSERTROWEXISTS 与 USEMAX 解析
对于此示例,USEMAX 分辨率以线索和数据库中记录的适用图像之前和之后进行说明。它显示如何解析行存在于源和目标中的插入,但某些或所有行值不同。
表 10:INSERTROWEXISTS 与 USEMAX 解析冲突
| 图像 | SQL | 备注 |
|---|---|---|
| 线索中的图像之前 | None (row was inserted on the source). |
不适用 |
| 在线索中图像后 | name='Mary' phone='1234567890' address='Oracle Pkwy' salary=100 balance=100 comment=NULL last_mod_time='9/1/10 3:00' |
|
| 目标数据库映像 | name='Mary' phone='111111' address='Ralston' salary=200 balance=500 comment='aaa' last_mod_time='9/1/10 1:00' |
last_mod_time='9/1/10 1:00 是目标中分辨率列的当前图像,用于比较线索中的分辨率列值。 |
检测冲突的复制应用初始 INSERT |
SQL 绑定的变量: 1)'Mary' 2)'1234567890' 3)'Oracle Pkwy' 4)100 5)100 6)NULL 7)'9/1/10 3:00' |
此 SQL 返回“Mary”上的唯一性冲突。 |
Replicat 应用 UPDATE 以解决冲突 |
SQL 绑定的变量: 1)'1234567890' 2)'Oracle Pkwy' 3)100 4)100 5)NULL 6)'9/1/10 3:00' 7)'Mary' 8)'9/1/10 3:00' |
由于为 INSERTROWEXISTS 指定了 USEMAX,因此 Replicat 会将插入转换为更新,并将线索记录中的 last_mod_time 值与数据库中的值进行比较。记录中的值更大,因此线索文件中列的后续图像将应用于目标。 |
UPDATEROWEXISTS 与 USEMAX 解析
对于此示例,USEMAX 分辨率以线索和数据库中记录的适用图像之前和之后进行说明。它显示如何解析行存在于源和目标中的更新,但某些或所有行值不同。
表 11 UPDATEROWEXISTS 与 USEMAX 解决方法冲突
| 图像 | SQL | 备注 |
|---|---|---|
| 线索中的图像之前 | name='Mary' phone='1234567890' address='Oracle Pkwy' salary=100 balance=100 comment=NULL last_mod_time='9/1/10 3:00' |
last_mod_time='9/1/10 3:00 是分辨率列的前一个图像。 |
| 在线索中图像后 | phone='222222' address='Holly' last_mod_time='9/1/10 5:00' |
last_mod_time='9/1/10 5:00 是分辨率列的后像。由于有后置图像,因此将用于确定分辨率。 |
| 目标数据库映像 | name='Mary' phone='1234567890' address='Oracle Pkwy' salary=100 balance=600 comment='com' last_mod_time='9/1/10 6:00' |
last_mod_time='9/1/10 6:00 是目标中分辨率列的当前图像,用于比较线索中的分辨率列值。 |
检测冲突的复制应用初始 UPDATE |
SQL 绑定的变量: 1)'222222' 2)'Holly' 3)'9/1/10 5:00' 4)'Mary' 5)'1234567890' 6)'Oracle Pkwy' 7)100 8)100 9)NULL 10)'9/1/10 3:00' |
此 SQL 返回一个未找到数据的错误,因为目标中 所有列都用在 |
Replicat 应用 UPDATE 以解决冲突 |
SQL 绑定的变量: 1)'Mary' 2)'222222' 3)'Holly' 4)100 5)100 6)NULL 7)'9/1/10 5:00' 8)'Mary' 9)'9/1/10 5:00' |
由于线索记录中 last_mod_time 的后值小于数据库中的当前值,因此将保留数据库值。Replicat 使用包含主键加上设置为小于 9/1/10 5:00 的 last_mod_time 值的 WHERE 子句应用该操作。没有符合此条件的行,因此该语句会失败并显示“data not found(未找到数据)”错误,但 Replicat 会忽略该错误,因为如果不满足条件,USEMAX 解析会失败。 |
通过覆盖解析实现更新权限
对于此示例,OVERWRITE 分辨率以线索和数据库中记录的适用图像之前和之后进行说明。它显示如何解决缺少目标行的情况。逻辑解析和使用的逻辑解析是将行覆盖到目标中,以便两个数据库再次同步。
表 12 UPDATEROWMISSING 与 OVERWRITE Resolution 的冲突
| 图像 | SQL | 备注 |
|---|---|---|
| 线索中的图像之前 | name='Jane' phone='333' address='Oracle Pkwy' salary=200 balance=200 comment=NULL last_mod_time='9/1/10 7:00' |
不适用 |
| 在线索中图像后 | phone='4444' address='Holly' last_mod_time='9/1/10 8:00' |
|
| 目标数据库映像 | None (row for Jane is missing) |
|
检测冲突的复制应用初始 UPDATE |
SQL 绑定的变量: 1)'4444' 2)'Holly' 3)'9/1/10 8:00' 4)'Jane' 5)'333' 6)'Oracle Pkwy' 7)200 8)200 9)NULL 10)'9/1/10 7:00' |
此 SQL 返回“no-data-found(未找到数据)”错误。所有列都用在 WHERE 子句中,因为 COMPARECOLS 语句设置为 ALL。 |
Replicat 应用 INSERT 以解决冲突 |
SQL 绑定的变量: 1)'Jane' 2)'4444' 3)'Holly' 4)200 5)200 6)NULL 7)'9/1/10 8:00' |
更新将转换为插入,因为 OVERWRITE 是分辨率。使用列的后图像(如果可用);否则使用之前的图像。 |
具有覆盖分辨率的 DELETEROWEXIST
对于此示例,OVERWRITE 分辨率以线索和数据库中记录的适用图像之前和之后进行说明。它显示如何解决删除来源行但目标行存在的情况。在这种情况下,OVERWRITE 解析会将删除应用于目标。
表 13 DELETEROWEXISTS 与 OVERWRITE 解析冲突
| 图像 | SQL | 备注 |
|---|---|---|
| 线索中的图像之前 | name='Mary' phone='222222' address='Holly' salary=100 balance=100 comment=NULL last_mod_time='9/1/10 5:00' |
不适用 |
| 在线索中图像后 | None |
不适用 |
| 目标数据库映像 | name='Mary' phone='1234567890' address='Oracle Pkwy' salary=100 balance=600 comment=com last_mod_time='9/1/10 7:00' |
该行存在于目标上,但是 phone、address、balance、comment 和 last_mod_time 列与线索中的前一图像不同。 |
检测冲突的复制应用初始 DELETE |
SQL 绑定的变量: 1)'Mary' 2)'222222' 3)'Holly' 4)100 5)100d 6)NULL 7)'9/1/10 5:00' |
所有列都用在 由于前值与当前值之间的差异,将出现“未找到数据”错误。 |
Replicat 应用 DELETE 以解决冲突 |
SQL 绑定的变量: 1)'Mary' |
因为 OVERWRITE 是解析。仅使用主键应用 DELETE(以避免完整性错误)。 |
使用 DISCARD 解析删除权限
对于此示例,DISCARD 分辨率以线索和数据库中记录的适用图像之前和之后进行说明。它显示如何解决缺少目标行的情况。对于源上的删除,目标行不存在是可以接受的(无论如何都需要将其删除),因此解决方法是放弃线索中的 DELETE 操作。
表 14 DELETEROWMSING 与 DISCARD Resolution 冲突
| 图像 | SQL | 备注 |
|---|---|---|
| 线索中的图像之前 | name='Jane' phone='4444' address='Holly' salary=200 balance=200 comment=NULL last_mod_time='9/1/10 8:00' |
不适用 |
| 在线索中图像后 | None |
不适用 |
| 目标数据库映像 | None (row missing) |
不适用 |
检测冲突的复制应用初始 DELETE |
SQL 绑定的变量: 1)'Jane' 2)'4444' 3)'Holly' 4)200 5)200 6)NULL 7)'9/1/10 8:00' |
此 SQL 返回“no-data-found(未找到数据)”错误。所有列都用在 WHERE 子句中,因为 COMPARECOLS 语句设置为 ALL。 |
| 复制应用 SQL 以解决冲突 | None |
因为 DISCARD 指定为 DELETEROWMISSING 的解析,所以从线索中删除将转至放弃文件。 |
CDR 示例 2:带有 USEDELTA 和 USEMAX 的 UPDATEROWEXISTS
此示例解析 UPDATE 上存在目标行但非键列不同的条件,并根据受影响的列使用两种不同的解析类型来处理此条件。
本示例中使用的表
这些示例假定相同的 Oracle 数据库。
CREATE TABLE tgt(
name varchar2(30) primary key,
phone varchar2(10),
address varchar2(100),
salary number,
balance number,
comment varchar2(100),
last_mod_time timestamp);
在源数据库上,将补充记录所有列:
ADD TRANDATA scott.src, COLS (name, phone, address, salary, balance, comment, last_mod_time);
MAP 语句
MAP fin.src, TARGET fin.tgt,
COMPARECOLS
(ON UPDATE KEYINCLUDING (address, phone, salary, last_mod_time),
ON DELETE KEYINCLUDING (address, phone, salary, last_mod_time)),
RESOLVECONFLICT (
UPDATEROWEXISTS,
(delta_res_method, USEDELTA, COLS (salary)),
(DEFAULT, USEMAX (last_mod_time)));
MAP 语句的说明
对于 UPDATEROWEXISTS 冲突,如果目标行存在于 UPDATE 上但非键列不同,则根据该列使用两个不同的解析:
-
根据
delta_res_method解析,对salary列使用USEDELTA解析逻辑,以便将值的更改添加到列的当前值中。 -
对于
DEFAULT,使用last_mod_time列作为解析列,对表(默认列组)中的所有其他列使用USEMAX解析逻辑。每当修改行时,都会使用当前时间更新此列;将线索中的此列的值与目标中的值进行比较。如果线索记录中的last_mod_time值大于目标数据库中last_mod_time的当前值,则对name、phone、address、balance、comment和last_mod_time的更改将应用于目标。
根据 COMPARECOLS,使用主键(name 列)加上 address、phone、salary 和 last_mod_time 列作为 UPDATE 和 DELETE 操作的冲突检测比较列。(不比较 balance 列和 comment 列。)
注:作为 USEMAX 的替代方法,您可以使用 USEMAXEQ 解析来应用 >= 条件。有关详细信息,请参阅 Oracle GoldenGate 的参数和函数参考。
错误处理
有关异常表的错误处理的示例,请参阅配置 Oracle GoldenGate 参数文件以处理错误。
表 15 使用 USEDELTA 和 USEMAX 的 UPDATEROWEXISTS
| 图像 | SQL | 备注 |
|---|---|---|
| 线索中的图像之前 | |
|
| 在线索中图像后 | |
last_mod_time='9/1/10 5:00 是 USEMAX 的分辨率列的后像。由于有后置图像,因此将用于确定分辨率。 |
| 目标数据库映像 | |
|
检测冲突的复制应用初始 UPDATE |
SQL 绑定的变量: |
此 SQL 返回“无数据发现”错误,因为 salary 和 last_mod_time 的值不同。(comment 和 balance 的值也不同,但不会比较这些列。) |
Replicat 应用 UPDATE 以使用 USEDELTA 解决 salary 的冲突。 |
SQL 绑定的变量: |
在 |
Replicat 应用 UPDATE,以使用 USEMAX 解决默认列的冲突。 |
SQL 绑定的变量: |
根据 请注意,此处未设置 |
CDR 示例 3:带有 USEDELTA、USEMAX 和 IGNORE 的 UPDATEROWEXISTS
此示例解决 UPDATE 上存在目标行但非键列不同的冲突,并根据受影响的列使用三种不同的解析类型来处理此条件。
本示例中使用的表
这些示例假定相同的 Oracle 数据库。
CREATE TABLE tgt(
name varchar2(30) primary key,
phone varchar2(10),
address varchar2(100),
salary number,
balance number,
comment varchar2(100),
last_mod_time timestamp);
在源数据库上,将补充记录所有列:
ADD TRANDATA scott.src, COLS (name, phone, address, salary, balance, comment, last_mod_time);
MAP 语句
MAP fin.src, TARGET fin.tgt,
COMPARECOLS
(ON UPDATE ALLEXCLUDING (comment)),
RESOLVECONFLICT (
UPDATEROWEXISTS,
(delta_res_method, USEDELTA, COLS (salary, balance)),
(max_res_method, USEMAX (last_mod_time), COLS (address, last_mod_time)),
(DEFAULT, IGNORE));
MAP 语句的说明
-
对于
UPDATEROWEXISTS冲突,如果目标行存在于UPDATE上但非键列不同,则根据该列使用两个不同的解析:-
根据
delta_res_method解析,对salary和balance列使用USEDELTA解析逻辑,以便将每个值的更改添加到每列的当前值中。 -
根据
max_res_method解析,对address和last_mod_time列使用USEMAX解析逻辑。last_mod_time列是分辨率列。每当修改行时,都会使用当前时间更新此列;将线索中的此列的值与目标中的值进行比较。如果线索记录中的last_mod_time值大于目标数据库中的当前值last_mod_time,则对address和last_mod_time的更改将应用于目标;否则,将忽略这些更改,取而代之的是目标值。 -
根据
DEFAULT,对表中的其余列(phone和comment)(默认列组)使用IGNORE解析逻辑。对这些列的更改将始终被复制忽略。
-
-
在
COMPARECOLS中,使用除comment列以外的所有列作为UPDATE操作的冲突检测的比较列。注释不会在WHERE子句中用于更新,但将使用线索记录中具有图像之前的所有其他列。注:作为USEMAX的替代方法,您可以使用USEMAXEQ解析来应用>=条件。有关详细信息,请参阅 Oracle GoldenGate 的参数和函数参考。
错误处理
有关异常表的错误处理的示例,请参阅配置 Oracle GoldenGate 参数文件以处理错误。
表 16 使用 USEDELTA、USEMAX 和 IGNORE 的 UPDATEROWEXISTS
| 图像 | SQL | 备注 |
|---|---|---|
| 线索中的图像之前 | |
|
| 在线索中图像后 | |
|
| 目标数据库映像 | |
|
检测冲突的复制应用初始 UPDATE |
SQL 绑定的变量: |
此 SQL 返回一个未找到数据的错误,因为 address、salary、balance 和 last_mod_time 列的值不同。 |
Replicat 应用 UPDATE 以使用 USEDELTA 解决 salary 的冲突。 |
SQL 绑定的变量: |
对于 salary,差异为 100,但是 balance 的值没有更改,因此在更新 SQL 中不需要。根据 USEDELTA,轨迹中 salary 的后 (200) 图像和前 (100) 图像之间的差值(差值)将添加到目标 (600) 中的当前值 salary。结果为 700。 |
Replicat 应用 UPDATE 以解决 USEMAX 的冲突。 |
SQL 绑定的变量: |
由于线索记录中 请注意,此处未设置 |
Replicat 对 IGNORE 应用了 UPDATE。 |
SQL 绑定的变量: |
为 DEFAULT 列组(phone 和 comment)指定了 IGNORE,因此不应用解析 SQL。 |
配置 Oracle GoldenGate 参数文件以进行错误处理
手动 CDR 应与错误处理结合使用,以捕获已解决的错误和 CDR 无法解决的错误。
-
在以下其他错误处理参数之前执行冲突解决:
HANDLECOLLSIONS、INSERTMISSINGUPDATES和REPERROR。使用REPERROR参数分配规则以处理无法由 CDR 解决的错误,或者分配不希望通过 CDR 处理的错误。可能适合让REPERROR处理一些错误,而 CDR 处理其他错误;但是,如果将REPERROR和 CDR 配置为处理相同的冲突,则 CDR 优先。INSERTMISSINGUPDATES和HANDLECOLLISIONS参数还可用于处理 CDR 未处理的一些错误。有关这些参数的详细信息,请参阅Oracle GoldenGate 的参数和函数参考。 -
(可选)创建例外情况表。当异常表与异常
MAP语句一起使用时,Replicat 会将生成冲突(已解决与否)的每个操作发送到异常MAP语句,以映射到异常表。如果 Replicat 要处理UPDATE和DELETE冲突,请省略此表中的主键;否则可能会出现完整性约束条件错误。至少,异常表应包含与目标表相同的列。这些行将包含复制应用于目标的每个行映像(或尝试应用)。
此外,还可以定义其他列来捕获有助于将数据置于事务处理上下文中的其他信息。Oracle GoldenGate 提供了通过异常
MAP语句捕获此信息的工具。此类列可以是(但不限于)以下列:-
线索记录的以前图像。这是名称为 col1 _before、col2 _before 等的目标列的一组重复项。
-
目标列的当前值。这也是名称为 col1 _current、col2 _current 等的目标列的一组重复项。
-
目标表的名称
-
冲突的时间戳
-
操作类型
-
数据库错误号
-
(可选)数据库错误消息
-
是否已解决冲突
-
-
创建异常
MAP语句以将异常数据映射到异常表。例外MAP语句包含:-
(必需)
INSERTALLRECORDS选项。此参数将所有映射的操作转换为INSERT,以便将所有列值映射至异常表。 -
(必需)
EXCEPTIONSONLY选项。此参数会导致 Replicat 映射生成错误的操作,但不会映射那些成功的操作。 -
(可选)
COLMAP子句。如果异常错误表中的列的名称和定义与源表中的列相同,并且异常错误表仅包含这些列,则不需要COLMAP。但是,如果任何名称或定义不同,或者如果异常表中存在要用其他数据填充的额外列,请使用COLMAP子句映射所有列。
-
用于将附加数据映射到异常表的工具
以下是一些工具,您可以在 COLMAP 子句中使用这些工具来填充额外的列:
-
如果源列的名称和定义与异常错误表中的目标列的名称和定义相同,则可以使用
USEDEFAULTS关键字,而不是显式映射名称。否则,必须在COLMAP子句中映射这些列,例如:COLMAP (exceptions_col1 = col1, [...]) -
要将源行的前一图像映射到异常错误表中的列,请使用
@BEFORE转换函数,该函数从线索记录中捕获列的前一图像。此示例显示了@BEFORE的用法。COLMAP (USEDEFAULTS, exceptions_col1 = @BEFORE (source_col1), & exceptions_col2 = @BEFORE (source_col2), [...]) -
要将目标行的当前图像映射到异常错误表中的列,请使用
SQLEXEC查询捕获该图像,然后使用COLMAP子句中的 'queryID.column ' 语法将查询结果映射到异常错误表中的列,如下例所示:COLMAP (USEDEFAULTS, name_current = *queryID*.*name*, phone_current = *queryID*.*phone*, [...]) -
要映射时间戳、数据库错误和其他环境信息,请使用相应的 Oracle GoldenGate 列转换函数。例如,以下内容映射执行时的当前时间戳。
res_date = @DATENOW ()
有关如何在例外 MAP 语句的 COLMAP 子句中组合这些功能以填充详细的例外表,请参阅例外表中的示例例外映射和附加列。
有关这些示例中所示的参数和列转换函数的使用和语法,请参阅Oracle GoldenGate 的参数和函数参考。
仅包含源列和目标列的示例例外映射
下面是一个示例参数文件,其中显示了开始的 CDR 示例中使用的源表和目标表的错误处理和简单异常映射。此示例映射源列和目标列,但不映射额外的列。出于以下原因,在此示例中的例外 MAP 语句中不需要 COLMAP 子句:
-
来源和目标例外列在名称和定义中是相同的。
-
异常错误表中没有其他列。注:此示例有意省略复制参数文件中需要的其他参数,例如进程名称和登录身份证明,以及给定数据库类型可能需要的任何可选参数。使用换行符将参数语句拆分为多行时,在每行的末尾使用“和”号 (&)。
-- REPERROR error handling: DEFAULT represents all error types. DISCARD
-- writes operations that could not be processed to a discard file.
REPERROR (DEFAULT, DISCARD)
-- Specifies a discard file.
DISCARDFILE /users/ogg/discards/discards.dsc, PURGE
-- The regular MAP statement with the CDR parameters
MAP fin.src, TARGET fin.tgt, &
COMPARECOLS (ON UPDATE ALL, ON DELETE ALL), &
RESOLVECONFLICT (UPDATEROWEXISTS, (DEFAULT, USEMAX (last_mod_time)), &
RESOLVECONFLICT (INSERTROWEXISTS, (DEFAULT, USEMAX (last_mod_time)), &
RESOLVECONFLICT (DELETEROWEXISTS, (DEFAULT, OVERWRITE)), &
RESOLVECONFLICT (UPDATEROWMISSING, (DEFAULT, OVERWRITE)), &
RESOLVECONFLICT (DELETEROWMISSING, (DEFAULT, DISCARD)), &
);
-- Starts the exceptions MAP statement by mapping the source table to the
-- exceptions table.
MAP fin.src, TARGET fin.exception, &
-- directs Replicat only to map operations that caused the error specified
-- in REPERROR.
EXCEPTIONSONLY, &
-- directs Replicat to convert all the exceptions to inserts into the
-- exceptions table. This is why there cannot be a primary key constraint
-- on the exceptions table.
INSERTALLRECORDS
;
例外表中包含附加列的例外映射示例
下面是一个示例参数文件,其中显示了开始的 CDR 示例中使用的源表和目标表的错误处理和复杂异常映射。在此示例中,异常表具有与源表相同的行,但是它还具有用于捕获上下文数据的附加列。
注:此示例有意省略复制参数文件中需要的其他参数,例如进程名称和登录身份证明,以及给定数据库类型可能需要的任何可选参数。使用换行符将参数语句拆分为多行时,在每行的末尾使用“和”号 (&)。
-- REPERROR error handling: DEFAULT represents all error types. DISCARD
-- writes operations that could not be processed to a discard file.
REPERROR (DEFAULT, DISCARD)
-- Specifies the discard file.
DISCARDFILE /users/ogg/discards/discards.dsc, PURGE
-- The regular MAP statement with the CDR parameters
MAP fin.src, TARGET fin.tgt, &
COMPARECOLS (ON UPDATE ALL, ON DELETE ALL), &
RESOLVECONFLICT (UPDATEROWEXISTS, (DEFAULT, USEMAX (last_mod_time))), &
RESOLVECONFLICT (INSERTROWEXISTS, (DEFAULT, USEMAX (last_mod_time)), &
RESOLVECONFLICT (DELETEROWEXISTS, (DEFAULT, OVERWRITE)), &
RESOLVECONFLICT (UPDATEROWMISSING, (DEFAULT, OVERWRITE)), &
RESOLVECONFLICT (DELETEROWMISSING, (DEFAULT, DISCARD))
);
-- Starts the exceptions MAP statement by mapping the source table to the -- exceptions table.
MAP fin.src, TARGET fin.exception, &
-- directs Replicat only to map operations that caused the error specified
-- in REPERROR.
EXCEPTIONSONLY, &
-- directs Replicat to convert all the exceptions to inserts into the
-- exceptions table. This is why there cannot be a primary key constraint
-- on the exceptions table.
INSERTALLRECORDS &
-- SQLEXEC query to select the values from the target record before the
-- Replicat statement is applied. These are mapped to the *_target
-- columns later.
SQLEXEC (id qry, query 'select name, phone, address, salary, balance, & comment, last_mod_time from fin.tgt where name = :p1', PARAMS(p1 = name )), &
-- Start of the column mapping, specifies use default column definitions.
COLMAP ( &
-- USEDEFAULTS maps the source columns to the target exceptions columns
-- that receive the after image that Replicat applied or tried to apply.
-- In this case, USEDEFAULTS can be used because the names and definitions
-- of the source and target exceptions columns are identical; otherwise
-- the columns must be mapped explicitly in the COLMAP clause.
USEDEFAULTS, &
-- captures the timestamp when the resolution was performed.
res_date = @DATENOW (), &
-- captures and maps the DML operation type.
optype = @GETENV ('LASTERR', 'OPTYPE'), &
-- captures and maps the database error number that was returned.
dberrnum = @GETENV ('LASTERR', 'DBERRNUM'), &
-- captures and maps the database error that was returned.
dberrmsge = @GETENV ('LASTERR', 'DBERRMSG'), &
-- captures and maps the name of the target table
tabname = @GETENV ('GGHEADER', 'TABLENAME'), &
-- If the names and definitions of the source columns and the target
-- exceptions columns were not identical, the columns would need to
-- be mapped in the COLMAP clause instead of using USEDEFAULTS, as
-- follows:
-- name_after = name, &
-- phone_after = phone, &
-- address_after = address, &
-- salary_after = salary, &
-- balance_after = balance, &
-- comment_after = comment, &
-- last_mod_time_after = last_mod_time &
-- maps the before image of each column from the trail to a column in the
-- exceptions table.
name_before = @BEFORE (name), &
phone_before = @BEFORE (phone), &
address_before = @BEFORE (address), &
salary_before = @BEFORE (salary), &
balance_before = @BEFORE (balance), &
comment_before = @BEFORE (comment), &
last_mod_time_before = @BEFORE (last_mod_time), &
-- maps the results of the SQLEXEC query to rows in the exceptions table
-- to show the current image of the row in the target.
name_current = qry.name, &
phone_current = qry.phone, &
address_current = qry.address, &
salary_current = qry.salary, &
balance_current = qry.balance, &
comment_current = qry.comment, &
last_mod_time_current = qry.last_mod_time)
;
一旦您确信例程在所有情况下都能按预期工作,就可以减少记录到异常表中的数据量,以减少解决例程的开销。