首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >多数据库事务

多数据库事务
EN

Stack Overflow用户
提问于 2009-02-18 09:06:41
回答 8查看 2.6K关注 0票数 6

在我的PHP应用程序(使用symfony框架和Propel ORM构建)中,当我向MYSQL数据库添加记录时,需要使用外部供应商提供的web服务API更新外部MYSQL数据库。

问题是维护数据库完整性的最佳实践是什么。例如,如果第一次更新是成功的,而第二次更新是不成功的,由于web服务不可用,我必须能够

  1. 回滚第一次更新的事务,或者
  2. 缓存对web服务的调用,并一直调用web服务,直到服务可用为止,
  3. 还有其他一些可以维护多个数据库完整性的技术。

具体来说,我正在寻找语法,比如

代码语言:javascript
复制
void RootMethod()
{
     using(TransactionScope scope = new TransactionScope())
     {
        try
         { 
          SomeMethod();
          scope.Complete();
          CallWebService();
         }
         catch
         {
             scope.abort();
          }
     }
}

但不确定是否

  1. 这是一种很好的技术
  2. 或者在塞福尼和C#

都是可行的

你认为如何?

编辑:有人问我为什么需要两个部分的更新。这是因为我正在创建一个前端应用程序,连接到现有的后端应用程序。我不想改变后端应用程序。因此,不可避免地会有一些重叠。因此,需要同步数据

另一个编辑:两个部件事务必须一起完成,执行cron任务来同步表是不可取的

EN

回答 8

Stack Overflow用户

回答已采纳

发布于 2009-02-22 03:24:17

这会很棘手的。您需要两个阶段提交一个可靠的解决方案,但这将需要大量的工作来实现您的特定需求。

也许实际上并不需要一个很好的解决方案。你在困难的性能约束下吗?一般来说,交易的时间应该很短.但也许你应该在webservice电话会议前后保持交易开放?这将降低数据库的总体吞吐量(至少).但这可能是完全可以接受的。

您展示的方法在处理硬系统故障(电源故障、硬件故障等)时会遇到问题。要解决这个问题,您需要在主数据库和后台进程/启动过程中添加跟踪,以处理故障。很难做,但肯定是有可能的。

有些失败可能最终无法修复(第一部分成功,第二部分失败,第一部分由于另一个事务更新了相同的数据而无法撤消)。这完全取决于你的精确的商业规则。会计系统将是最简单的,因为撤销事务实际上是作为替代记录而不是更新来完成的。

祝好运。

票数 4
EN

Stack Overflow用户

发布于 2009-02-23 11:32:43

最大的问题是对web服务的重复更新是否重要,以及它们是否能够被检测到。如果您可以检测到重复项(通常具有唯一的事务号),或者重复项不重要,那么您可以构建一种可靠的两阶段提交样式方法。

如果无法检测到web服务的重复事务,并且更新不是幂等的,那么您就倒霉了。

这是基本的算法:

代码语言:javascript
复制
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;

然后,您需要一个常规的任务、线程或其他类似的任务:

代码语言:javascript
复制
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服务完成之后,但在第二次提交完成之前,

  • A失败:恢复任务检测到重复的web服务事务,本地记录在恢复任务中为:本质上与第二个web服务事务中的故障相同。

其他说明:

  • 是一种渐进的后退方法,对于失败很有用.如果某个服务出现了暂时故障,您想要减慢重试速度。如果您对外部服务有排序要求,您可能需要一些关于如何实现恢复任务的附加structure.
  • Depending,您可以将web服务调用留给该任务,而不是在主应用程序流中有第二个事务。

对附加要求的响应:“两个部件事务必须一起完成,执行cron任务以同步表是不可取的”

我对这一要求的解读是:“这两个制度不应该失败。”

当其中一个或两个系统发生故障时,您需要一些东西来收拾残局并调和问题。您可以使用成熟的TP监视器进行事务协调,也可以构建一个简单的监视器,如我的示例中处理特定情况的监视器。无论哪种方式,都有一些东西可以跟踪正在发生的事情,以便在发生故障后能够正确地解决问题。

如果您的需求确实是总是同时发生(并且事务性消息队列或两阶段提交方法对您不起作用),那么最好将两个系统的数据存储在同一个数据库中(也称为“资源管理器”),并拥有一个单一的资源管理器事务。

如果您确实得到了一个解决此问题的解决方案,该解决方案满足了在多个事务中具有两个独立的系统一致的要求,并且在失败后永远不需要后续的协调,那么您应该编写它并将其发表在VLDB日志、ACM TODS或IEEE TKDE中。

票数 5
EN

Stack Overflow用户

发布于 2009-02-24 18:10:25

我不认为回过头来对形势有任何帮助。如果您的web服务被关闭,更多的调用只会使问题更加复杂,那么您必须担心您的回滚是否通过等等。

我会用预定的全同步来做这件事。你的错误幅度是多少?您愿意让数据库稍微不同步吗?多少钱?如果每天晚上都运行一个同步器来解决出现的问题,会不会是件大事呢?你要担心的web服务有多长时间一次?

对于失败的web服务调用,更新队列是一个不错的主意,但是如果您的web服务被关闭了,那么可能一次就会有大量的更新队列,而不仅仅是一两次,所以您最好还是在中断后进行完全同步。

你的答案取决于这些问题。不要误以为你的整个程序会崩溃,如果事情是0.01%的不同步10分钟。找出错误的可接受范围是什么。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/560326

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档