如何在begin / commit / rollback块中写入对数据库的更改

时间:2014-09-03 09:56:33

标签: php database postgresql

我们已经实现了一个数据库开始/提交/回滚系统,您可以在任何地方使用代码中的begin begin / commit,如果在特定位置执行begin / commit,则您在另一个begin / commit块中,然后它只会在你回到第一级开始时进行提交。这是使用静态变量完成的,该变量只保留您所在的开始/提交块级别的计数。每次遇到开始时,如果计数器为1,则将BEGIN发送到DB并且计数器递增。如果计数器大于1,则仅递增计数器。类似地,如果请求提交,则计数器递减,并且只有在计数器为1的情况下,才会向数据库发送实际的COMMIT命令。

首先,有关这种方式的想法吗?这对我们来说已经很长时间了。但是,我们现在遇到的情况是,我们需要将一些数据保存到数据库,而不管我们在开始/提交级别方面的位置。

人们如何处理这个问题?关于我们处理多级开始/提交的方式还有什么想法?

顺便说一下,我们在PHP中使用postgres数据库进行此操作。

由于 齐亚德

1 个答案:

答案 0 :(得分:3)

您所描述的几乎是JTA(Java Transaction API)如何管理EJB3中的声明性事务范围。您将方法标记为需要事务,如果没有事务处于打开状态,则会开始。交易结束由开始交易的方法结束描述。

  

但是,我们现在遇到的情况是,我们确实需要将一些数据保存到数据库,而不管我们在开始/提交级别方面的位置。

您将需要以某种方式建立新连接,因为PostgreSQL不支持自治事务 - 暂停事务,执行其他操作,恢复事务,或者仅提交部分事务事务。

当你有一个方法说明它REQUIRES_NEW时,JTA通过在幕后与服务器建立新的JDBC连接来处理这个问题。该方法要求即使有一个打开的事务,该事务被挂起并且启动一个新事务。由于PostgreSQL不支持,JTA会模仿它。

您也希望这样做,我强烈建议您研究JTA​​如何做事。对于Java API来说,它非常糟糕。


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


顺便说一下,你可能不知道保存点。

如果您看到嵌套的BEGIN,则可以将其更改为SAVEPOINT [savepointname]ROLLBACK成为ROLLBACK TO SAVEPOINT [savepointname]COMMIT只是RELEASE SAVEPOINT [savepointname] - 即“我不希望回滚到此,如果外部事务提交则我的应该是”。

保存点不是免费的,所以只有在你可能真的需要回滚子事务时才应该使用它们。

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

相关问题