在我的PHP应用程序(使用symfony框架和Propel ORM构建)中,当我向MYSQL数据库添加记录时,我需要使用外部供应商提供的Web服务API更新外部MYSQL数据库.
问题是维护数据库完整性的最佳实践是什么.举例来说,如果第一次更新成功,而第二次更新不成功,由于Web服务不可用,我必须能够
回滚第一次更新的事务,或
缓存对Web服务的调用,并继续调用Web服务,直到服务可用
一些其他可以保持多个数据库完整性的技术.
具体来说,我正在寻找类似的语法
void RootMethod() { using(TransactionScope scope = new TransactionScope()) { try { SomeMethod(); scope.Complete(); CallWebService(); } catch { scope.abort(); } } }
但不确定是否
这是一个很好的技术
或者这在symfony中是可行的,就像在C#中一样
你怎么看?
编辑:有些人问我为什么需要两部分更新.这是因为我正在创建一个连接到现有后端应用程序的前端应用程序.我不想改变后端应用程序.因此不可避免地会有一些重叠.因此需要同步数据
另一个编辑:两部分事务必须一起完成,做一个cron作业同步表是不可取的
最大的问题是对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服务本身中的短暂故障):远程Web服务事务由恢复任务重播。
Web服务完成之后但第二次提交完成之前发生故障:恢复任务检测到重复的Web服务事务,并且使本地记录出队。
恢复任务中的失败:与第二个事务中的失败基本相同。
其他说明:
渐进的退避方法对于失败很有用。如果服务暂时出现故障,则需要减慢重试的时间。
如果您对外部服务有订购要求,则可能需要一些其他结构。
根据执行恢复任务的方式,您可以仅将Web服务调用留给该任务,而在主应用程序流中不包含第二个事务。
对附加要求的响应:“两个部分的事务必须一起完成,不希望执行cron作业来同步表”
我对这一要求的理解是:“这两个系统永远都不会失败。”
当一个或两个系统发生故障时,您需要采取一些措施来解决问题并进行协调。您可以使用成熟的TP监视器来进行事务协调,也可以构建一个简单的监视器,例如本例中处理特定情况的监视器。无论哪种方式,都可以跟踪发生的事情,以便在出现故障后可以正确解决问题。
如果您的需求确实是总是在一起发生(并且事务性消息队列或两阶段提交方法不适合您),那么最好将两个系统的数据存储在同一数据库中(也称为“资源管理器”) )并进行一次资源管理器交易。
如果您确实找到了一个解决方案,该解决方案满足了使两个独立的系统在多个事务中保持一致并且在故障发生后不再需要对帐的要求,则应将其记录下来并发布在《 VLDB Journal》,《 ACM TODS》或《 IEEE TKDE》中。