代码之家  ›  专栏  ›  技术社区  ›  Mike Atlas

处理“异步”提交的好方法是什么?

  •  1
  • Mike Atlas  · 技术社区  · 15 年前

    我有一个使用 ODP.NET 从Oracle数据库中读取数据。该服务也会写入数据库,但间接地,因为所有更新和插入都是通过我通过COM+访问的较旧的业务逻辑层实现的,我将其包装在 TransactionScope . 旧层通过ODBC而不是odp.net连接到Oracle。

    我遇到的问题是,因为Oracle使用两阶段提交,并且因为旧的业务层使用的是ODBC而不是odp.net,所以事务 有时 返回 TransactionScope.Commit() 在数据实际可用于从服务层读取之前。

    我懂了 a similar post about a Java user having trouble like this 以及堆栈溢出。

    甲骨文代表 posted that there isn't much I can do about this 问题:

    这可能是因为Oletx itransaction::commit()方法的行为。 在2PC的第1阶段之后(即 准备阶段)如果全部成功, 即使资源 经理们还没有真正承诺 . 毕竟成功的“准备”是 保证资源管理者 在此之后不能任意中止 点。因此,即使资源 经理无法提交,因为它 没有收到“提交”通知 从MSDTC(应该说 通信故障),以及 组件的提交请求返回 成功地。如果从中选择行 您可以立即将桌子 有时会看到实际提交发生 在数据库中 执行了您的选择。您的选择将 因此,由于 一致的读取语义。有 在Oracle中我们对此无能为力 作为“承诺成功之后” 成功的第一阶段“优化是 MSDTC实现的一部分。

    所以,我的问题是:

    我应该如何处理可能的延迟(通过标题“asyc”)问题,确定2pc的第二部分何时实际发生,因此我可以确保我插入(间接)的数据在 Commit() 呼叫返回?

    大型系统如何处理数据可能无法立即读取的事实?

    1 回复  |  直到 15 年前
        1
  •  1
  •   djna    15 年前

    我假设整个事务已经准备好,并且提交结果由TransactionManager决定,因此最终(除非有启发式的破坏),资源管理器将收到它们的提交消息并完成。但是,对于可能需要多长时间(可能是几天),不应用超时,在准备资源管理器时已投票“提交”,没有任何保证。 必须 等待听到集体的结果。

    在这种情况下,最简单的方法是采用“理解,我们在思考”的方法。您的请求已被理解,但实际上您不知道结果,这就是您告诉用户的。是的,在所有正常情况下,请求都将完成,但在某些情况下,操作员实际上可以选择手动干预事务(这样做可能会导致启发式的损坏)。

    为了更进一步,您可以启动一个新事务并执行一些查询,以查看数据是否存在。现在,如果您正在填充一个结果屏幕,那么您自然会执行查询等操作。如果没有预期的结果,问题是该怎么做。因此,再次告诉用户“最近的请求正在处理中,点击刷新查看是否完成”。或者自动重试(我不太喜欢自动重试——更喜欢告诉用户它实际上是一个异步操作。)

    推荐文章