在我的PHP应用程序(使用symfony框架和Propel ORM构建)中,当我向MYSQL数据库添加记录时,需要使用外部供应商提供的web服务API更新外部MYSQL数据库。
问题是维护数据库完整性的最佳实践是什么。例如,如果第一次更新是成功的,而第二次更新是不成功的,由于web服务不可用,我必须能够
具体来说,我正在寻找语法,比如
void RootMethod()
{
using(TransactionScope scope = new TransactionScope())
{
try
{
SomeMethod();
scope.Complete();
CallWebService();
}
catch
{
scope.abort();
}
}
}但不确定是否
都是可行的
你认为如何?
编辑:有人问我为什么需要两个部分的更新。这是因为我正在创建一个前端应用程序,连接到现有的后端应用程序。我不想改变后端应用程序。因此,不可避免地会有一些重叠。因此,需要同步数据。
另一个编辑:两个部件事务必须一起完成,执行cron任务来同步表是不可取的。
发布于 2009-02-22 03:24:17
这会很棘手的。您需要两个阶段提交一个可靠的解决方案,但这将需要大量的工作来实现您的特定需求。
也许实际上并不需要一个很好的解决方案。你在困难的性能约束下吗?一般来说,交易的时间应该很短.但也许你应该在webservice电话会议前后保持交易开放?这将降低数据库的总体吞吐量(至少).但这可能是完全可以接受的。
您展示的方法在处理硬系统故障(电源故障、硬件故障等)时会遇到问题。要解决这个问题,您需要在主数据库和后台进程/启动过程中添加跟踪,以处理故障。很难做,但肯定是有可能的。
有些失败可能最终无法修复(第一部分成功,第二部分失败,第一部分由于另一个事务更新了相同的数据而无法撤消)。这完全取决于你的精确的商业规则。会计系统将是最简单的,因为撤销事务实际上是作为替代记录而不是更新来完成的。
祝好运。
发布于 2009-02-23 11:32:43
最大的问题是对web服务的重复更新是否重要,以及它们是否能够被检测到。如果您可以检测到重复项(通常具有唯一的事务号),或者重复项不重要,那么您可以构建一种可靠的两阶段提交样式方法。
如果无法检测到web服务的重复事务,并且更新不是幂等的,那么您就倒霉了。
这是基本的算法:
begin transaction;
do local work;
save information for external call;
set an appropriate time for next attempt;
mark external call as not performed;
commit work;
begin transaction;
make external call;
if successful
mark external call as performed (or delete the record)
else
set the time for the next attempt
commit;然后,您需要一个常规的任务、线程或其他类似的任务:
for each record where the time for the next attempt <= now
begin work;
if the remote service has not performed this transaction
make the remote call;
if successful
mark as done;
else if too many attempts
mark the transaction as permanently failed;
alert operator;
else
set the time for the next attempt;
endif
else
mark as done;
endif
commit;
endfor该方法可靠地处理所有故障条件,并确保最终完成这两项工作。
基本的失败:
在第一次提交完成之前失败:一切都回滚。在第一次提交之后,但在web服务完成之前(这包括web服务本身的瞬态故障):远程transaction.服务事务由恢复任务重放。在web服务完成之后,但在第二次提交完成之前,
其他说明:
对附加要求的响应:“两个部件事务必须一起完成,执行cron任务以同步表是不可取的”
我对这一要求的解读是:“这两个制度不应该失败。”
当其中一个或两个系统发生故障时,您需要一些东西来收拾残局并调和问题。您可以使用成熟的TP监视器进行事务协调,也可以构建一个简单的监视器,如我的示例中处理特定情况的监视器。无论哪种方式,都有一些东西可以跟踪正在发生的事情,以便在发生故障后能够正确地解决问题。
如果您的需求确实是总是同时发生(并且事务性消息队列或两阶段提交方法对您不起作用),那么最好将两个系统的数据存储在同一个数据库中(也称为“资源管理器”),并拥有一个单一的资源管理器事务。
如果您确实得到了一个解决此问题的解决方案,该解决方案满足了在多个事务中具有两个独立的系统一致的要求,并且在失败后永远不需要后续的协调,那么您应该编写它并将其发表在VLDB日志、ACM TODS或IEEE TKDE中。
发布于 2009-02-24 18:10:25
我不认为回过头来对形势有任何帮助。如果您的web服务被关闭,更多的调用只会使问题更加复杂,那么您必须担心您的回滚是否通过等等。
我会用预定的全同步来做这件事。你的错误幅度是多少?您愿意让数据库稍微不同步吗?多少钱?如果每天晚上都运行一个同步器来解决出现的问题,会不会是件大事呢?你要担心的web服务有多长时间一次?
对于失败的web服务调用,更新队列是一个不错的主意,但是如果您的web服务被关闭了,那么可能一次就会有大量的更新队列,而不仅仅是一两次,所以您最好还是在中断后进行完全同步。
你的答案取决于这些问题。不要误以为你的整个程序会崩溃,如果事情是0.01%的不同步10分钟。找出错误的可接受范围是什么。
https://stackoverflow.com/questions/560326
复制相似问题