工作负载与 Db2 数据库考量
由于复制技术在源系统和目标系统(它们是独立 Db2 系统)上采用日志捕获/事务重放技术,因此需要对您的工作负载和数据库进行若干考量。
Log-capture/transaction-重放技术通过从数据库恢复日志中捕获日志记录并重构 SQL 语句以在目标上重放事务,来检测对源数据库进行的更改 (异步且对源应用程序没有影响)。
SQL 重放要求表具有唯一约束,以在复制将行应用于目标表时强制执行每行的唯一性。 根据数据库和工作负载的特征,您可能还需要在复制之外执行一些管理更改。
以下部分描述了可能需要针对工作负载和数据库解决的与复制相关的约束。
概述
通过日志捕获技术,只能复制存在某些 DBMS 日志记录的数据库操作。 复制可自动复制以下操作:
- DML :INSERT/UPDATE/DELETE
- DDL:请参阅 Db2 中的受支持DDL操作。
- 立即截断
复制可以检测对复制的源表调用 Db2 LOAD 实用程序,并重新初始化该表的复制预订。 在使用初始装入来定义预订时,将通过对按列组织的表使用外部表装入或者对按行组织的表使用 Db2 LOAD 从游标来自动在目标端重新装入整个表。 在重新装入期间捕获更改,因此应用程序可以继续更新源表。
要点: 预订重新初始化适用于整个表,即使对源表执行了 LOAD APPEND 也是如此。 要复制增量 LOAD 而不是重新装入整个表,必须使用外部表装入 (这是已记录的操作) 或插入来装入表,而不是使用 LOAD 实用程序。
对于 DDL 更改复制,允许用户在目标系统上已进行更改的情况,在这种情况下,复制只需更新其元数据。 您还可以在执行 DDL 更改时临时停止复制,在应用程序升级期间出现任何问题时保留回退的目标级别,然后在验证完成后重新启动复制,以使复制使用相同的 DDL 更改来更新目标系统。
通常,会识别复制到重放事务所需的 DDL 更改 (例如复制的表中的新列) ,并且缺省情况下会自动复制这些更改。 当前不会复制仅由应用程序需要或特定于数据库配置的更改 (例如,创建视图或请求数据库配置更改)。 用户必须对每个数据库执行此类更改。 由于数据库彼此独立,并且每个数据库都处于完全活动状态,因此它们可以运行不同的应用程序,并且可以进行不同的配置。 这允许您登台升级,并使其中一个系统处于较低级别以进行回退。
可以在没有任何用户干预的情况下复制某些 DDL 操作,并且不会对复制过程和应用程序工作负载造成任何中断。 对于 LOAD 实用程序,复制提供了用于执行目标表完全刷新的选项。
通过日志捕获/事务重放技术,在目标上执行的 SQL 语句相当于但不一定与应用程序针对源数据库发出的 SQL 语句相同。 目标数据库上的 SQL 语句反映的是记录的内容,而不是用户在源上发出的内容。 此方法具有巨大优势,因为您可以复制在源上成功落实的内容,而不是复制应用程序可能尝试运行的内容。 例如,它允许您复制存储过程的每个操作,而在目标上重放相同的存储过程可能会产生不同的结果。 它还确保源端 Db2 生成的值(如时间戳、日期或自动生成列)在源系统和目标系统上完全一致。
唯一约束
对于按行组织的表和按列组织的表,表上应存在唯一约束:
- 对于按行组织的表,应强制实施唯一约束并具有关联的索引。
- 对于按列组织的表,不必强制实施唯一约束 (不需要索引) ,但应用程序必须遵守唯一约束。 Db2 不检查重复行。
如果按列组织的表没有唯一约束或任何可唯一标识每行的列集,那么建议的解决方案是将标识列添加到对该列具有唯一约束的表中。 Db2 然后为插入到该表中的每行生成一个唯一值。
若需为多分区数据库中已投入使用的现有表添加唯一约束,必须先停用再重新启用该数据库, Db2 以确保约束在所有分区中生效,并避免对该表执行删除操作时导致性能下降。 如果未能执行此操作,那么在删除按列组织的表上的大量行时,可能会导致严重的性能下降。
以下查询可用于标识没有唯一索引的表:
with unitab(tabname) as(
select distinct tabname from syscat.indexes
where
tabschema IN ('YOURSCHEMA') and not tabname like 'CD%'
and uniquerule in ('P','U')
)
select
SUBSTR(TABSCHEMA,1,12) AS TABSCHEMA,
char(t.tabname,30) tabname,
case
when u.tabname is not null then 'No problem'
when u.tabname is null then 'No unique Index!!'
end
from syscat.tables t left join unitab u on t.tabname = u.tabname
where
t.tabschema IN ('YOURSCHEMA') AND t.type ='T' and not t.tabname like 'CD%'
ORDER BY 3,1,2 desc;
引用完整性约束
必须在同一复制集中复制由外键约束相关的表。 必须先对父表进行活动复制,然后才能激活任何子表。
提示: 为了在必须停止复制并累积大量积压更改的长时间中断后更快地重新启动系统,请删除正在恢复联机的站点上的 RI 约束,以更快地再同步。 在复制清除了积压的更改之后,以及在将应用程序重新路由到该站点之前,复原 RI 约束。
具有标识列的表
对于标识列,生成的值的范围不得在源数据库与目标数据库之间重叠。 例如,假定下表包含名为 ID 的标识列:
CREATE TABLE CUSTOMER (ID SMALLINT
GENERATED BY DEFAULT AS IDENTITY(START WITH 100 INCREMENT BY 1),
NAME VARCHAR(30));
请遵循以下建议:
- 如果要在两个站点之间复制,或者在每个站点的不同范围之间复制,请使用奇偶性方案。 例如,如果使用范围,请在目标处变更表:
在此示例中,将在站点 1 上使用值 1 到 15999 ,并在站点 2 上使用值 16000 和更大的值。ALTER TABLE CUSTOMER ALTER COLUMN ID RESTART WITH 16000 - 在活动/备用配置中使用复制 (其中仅允许在一个站点上对相同数据执行读写操作,直到故障转移到备用站点) 时,请编写一个脚本以在将应用程序故障转移到备用站点之前将备用站点上的标识列从 MAX (identity-column-name) + 1 开始。 例如:
SELECT MAX(ID)+1 FROM CUSTOMER ALTER TABLE CUSTOMER ALTER COLUMN ID RESTART WITH :val
如果无法定义标识列以在站点之间生成非重叠值,那么需要在应用程序站点切换之前进行重置。
数据库序列
序列是可用于生成用于插入或更新到表中的值的数据库对象。 例如,insert into t2(col1) values(next value for myseq)。
例如,源数据库可能是位于法国蒙彼利埃的 Db2 系统,目标数据库则是位于加利福尼亚州圣何塞的 Db2 系统。 数据库独立性对系统 Db2 自动生成的任何值(如数据库序列)均有影响。 因为在两个独立数据库系统之间没有生成这些值的协调,所以在蒙彼利埃可用于序列的下一个值与在圣何塞可用的下一个值不相同。 如果更新在每个站点上使用此类序列并双向复制的表,那么需要策略以防止值重叠。
请遵循以下建议:
- 使用奇数/偶数方案或不同值范围在站点之间生成分区序列,以便值不会重叠。 无法在没有高冲突风险的主动/主动配置中使用可生成重叠值的序列。
- 活动/备用配置: 在应用程序将在发生灾难或进行维护时进行故障转移的情况下,请在重新路由应用程序之前将序列更改为 max+1 ,例如:
ALTER SEQUENCE ORG_SEQ RESTART SELECT NEXT VALUE FOR ORG_SEQ, ORG.* FROM ORG。
在应用程序站点切换之前,序列可能需要重置。
未记录的操作
未记录的数据库操作 (例如,使用 LOAD 实用程序装入数据以及指定 NOT LOGGED 初始的表) 需要特别考虑。 复制可以检测以下类型的 LOAD 实用程序并触发表的自动重新初始化:
- 装入 REPLACE
- 加载插入
提示: 捕获程序无法检测第三方装入实用程序。 如果希望通过复制自动处理装入操作,请使用 IBM® 实用程序。 否则,请停止该表的复制,并在重新装入该表后将其重新启动。
增量装入和分区装入
无法自动复制 LOAD INSERT。 只有完全刷新才能由复制自动执行。 即,即使装入了单个分区,当 CAPTURE_LOAD=R 并且将复制集定义为使用自动装入时,也会重新装入整个表。
同时运行应用程序,以更新两个站点上的相同数据
在主动/主动配置中,不应让应用程序在复制同步之前更新同一行。 如果发生此情况,那么将检测并报告复制冲突,并且缺省情况下将强制进行更改。 这种情况通常会导致站点之间的数据不一致。 冲突意味着用户落实的更改丢失,冲突解决永远无法从业务角度保证正确的结果。 用户负责确保应用程序正确路由到每个数据库以防止冲突。 在数据库之间切换应用程序时,首先从控制台验证在应用程序停止更新源站点时是否达到了一致性点。
请注意,仅插入的工作负载从不冲突,并且可以路由到所有站点。
在主动/主动环境中具有多个唯一索引的表上存在冲突的特殊情况。 对于大多数情况下,可以复制同时具有主键和一个或多个辅助唯一索引的表,而不会出现任何问题,但是在两个站点上同时更新主键和一个辅助键时可能会出现问题。 例如:
SITE A: (1,2) SITE B: (1,2)
SITE A: insert (2,3) SITE B: insert (5,3)
----replication sends the rows in each direction ----
SITE A: insert (5,3) ---> ERROR: SQL803 (duplicate row) Q Apply
follows ERROR_ACTION
SITE B: insert (2,3) ---> ERROR: SQL803 (duplicate row) Q Apply
follows ERROR_ACTION
具有用于更新其他表的触发器的表
应用程序可能依赖于触发器将数据插入到 Db2. 中。 例如,您可能在表上具有插入触发器,该触发器生成时间戳记并将一行插入到具有该时间戳记的另一个表中。
如果两个表都添加到复制集,并且触发器在目标上不存在,那么将复制父表中的插入和从属表中的插入,在我们的示例中保持相同的时间戳记值。
其含义是,在将应用程序重新路由到目标站点之前,需要复原触发器。
若您希望保留触发器,可向 IBM 提交服务请求,以更改复制配置: 当父表插入操作被复制时,触发器产生的操作将不被复制,而是依赖目标端触发器自行执行。 如果未触发 Db2 任何自动生成的值(例如无时间戳),这可能是更优方案,因为您无需先从目标表中删除触发器,也无需在重新路由依赖此触发器的应用程序前恢复该触发器。
限制
- 对具有强制唯一约束的表执行的多行SQL更新语句, Db2 若需将唯一性检查推迟至语句末尾执行,则无法在不修改数据库或应用程序的情况下进行复制。 如果执行此语句会导致临时重复值,那么无法复制使用唯一约束更新一个或多个列的多行更新语句。 这类语句的一个例子是在一个表中更新k=k+1",而这个表中已经包含了 k 值为 1 和 2 的行。 这是因为多行语句在目标上作为独立语句重放,因为它们是从源上的日志中捕获的。 如果任何单个语句失败,那么将遵循为复制集定义的错误操作。 数据库变通方法是向此表添加另一个唯一索引,并将此索引用作复制键,如果可能,请除去目标上的唯一约束。
提示: 要在无法从表中的现有列生成唯一键时生成唯一键,可以使用序列。 以下示例说明了此概念。 这些命令适用于命令行 Db2 界面。 假定已创建下表:
create table T1(tabkey integer not null primary key);应用程序使用 tabkey=tabkey+1更新表,这将导致语句执行期间出现临时重复值。 复制这种多行更新语句的解决方案是使用具有唯一值的表的另一列,必要时添加一个。 以下示例使用序列。 首先添加几行以演示:
insert into T1 values (0),(1);然后添加新的唯一索引和列:
alter table T1 add column repkey integer not null with default 0; alter table T1 alter column repkey drop default; alter table T1 alter column repkey set generated always as identity;然后,删除主键并将其重新创建为非唯一索引:
alter table T1 drop primary key; create index tabind on T1(tabkey); update T1 set repkey = default; reorg table T1;然后,您可以查看新索引的生成值:
select * from T1;此语句将唯一增量值插入到表中的每行中。 在目标上,还必须将主键替换为非唯一索引。 定义此表的预订时,请选择新的唯一键 (在我们的示例中为 repkey) 作为复制键,而不是主键。
- 在使用基于网格的访问控制 (LBAC) 的数据库上不支持复制。