如何在开始/提交/回滚块内将更改写入数据库



我们已经实现了一个DB begin/commit/rollback系统,在该系统中,您可以在任何地方的代码中进行begin-begin/提交,如果在特定位置执行begin-commit时,您在另一个begin-/commit块中,那么它只会在您返回到第一级begin时执行提交。这是使用一个静态变量来完成的,该变量只记录您所在的begin/commit块的级别。每次遇到begin时,如果计数器为1,则会向DB发送一个begin,计数器会递增。若计数器大于1,则只递增计数器。类似地,如果请求提交,则计数器递减,并且只有在计数器为1的情况下,才会向数据库发送真正的commit命令。

首先,对这种方式有什么想法吗?长期以来,这对我们来说非常有效。然而,我们现在遇到的情况是,无论我们在开始/提交级别上处于什么位置,我们都需要将一些数据保存到数据库中。

人们通常是如何处理这一问题的?此外,我们对处理多级开始/提交的方式有什么想法?

顺便说一句,我们在PHP中使用postgres数据库来完成这项工作。

谢谢Ziad

您所描述的基本上是JTA(Java Transaction API)如何管理EJB3中的声明性事务作用域。将方法标记为需要一个事务,如果没有打开任何事务,则开始一个事务。事务结束由开始事务的方法的结束来描述。

然而,我们现在遇到的情况是,无论我们在开始/提交级别上处于什么位置,我们都需要将一些数据保存到数据库中。

不管怎样,你都需要一个新的连接,因为PostgreSQL不支持自主事务——暂停事务、做其他事情、恢复事务,或者只提交事务的一部分。

当您有一个称为REQUIRES_NEW的方法时,JTA通过在后台与服务器建立新的JDBC连接来处理此问题。该方法要求,即使有一个打开的事务,该事务也会被挂起,而是启动一个新的事务。由于PostgreSQL不支持这一点,JTA对其进行了模拟

你也会想这样做,我强烈建议你研究JTA是如何做事的。对于一个Java API来说,它是令人惊讶的不实用的。


PHP特有的因素:PHP喜欢缓存连接,因此多次连接尝试通常会返回相同的连接句柄。对pg_connect使用PGSQL_CONNECT_FORCE_NEW选项,或者(最好)使用PDO,PDO不会返回缓存的连接,除非您用PDO::ATTR_PERSISTENT明确告诉它。


顺便说一句,您可能不知道保存点。

如果看到嵌套的BEGIN,可以将其更改为SAVEPOINT [savepointname]。CCD_ 7变为CCD_。COMMIT只是RELEASE SAVEPOINT [savepointname],即"我不希望必须回滚到这一点,如果外部事务提交,那么我的事务应该提交"。

不过,保存点不是免费的,所以只有在有可能需要回滚子变速器操作时才应该使用它们。

如果外部事务回滚,您不能以保留的方式提交子事务,但当您运行可能作为大型、昂贵事务的一部分的ERROR时,它们仍然非常方便。

最新更新