处理现实世界中的交易

时间:2010-12-09 03:59:41

标签: php mysql transactions

我正在重写这个问题,因为它没有回复。

我正在试图找出使用数据库事务的正确方法。我所看到的关于如何进行交易的所有内容都是非常基本的,如下所示:

  1. 查询“开始”以开始交易
  2. 运行您的查询。
  3. 如果一切正常,请提交交易。
  4. 我明白了,但这是错误(死锁)处理我没有得到。我听说过两个选择:

    1. 向用户显示错误并说“再试一次”
    2. 在现场再试一次,直至成功。
    3. 对我而言,告诉用户因为这样的技术问题再次尝试似乎很糟糕 - 真正的应用程序是否经常这样做?那是我有时看到的“哎呀,出了什么问题”的一次性错误吗?这适用于网站,因此用户甚至不应该知道数据库。

      所以我有几个问题:

      1. 我应该采用哪种故障处理方法同时处理涉及多个用户的数据?
      2. 如果我执行“即时重试”选项,那么复杂的PHP脚本需要什么?从顶部重新启动整个请求?我担心这会导致比解决的问题更多的问题。
      3. 我还没有看到第三种选择吗?

3 个答案:

答案 0 :(得分:1)

我使用的解决方案是重试循环,让我们说3(我认为在大多数应用程序的现实生活中我没有超过1次重试)。在这个循环中,必须完成事务的所有请求,即写请求,以及读请求。

一个非常重要的一点是在事务中执行 请求,因为这会设置锁定,这是将数据置于实际隔离级别的唯一方法。

然后所有这些请求都在一个开始/提交块中,带有try / catch。在catch部分,我运行回滚,然后重新抛出异常。

通过重新抛出异常,您可以在更高级别捕获它,这是您可以决定重新运行的级别(3次循环)或将其发送给用户。

根据您的应用程序编码方式,有几种解决方案可以很好地解决这个问题:

  • 使用负责begin / commit / rollack的transactionManager对象,事务中的所有查询
  • 获取规则,例如'所有事务都由控制器处理,没有DAO或DB级对象知道是否有正在运行的事务
  • 您甚至可以使用只有transactionManager使用的专用数据库连接(具有写权限),并保留原始的只读数据库连接以用于其他事情。

答案 1 :(得分:0)

交易过程中的死锁通常表明您正在尝试更新其他人同时更新的内容。具体如何处理将特定于用户执行的操作。

在某些情况下它不会出现问题,你会重试这个操作,但我认为在大多数情况下你会产生一个错误给用户,因为你知道哪个更新是“正确的”之一。

答案 2 :(得分:0)

这里列出了一些你没有提及的事情:

http://dev.mysql.com/doc/refman/5.0/en/innodb-deadlocks.html