13

我正在实施涉及分布式资源的两阶段提交。如何模拟参与数据库的故障?拔网线不起作用,因为它会导致表死锁。我目前在我的应用程序代码中使用钩子,这些钩子在StaleConnectionException查询执行之前和查询执行之后抛出不同的点。我对这种方法的担忧是:

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

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

有没有模拟器/模拟器或工具可以帮助我做到这一点?

4

4 回答 4

5

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

Is there a better way to simulate the DB failure?

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

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

三部分之间的通信

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

请注意,很难控制参与者的入伍顺序(请参阅此问题)。所以很容易测试其中一个prepare失败(即你的失败),但很难控制它们被调用的顺序。重现 2 阶段提交的所有可能的无效状态是复杂的,尤其是在进行优化时。

(我曾经写过一个 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?

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

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

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

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?

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

于 2012-04-26T06:43:12.213 回答
1

Andrej 回答了问题的一部分,所以让我回答第二部分。

您在应用程序中获得的 Connection 对象只是物理连接的包装器。该包装器在连接池和事务管理中发挥作用。如果数据库出现任何问题,连接包装器将无法使用,您只能回滚。这是有道理的,因为您只能在 2PC 启动之前访问连接,并且在 2PC 启动之前所做的任何事情都无法恢复。

请注意,尝试释放连接并获取新连接不会改变任何事情,因为一旦在事务中使用了来自给定数据源的连接,只要您在该数据源中,您将始终从该数据源获得相同的连接同一笔交易。这意味着您的应用程序无法在不重新启动整个事务的情况下“重新连接”。

另一方面,如果在所有资源都准备好之后但在所有资源提交之前出现问题,则事务管理器有责任恢复事务。但这发生在幕后,您的应用程序无法控制。同样在这一点上,您的应用程序应该已经释放了该事务中使用的所有连接。

于 2012-04-11T19:10:52.310 回答
1

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

于 2012-04-11T15:19:01.023 回答
0

您最好的选择可能是在内存数据库中使用。调用失败并检查前后数据源的状态,以确保回滚/提交正确执行。

至于您的其他问题,这些似乎是极高成本/低回报的测试。阅读您的供应商文档并确保您的事务环境配置正确。完成此操作后,您可能应该将其自动化,以便放手。

除非您编写自己的 2PC 协议特定事务管理器 + DB 实现,否则我会将这些功能的测试留给您的供应商。

于 2012-04-11T19:27:40.313 回答