如何模拟数据库失败以测试Java中的两阶段提交

And*_*ndy 11 java database websphere transactions 2phase-commit

我正在实施涉及分布式资源的两阶段提交.如何模拟参与数据库的失败?拔出网络电缆不起作用,因为它会导致表死锁.我目前在我的应用程序代码中使用钩子,它StaleConnectionException在查询执行之后抛出不同的点,就像查询执行之前一样.我对这种方法的关注是:

  • 有没有更好的方法来模拟数据库故障?
  • 当数据库连接变坏时,连接对象会发生什么?它是保留其价值还是变为空?
  • 当应用程序尝试重新连接到DB时实际发生了什么?连接对象获得了什么值?它是否使用连接池中的现有值?

我还想在中间点测试,例如在查询执行期间,提交期间(发送准备之后等).现在我将应用程序置于调试模式并进入函数调用并在其间插入插件.但这种方法是手动的,不适用于规模测试.

是否有模拟器/模拟器或工具可以帮助我这样做?

ewe*_*nli 5

这是很多问题:)我会尝试完成之前的答案。

Is there a better way to simulate the DB failure?
Run Code Online (Sandbox Code Playgroud)

测试所有情况都很复杂。测试主要情况的一种方法是创建 JCA 连接器(数据库驱动程序就是JCA 连接器)。您可以从将在事务中登记的连接器(第三个参与者)获取连接。连接可能会引发某些错误。

共有三个部分协同工作:(1) 应用程序,(2) 应用程序。服务器的事务管理器,以及 (3) jca 连接器(所谓的资源适配器)。

三部分之间的通信

连接通过将自身挂接到事务中ManagedConnection.getXAResource。使用自定义 jca 连接器,您可以向应用程序(Connection在图中)或应用程序服务器的事务管理器(XAResource通过ManagedConnection图中获得)引发异常。您可以在XAResource.prepare和期间抛出异常XAResource.commit,这对应于第二阶段提交 期间的错误。

请注意,很难控制参与者的征募顺序(请参阅此问题)。因此,很容易测试其中一个prepare失败(即您的失败),但很难控制它们的调用顺序。重现两阶段提交的所有可能的无效状态很复杂,特别是在考虑优化时。

(我曾经写过一个 JCA 连接器(http://code.google.com/p/txfs),如果您想要示例代码,还有其他连接器。)

What happens to the connection object when DB connection goes bad? 
Does it retain its value or does it become null?
Run Code Online (Sandbox Code Playgroud)

可以ManagedConnection通知事务管理器。其中一个通知是ConnectionEvent.CONNECTION_ERROR_OCCURRED通知它在使用此特定连接时发生错误。

正如其他答案中所述,每个事务通常有一个关联的托管连接。托管连接抽象了物理连接,您不想使用太多。应用程序仅获取“句柄”(Connection如图所示)。在一个给定事务中获得的句柄都指向同一个托管连接。这是大多数应用服务器支持的优化。

如果托管连接变得无效,则使用它的句柄也会变得无效。但据我所知,手柄不能被“刷新”。事务必须回滚,托管连接被破坏。当另一个事务启动时,它将与池中的另一个有效的托管连接相关联。

What actually happens when application tries to reconnect to DB?
What value does connection object get?
Does it use an existing value from the connection pool?
Run Code Online (Sandbox Code Playgroud)

应用程序服务器管理托管连接池。正如上一段所说,在使用过程中可能会变质。但如果不使用,也可能会变质。例如,池中已使用的托管连接可能会因为底层物理连接超时而变得无效。应用程序服务器通常具有在开始使用托管连接之前测试它是否有效的功能。如果没有,它将尝试池中的另一个托管连接,或创建一个新连接。


And*_*rej 1

也许您可以添加自己的资源来参与提交并在第一阶段之后暂停事务。与此同时,您可以“拔掉插头”。