我们已经实现了一个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
时,它们仍然非常方便。