跨许多PHP请求的MySQL事务

时间:2009-11-21 22:07:55

标签: php mysql transactions

我想创建一个用于以类似事务的方式处理发票的界面。

数据库包含一张发票表和一张invoice_lines表,发票表中包含结算信息,invoice_lines表包含发票的订单项。该网站是一组脚本,允许添加,修改和删除发票及其相应的行。

我遇到的问题是,我希望数据库的ACID属性能够反映在Web应用程序中。

  • Atomic :当用户点击保存时,修改整个发票或根本不更改整个发票。
  • 一致:应用程序代码已确保一致性,无法将行添加到不存在的发票中。发票ID不能重复。
  • 隔离:如果用户正在对发票进行一组更改,我希望在用户点击保存之前隐藏其他用户的更改。
  • 持久:如果网站死亡,数据应该是安全的。这已经有效了。

如果我正在编写桌面应用程序,它将始终保持与MySQL数据库的连接,允许我在编辑的开头和结尾简单地使用BEGIN TRANSACTION和COMMIT。

根据我的理解,你不能在一个PHP页面上进行交易,而在另一个页面上进行COMMIT,因为页面之间的连接是关闭的。

有没有办法在没有扩展的情况下实现这一目标?根据我的发现,只有SQL Relay执行此操作(但它是一个扩展名)。

6 个答案:

答案 0 :(得分:7)

您不希望长时间运行事务,因为这会限制并发性。 http://en.wikipedia.org/wiki/Command_pattern

答案 1 :(得分:4)

此类处理的网络翻译是使用会话数据或页面本身存储的数据。通常所做的是,在每个网页完成之后,数据被存储在会话中(或页面本身中)以及所有页面已经完成的点(通过数据输入)和“处理”(点击或“保存”按钮,数据被转换为数据库表格并保存 - 即使你提到的数据的关系方面。有很多方法可以做到这一点,但我想说大多数开发人员都有类似于我提到的架构(使用会话数据或页面中的状态)来满足你所说的。

你会在不同的架构上得到很多建议,但我可以说Zend框架(http://framework.zend.com)和Doctrine(http://www.doctrine-project.org/)的使用使这个仙女变得容易,因为Zend提供了大量的MVC架构和会话管理以及Doctrine提供了您正在寻找的基本CRUD(创建,检索,更新,删除) - 以及所有其他方面(唯一性,提交,回滚等)。保持连接对mysql开放可能会导致超时和缺少可用的连接。

答案 2 :(得分:2)

数据库事务并非真正用于此目的 - 如果您确实使用它们,则可能会遇到其他问题。

但您也不能使用它们,因为每个页面请求都使用自己的连接(可能),因此无法与任何其他页面共享事务。

在用户编辑发票时,在其他地方保留对发票的修改,然后在她点击保存时应用它们;你可以在一个交易中做最后的申请步骤(尽管这个步骤很短暂)。

长期交易通常很糟糕。

答案 3 :(得分:1)

解决方案不是在GET阶段打开交易。在“保存”按钮触发POST期间,执行事务的所有方面 - BEGIN TRANSACTION,processing和COMMIT-all。

答案 4 :(得分:0)

持久连接可以帮助您: http://php.net/manual/en/features.persistent-connections.php

  

另一个是使用时   交易,交易块会   也转到下一个脚本   如果脚本使用该连接   执行在交易之前结束   块确实。

但我建议你找另一种解决问题的方法。 例如:创建缓存表。 当您需要“提交”时,将记录从缓存表传输到“真实”表。

答案 5 :(得分:0)

尽管有一些很好的答案,我认为对你的问题找到了一些好的回答,我也被困在了。我认为最好的方法是使用像Doctrine(O / R映射)这样的框架,这种方法以某种方式实现。 Here你有我正在谈论的内容的链接。