ER:冲突解决
当多个数据库服务器试图同时更新同一行时(更新的时间戳是相同的 GMT 时间),就会发生冲突。ER 必须判断出要复制的新数据。为了解决冲突,必须指定冲突解决规则和规则的事务范围。本节讨论以下主题:
有五个不同的冲突解决选项,它们的表现各不相同。下面的表总结了这些方法:
规则 |
描述 |
Ignore(忽略) |
ER 不尝试解决冲突。 |
Time stamp(时间戳) |
应用时间戳最近的行或事务。 |
SPL routine(SPL 例程) |
ER 使用一个用 SPL(Stored Procedure Language)编写的例程来判断应该应用的数据。 |
Time stamp with SPL routine(结合使用时间戳与 SPL 例程) |
如果时间戳相同,那么 ER 就调用 SPL 例程来解决冲突。 |
Always-apply(总是应用) |
ER 不尝试解决冲突,总是把源数据应用于目标。 |
目标是否存在键值? |
插入 |
更新 |
删除 |
No |
应用源记录 |
丢弃源记录 |
丢弃源记录 |
Yes |
丢弃源记录 |
应用源记录 |
应用源记录 |
目标是否存在键值? |
插入 |
更新 |
删除 |
No |
应用源记录 |
将行作为 upsert 应用 |
将行应用于影子表 |
Yes |
将行作为 upsert 应用,覆盖现有行 |
应用行 |
删除行 |
副本的范围(事务或行)定义 ER 如何对故障做出反应。故障可能由冲突、锁问题等造成。如果范围是 ‘row’,那么只有单独的行失败;但是,如果范围是 ‘transaction’,那么整个事务都将失败。
为了解决冲突,需要了解两种影子对象:
对于使用时间戳或存储过程冲突解决选项的所有表,复制过程使用影子列实现冲突解决。这些列也称为 CRCOLS 或冲突解决列。它们由两个字段组成,cdrserver 和 cdrtime。cdrserver 是一个惟一 ID,表示行的源服务器 id。cdrtime 是一个时间戳,表示在源服务器上执行提交的时间。
ER 创建影子表(即删除表)来存储已经删除的行,直到删除操作完全传播出去为止。影子表包含删除的行的完整拷贝(包括影子列)。只要冲突解决类型不是忽略,那么在创建副本时,就会创建影子表。在 syscdr 数据库的 ‘deltabdef’ 表中包含复制的表和影子表之间的关系。
如果一个事务无法应用,ER 就会从接收队列中删除失败的事务,并在指定的 ATS 目录中写入一个文件,其中包含整个事务的详细信息。只在整个事务失败的情况下,执行 ATS spooling。每个失败的事务被写到 ATS 配置参数指定的目录中的一个外部文件中。ATS 和 RIS 文件的默认位置是 /tmp。ATS 文件名的格式是 ats.targetServername.sourceServername.threadId.timestamp.sequence,其中各个部分的含义如下:
- targetServername —— 接收这个事务的 ER 服务器的名称
- sourceServername —— 发送这个事务的 ER 服务器的名称
- threadId —— 处理这个事务的线程
- timestamp —— 创建 ATS 文件时 cdrtime 的值
- sequence —— 对于每个文件递增的惟一整数
示例:
- ats.test1.test3.D_1.970827_14:23:42.4
- ats.test2.test3.D_1.970827_14:23:41.4
在插入转换为更新和更新转换为插入时,ER 将失败的行错误记录在 RIS 文件中。另外,如果用来解决冲突的存储过程失败了,那么用返回码生成一个 RIS 文件。RIS 文件名的格式与 ATS 文件名相同。下面是一些示例:
- ris.test1.test3.D_1.970827_14:23:42.3
- ris.test2.test3.D_1.970827_14:23:41.3
这个练习实践复制和冲突解决方面的操作。通过这个练习,您应该能够看到 ER 如何用时间戳和忽略选项处理冲突。
练习:执行以下步骤:
步骤 |
描述 |
1 |
定义下面的表:
CREATE table rocket(
rocket_id int,
rocket_name char(20),
rocket_cost money(10,2),
launch_date datetime year to second,
primary key (rocket_id,rocket_name))
with crcols; |
|
2 |
定义一个副本,这个副本在系统的其他节点上创建这个表。这个副本包含以下属性:
- 时间戳冲突解决选项
- 事务范围
- ATS 和 RIS 错误日志记录
|
3 |
启动副本并插入以下行:
insert into rocket values (10,"Gemini",500000.00,today);
insert into rocket values (20,"Apollo13",800000.00,today);
insert into rocket values (30,"Ramjet",400000.00,today);
insert into rocket values (40,"Ramjet2",1000000.00,today); |
|
4 |
暂停副本 |
5 |
在两个服务器上执行以下更新。一定要按照这里的次序执行更新(首先执行 T1)。
(T1) 在服务器 A 上
UPDATE rocket set rocket_cost = 600000.00
where rocket_cost = 500000.00 and rocket_name = "Gemini";
(T2) 在服务器 B 上
UPDATE rocket set rocket_cost = 700000.00
where rocket_cost = 500000.00 and rocket_name = "Gemini"; |
|
6 |
继续执行副本。在两个服务器上 Gemini 的成本值是相同的吗?值为多少?在哪里进行冲突探测?在哪里执行冲突解决?在每个服务器上查询数据库来证实您的猜测。 |
7 |
检查是否生成了任何日志消息。每个服务器上应该会生成一个日志消息。是什么导致生成 ATS 和 RIS 文件? |
解决方案:应该执行以下步骤:
步骤 |
描述 |
1 |
定义下面的表:
CREATE table rocket(
rocket_id int,
rocket_name char(20),
rocket_cost money(10,2),
launch_date datetime year to second,
primary key (rocket_id,rocket_name))
with crcols; |
|
2 |
定义一个副本,这个副本在系统的其他节点上创建这个表。这个副本包含以下属性:
- 时间戳冲突解决选项
- 事务范围
- ATS 和 RIS 错误日志记录
cdr def repl -M g_80s -n n -u -C "timestamp" -S tran -A -R rocketrep \
"stores7@g_80s:informix.rocket" "select * from rocket" \
"stores7@g_90s:informix.rocket" "select * from rocket"
| 定义副本的语句产生以下输出:
$ ./def_rocketrep.sh
Verification of stores7@g_80s:informix.rocket started
Verification of stores7@g_80s:informix.rocket is successful
Verification of stores7@g_90s:informix.rocket started
Creating table...
create table informix.rocket (
rocket_id integer,
rocket_name char(20),
rocket_cost money(10,2),
launch_date datetime year to second,
primary key (rocket_id, rocket_name)) with CRCOLS lock mode row;
Verification of stores7@g_90s:informix.rocket is successful
|
|
3 |
启动副本并插入以下行:
insert into rocket values (10,"Gemini",500000.00,today);
insert into rocket values (20,"Apollo13",800000.00,today);
insert into rocket values (30,"Ramjet",400000.00,today);
insert into rocket values (40,"Ramjet2",1000000.00,today); |
|
4 |
暂停副本:
cdr suspend repl rocketrep
| 检查 onstat -g cat 的输出,副本的状态应该是 SUSPENDED。 |
5 |
在两个服务器上执行以下更新。一定要按照这里的次序执行更新(首先执行 T1)。
(T1) 在服务器 A 上
UPDATE rocket set rocket_cost = 600000.00
where rocket_cost = 500000.00 and rocket_name = "Gemini";
(T2) 在服务器 B 上
UPDATE rocket set rocket_cost = 700000.00
where rocket_cost = 500000.00 and rocket_name = "Gemini"; |
|
6 |
继续执行副本 —— cdr resume repl rocketrep 。在两个服务器上 Gemini 的成本值是相同的吗?值为多少?在哪里进行冲突探测?在哪里执行冲突解决?在每个服务器上查询数据库来证实您的猜测。
on server A
rocket_id rocket_name rocket_cost launch_date
10 Gemini $600000.00 2007-06-09 00:00:00
20 Apollo13 $800000.00 2007-06-09 00:00:00
30 Ramjet $400000.00 2007-06-09 00:00:00
40 Ramjet2 $1000000.00 2007-06-09 00:00:00
on server B
rocket_id rocket_name rocket_cost launch_date
10 Gemini $700000.00 2007-06-09 00:00:00
20 Apollo13 $800000.00 2007-06-09 00:00:00
30 Ramjet $400000.00 2007-06-09 00:00:00
40 Ramjet2 $1000000.00 2007-06-09 00:00:00
| 如果先在服务器 B 上运行更新,然后是服务器 A,那么结果可能不一样。 |
7 |
检查是否生成了任何日志消息。是什么导致生成 ATS 和 RIS 文件?
15:28:51 CDR CDRD_3: transaction aborted (One or more rows in a
transaction defined with tx scope were rejected) with sql error 0 isam
error 0.
15:28:51 CDR CDRD_3: failed transaction spooled to file
/informix/ats-ris/boy/ats.g_80s.g_90s.D_3.070609_15:28:51.2
|
$ more ats.g_80s.g_90s.D_3.070609_15:28:51.2
TXH RIS file:/informix/ats-ris/boy/ris.g_80s.g_90s.D_3.070609_15:28:51.1
has also been created for this transaction
==========
TXH Source ID:90 / Name:g_90s / CommitTime:07-06-09 15:26:40
TXH Target ID:80 / Name:g_80s / ReceiveTime:07-06-09 15:28:51
TXH Number of rows processed when transaction was aborted:1
TXH One or more rows in a transaction defined with tx scope were rejected
TXH CDR:14 (Error: Failed conflict resolution rule) / SQL:0 / ISAM:0
----------
RRH Row:1 / Replicate Id: 5242884 / Table: stores7@informix.rocket /
DbOp:Update
RRS 90 (g_90s)|1181420800 (07/06/09 15:26:40)
RRD 10|Gemini|700000.00|2007-06-09 00:00:00
|
$ more ris.g_80s.g_90s.D_3.070609_15:28:51.1
TXH Source ID:90 / Name:g_90s / CommitTime:07-06-09 15:26:40
TXH Target ID:80 / Name:g_80s / ReceiveTime:07-06-09 15:28:51
----------
RRH Row:1 / Replicate Id: 5242884 / Table: stores7@informix.rocket /
DbOp:Update
RRH CDR:14 (Error: Failed conflict resolution rule) / SQL:0 / ISAM:0
LRS 80 (g_80s)|1181420912 (07/06/09 15:28:32)
LRD 10|Gemini|600000.00|2007-06-09 00:00:00
RRS 90 (g_90s)|1181420800 (07/06/09 15:26:40)
RRD 10|Gemini|700000.00|2007-06-09 00:00:00
==========
TXH Transaction aborted
TXH ATS file:/informix/ats-ris/boy/ats.g_80s.g_90s.D_3.070609_15:28:51.2
has also been created for this transaction
| |
阅读(2026) | 评论(0) | 转发(0) |