我有一个使用ODP.NET从Oracle数据库读取数据的WCF服务。该服务还会间接地写入数据库,因为所有更新和插入都是通过我通过COM +访问的旧层业务逻辑实现的,我将其包装在TransactionScope中。较旧的层通过ODBC连接到Oracle,而不是ODP.NET。
我遇到的问题是,由于Oracle使用两阶段提交,并且由于较旧的业务层使用的是ODBC而不是ODP.NET,因此事务有时会返回{{1在数据实际可用于从服务层读取之前。
我在Stack Overflow上也看到a similar post about a Java user having trouble like this。
来自Oracle posted that there isn't much I can do about this问题的代表:
这可能是由于OLETx的方式 ITransaction :: Commit()方法的行为。 在2PC的第1阶段之后(即 准备阶段)如果一切都成功, 即使资源,提交也可以返回 经理们没有真正承诺。 毕竟成功的“准备”是 保证资源管理者 在此之后不能随意中止 点。因此即使是资源 经理无法承诺,因为它 没有收到“提交”通知 来自MSDTC(由于说 沟通失败), 组件的提交请求返回 成功。如果从中选择行 您可以立即使用这些表格 有时看到实际的提交发生 你已经在数据库中 执行你的选择。你的选择会 因此,不会看到新的行 一致的读语义。有 我们在Oracle中无能为力 作为“继承之后的成功” 成功的第1阶段“优化是 MSDTC实施的一部分。
所以,我的问题是:
我应该如何处理可能的延迟(通过标题的“asyc”)问题,找出2PC的第二部分何时实际发生,所以我可以肯定我插入的数据(间接)实际上是可用的在TransactionScope.Commit()
调用返回后选择?
大型系统如何处理数据可能无法立即读取的事实?
答案 0 :(得分:1)
我假设整个事务已经准备好并且由TransactionManager决定提交结果,因此最终(除了启发式损坏)资源管理器将收到它们的提交消息并完成。但是,无法保证可能需要多长时间 - 可能是几天,没有超时适用,在准备资源管理器中投票“提交”必须等待听取集体结果。
在这些条件下,最简单的方法是采取“理解,我们正在思考”的方法。您的请求已被理解,但您实际上并不知道结果,这就是您告诉用户的内容。是的,在所有理智的情况下,请求将完成,但在某些情况下,操作员实际上可以选择手动干预交易(并且可能会导致启发式损坏。)
更进一步,您可以启动一个新事务并执行一些查询以查看数据是否存在。现在,如果要填充结果屏幕,您自然会进行查询等操作。问题是如果预期的结果不存在该怎么办。再次,告诉用户“您最近的请求正在处理中,点击刷新以查看它是否完整”。或者自动重试(我不太喜欢自动重试 - 更喜欢教育用户它实际上是异步操作。)