消息流可以由以下部分组成:
下面是消息流处理消息时发生的典型事件顺序:
请注意,对于访问表和写输出消息,该事件顺序没有区别。虽然,流经常产生某种输出消息,但是,产生输出消息和更新数据库表之间没有实际的区别;在这两种情况下,系统中数据的状态都会改变。
=====x=========x===x=======x=============x====x===== 1 2 3 4 5 6
该行表示随着时间的推移系统内的数据。在时间 1,消息到达,并且从输入队列中取出消息。在时间 2、3、4 和 5,数据用来更新数据库表或被写入队列。在图中用 x 符号表示数据状态的更改。 在时间 6,发送输出消息并且系统是不活动的。数据的状态在这些事件之间没有变化,这在图中用 = 符号表示。
如果系统发生故障(例如,正在运行代理的计算机断电),则发生故障之前已对表和队列状态的进行了更改,但是,在故障之后将不会再进行更改。在某些情况下这种情形是不可接受的,例如,如果将款项从活期存款帐户转到贷款帐户时系统发生故障,则可能从活期存款帐户中转出了这笔款项,但没有转入贷款帐户。
-----x=========x===x=======x=============x====x----- 1 2 3 4 5 6
图中的该行表示随着时间的推移系统内的额外数据。在时间 1,消息到达,并且从输入队列中取出消息。在时间 1 之前,系统中没有额外数据,这在图中用 - 符号表示。在时间 1 之后,状态表示已经从队列中取出消息,从而可以在需要时将消息放回队列中。在时间 2、3、4 和 5,数据用来更新数据库表或被写入队列。额外数据的状态再次发生变化,从而可在需要时撤销对表和队列的更改。在时间 6,发送输出消息,此时系统处于非活动状态,并且系统中不再有额外的数据。在这些事件之间,额外数据的状态没有变化,这由 = 符号表示。如果在时间 1 和时间 6 的任何时间内发生故障,便会使用额外数据来有效复原系统数据的原始状态,输出队列中没有写入任何数据,也没有更新任何表,并且没有从输入队列中取出任何输入消息。如果未发生故障,则在时间 6 的更改将成为永久的更改(后继故障后的撤销操作不会撤销更改)。
上述的操作方式就是协调事务方式。事务成功完成称为事务的落实。未成功完成称为回滚。
操作的协调事务方式的主要特性是,无论在何处或何时发生故障,对与某个输入消息关联的多个队列和表的所有更改会全部执行或都不执行。但是,如以下示例所示,这个特性并不是总是适用的:
MAIN -----x=========x===x=======x=============x====x----- 1 2 4 5 8 9 1st AUX --------------x======x========x------ 3 6 7
MAIN 行表示主要事务,它包含在需要时复原到原始状态所需的额外数据。1st AUX 行表示辅助事务。在时间 3,执行对表或队列的更新,在时间 6 执行另一个更新。在时间 7,消息流确定完成了所有需要在辅助事务下进行的更改并且落实这些更改。
如果在时间 7 之前消息流发生故障,则系统状态不会更改,因为两个事务都会回滚。如果在时间 7 之后但在时间 9 之前发生故障,说明已经落实了辅助事务,但会回滚主要事务。如果在时间 9 之前没有发生故障,则两个事务都会落实。
您可以使用多个辅助事务并且对可落实或回滚的数据库表进行多次更新。然后,您可以对相同或不同的数据库表进行其他更改,然后落实或回滚这些更改。
您所使用的每个数据库都有它自己的辅助事务;因此,如果消息流更新属于不同数据库实例(不同数据源名称)的表,则每个数据库会有一个辅助事务。您必须逐个落实或回滚这些事务。无论处理成功还是失败,任何在操作完成时(在上述示例中是时间 9)尚未落实或回滚的更新都由代理自动进行落实或回滚。
某些数据库类型(如 AIX 上的 DB2)不允许协调和非协调事务处于同一个数据库实例中。在这些情况下,必须创建不同的数据库实例。应该为协调事务配置一个数据库实例,为非协调事务配置另一个数据库实例。
使用 ESQL COMMIT 和 ROLLBACK 语句来落实和回滚辅助数据库事务。通过在单独的数据库语句(例如,INSERT 和 UPDATE 语句)上指定 UNCOORDINATED 关键字来获取主事务之外的操作。