HANDLECOLLISIONS | NOHANDLECOLLISIONS
有效对象
复制
说明
使用 HANDLECOLLISIONS 和 NOHANDLECOLLISIONS 参数控制在目标上应用 SQL 时复制是否尝试解决重复记录和缺失记录错误。将源表中的数据加载到目标表,Oracle GoldenGate 正在复制这些表正在进行的事务处理更改时,这些错误(称为冲突)会在初始装入过程中出现。当 Oracle GoldenGate 在加载完成后应用复制的更改时,HANDLECOLLISIONS 会为复制提供这些冲突的错误处理逻辑。
您可以通过以下方式使用 HANDLECOLLISIONS 和 NOHANDLECOLLISIONS:
-
通过在参数文件的根级别指定
HANDLECOLLISIONS和NOHANDLECOLLISIONS,可以以全局方式启用它们。在遇到相反参数之前,将为参数文件中的所有后续MAP语句保留一个参数。 -
可以在特定的
MAP参数中启用HANDLECOLLISIONS或NOHANDLECOLLISIONS,以便仅为该源 - 目标映射启用或禁用错误处理。
可以组合上述方法。您可以指定全局冲突处理规则,然后在 MAP 语句中使用不同的冲突处理规则覆盖该规则。MAP 规范始终覆盖全局规范。
注意:集成复制的错误处理不适用于 HANDLECOLLISIONS。Oracle 建议您使用精确的实例化方法,而不是使用 HANDLECOLLISIONS。
HowHANDLECOLLISIONSWorks
以下示例说明 HANDLECOLLISIONS 的工作原理:
-
当 Replicat 遇到 Oracle GoldenGate 将其用作密钥的列更新时,处理方式如下:
-
如果在目标中未找到具有旧关键字的行,则线索中的更改记录将转换为插入。
-
如果目标中存在具有新关键字的行,Replicat 将删除具有旧关键字的行(如果更新成功执行,则该行将不存在),然后将具有新关键字的行更新为线索值替换当前值的覆盖层。
此逻辑要求默认或强制将表中的所有列(不仅仅是更改的列)记录到事务日志中,例如,对 Oracle 数据库使用
ADD TRANDATA的COLS选项。请参阅避免缺少列值的可能解决方案。 -
-
当 Replicat 遇到重复记录错误时,由初始加载应用的静态记录将被线索中的更改记录覆盖。从运营角度来看,覆盖更改比忽略重复记录错误更安全。
-
使用
HANDLECOLLISIONS进行复制不会放弃线索中的更改记录,即使更新或删除操作不会影响源中的键列,并且 Replicat 在目标中遇到缺失记录错误。当在源系统上更改记录,然后在初始加载处理提取表数据之前删除记录时,会发生这些错误。例如:
-
应用程序将更新源 table1 中的记录 A。
-
提取将提取更新。
-
应用程序将删除源 table1 中的记录 A。
-
提取将提取删除。
-
Oracle GoldenGate 从源 table1 提取初始加载数据,没有记录 A。
-
Oracle GoldenGate 应用初始加载,但不应用记录 A。
-
复制尝试应用记录 A 的更新。
-
数据库将返回“record missing”错误。
-
复制尝试应用记录 A 的删除。
-
数据库将返回“record missing”错误。
在将初始加载期间捕获的事务处理更改应用于目标表后禁用 HANDLECOLLISIONS,以便复制不会自动处理后续错误。初始同步后生成的错误表示异常情况,应由可确定如何解决错误的人员进行评估。例如,缺少记录错误可能表明源系统上存在的记录被无意中删除。
您可以通过以下方式关闭 HANDLECOLLISIONS:
-
停止复制并从 Replicat 参数文件中删除
HANDLECOLLISIONS(可能会导致目标延迟)。或者,可以编辑参数文件,在要禁用错误处理的MAP语句之前添加NOHANDLECOLLISIONS。 -
在 Replicat 正在运行时,运行 GGSCI,然后对要影响的表使用带有
NOHANDLECOLLISIONS选项的SEND REPLICAT命令。注意:如果使用
SEND REPLICAT,请确保在启动另一个复制运行之前从参数文件中删除HANDLECOLLISIONS或添加NOHANDLECOLLISIONS参数,以便HANDLECOLLISIONS不会再次激活。
避免缺少列值的可能解答
默认情况下,数据库未记录源表的所有列值时,当 Replicat 尝试将主键更新转换为插入时,如果目标表具有 NOT NULL 约束条件,则可能会出现错误。您可以通过以下方式处理此方案:
-
HANDLECOLLISIONS要求表在目标表上具有 NOTNULL主键或 NOTNULL唯一约束条件。 -
使用“提取”参数文件中的
NOCOMPRESSUPDATES参数将表的所有列发送到线索,并将数据库配置为记录所有列值。默认情况下,Extract 仅写入主键和已更改为线索的列。这是最安全的方法,因为它在执行操作时写入当前值,并且无需提取。 -
将
FETCHOPTIONS参数与提取参数文件中的FETCHPKUPDATECOLS选项一起使用。此配置会导致在源上更新键列时提取不可用列。提取是当前值,不一定是特定更新时的值,因此可能会出现数据完整性问题。有关更多信息以及用于处理不成功提取的其他提取选项,请参见"[FETCHOPTIONS](fetchoptions.html#GUID-DB7BCF87-E3E8-48CF-868A-A56F6D0B6A07)"。
如果数据库默认包含所有列,则必须使用 NOCOMPRESSUPDATES 和 NOCOMPRESSDELETES 才能使 HANDLECOLLISIONS 正常工作。如果数据库不支持 NOCOMPRESSDELETES,则必须使用 FETCHOPTIONS MISSINGCOLS。
有关 Oracle GoldenGate 初始加载方法的更多信息,请参阅关于使用初始加载提取实例化。
默认值
NOHANDLECOLLISIONS
语法
HANDLECOLLISIONS | NOHANDLECOLLISIONS [_ALLOWPKMISSINGROWCOLLISIONS]
[THREADS (<threadID>[, <threadID>][, ...][, <thread_range>[, <thread_range>][, ...])]
HANDLECOLLISIONS
启用碰撞处理。
_ALLOWPKMISSINGROWCOLLS
如果对应的目标行不存在,则将 HANDLECOLLISIONS 与 _ALLOWPKMISSINGROWCOLLISIONS 一起使用可跳过主键 UPDATE 操作。
注意:跳过操作可能会导致数据损坏。请参见本主题中的“说明”。
NOHANDLECOLLISIONS
关闭碰撞处理。
THREADS (<threadID>[, <threadID>][, ...][, <thread_range>[, <thread_range>][, ...])
为指定的线程启用 HANDLECOLLISIONS。在参数文件的根级别的全局 HANDLECOLLISIONS 语句中使用时,无论指定线程位于 的所有 MAP 语句中的哪个位置,都将为其启用 HANDLECOLLISIONS。在 MAP 语句的 HANDLECOLLISIONS 子句中使用时,仅为该 MAP 语句启用 HANDLECOLLISIONS。
threadID[, threadID][, …]
指定一个线程 ID,或以 threadID, threadID, threadID 格式指定逗号分隔的线程列表。
thread_range[, thread_range][, …]
以 threadIDlow-threadIDhigh 形式指定线程范围,或以 threadIDlow-threadIDhigh,threadIDlow-threadIDhigh 格式指定的逗号分隔的范围列表。
允许组合使用这些格式,例如 threadID、threadID、threadIDlow-threadIDhigh。
示例
示例 1
此示例为参数文件中的所有 MAP 语句启用 HANDLECOLLISIONS。
HANDLECOLLISIONS
MAP hr.emp, TARGET hr.emp;
MAP hr.job_hist, TARGET hr.job_hist;
MAP hr.dep, TARGET hr.dep;
MAP hr.country, TARGET hr.country;
示例 2
此示例为某些 MAP 语句启用 HANDLECOLLISIONS,而为其他语句禁用它。
HANDLECOLLISIONS
MAP hr.emp, TARGET hr.emp;
MAP hr.job_hist, TARGET hr.job_hist;
NOHANDLECOLLISIONS
MAP hr.dep, TARGET hr.dep;
MAP hr.country, TARGET hr.country;
示例 3
此示例显示 MAP 语句中 HANDLECOLLISIONS 的基本用法。
MAP dbo.tcust, TARGET dbo.tcust, HANDLECOLLISIONS;
示例 4
此示例显示了全局使用和 MAP 级使用的组合。MAP 规范将覆盖指定表的全局规范。
HANDLECOLLISIONS
MAP hr.emp, TARGET hr.emp;
MAP hr.job_hist, TARGET hr.job_hist;
MAP hr.dep, TARGET hr.dep, NOHANDLECOLLISIONS;
MAP hr.country, TARGET hr.country, NOHANDLECOLLISIONS;
示例 5
在以下示例中,为所有 MAP 语句全局启用了 HANDLECOLLISIONS,除了第一个 MAP 语句中的缺省线程 0 和第二个 MAP 语句中的线程 3。
HANDLECOLLISIONS
MAP fin.*, TARGET fin.*;
MAP sales.*, TARGET sales.*;
MAP orders.*, TARGET orders.*;
MAP scott.cust, TARGET scott.cust, NOHANDLECOLLISIONS;
MAP amy.cust, TARGET amy.cust, THREAD(3), NOHANDLECOLLISIONS;
示例 6
In this example, HANDLECOLLISIONS is enabled globally, but turned off for thread 3. 剩余的线程 1、2 和 4 将处理碰撞。
HANDLECOLLISIONS
NOHANDLECOLLISIONS THREAD(3)
MAP scott.emplyees, TARGET scott.employees, THREADRANGE(1,4, OID);
MAP scott.inventory, TARGET scott.inventory, THREADRANGE(1,4, OID);
MAP scott.cust, TARGET scott.cust, THREADRANGE(1,4, OID);
示例 7
In this example, HANDLECOLLISIONS is enabled globally, then disabled globally for threads 5 through 7. 在第一个 map 语句中,所有线程都将处理冲突,因为 HANDLECOLLISIONS 参数未指定线程或范围。在第二个 map 语句中,只有线程 4、8 和 9 将处理冲突,因为全局 NOHANDLECOLLISIONS 适用于线程 5-7。
HANDLECOLLISIONS
NOHANDLECOLLISIONS THREADRANGE(5-7)
MAP scott.cust, TARGET scott.cust, THREADRANGE(4,9,OID), HANDLECOLLISIONS;
MAP scott.offices, TARGET scott.offices, THREADRANGE(4,9,OID);
MAP scott.emp, TARGET scott.emp, THREADRANGE(4,9,OID);
MAP scott.ord, TARGET scott.ord, THREADRANGE(4,9,OID);
MAP acct.*, TARGET acct.*;
MAP admin.*, TARGET admin.*;