Chinaunix首页 | 论坛 | 博客
  • 博客访问: 91305108
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类: DB2/Informix

2008-05-31 17:56:36

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 启动副本并插入以下行:


                                
cdr start repl rocketrep
              



                                
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
阅读(1970) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~