多个应用程序访问相同的数据

时间:2013-11-24 03:32:58

标签: php mysql database postgresql

所以我的团队正在用PHP开发API。 我主要担心的是2个人要求更新同一行的情况。

因此,如果一个API调用将执行读取然后处理信息然后写入,如果另一个API调用对同一行数据执行相同操作会发生什么。我们正在使用Postgres OR Mysql。

User has 100 dollars.
API Call 1 to ADD 20 1 reads 100.
API Call 2 to Subtract 20 reads 100.
API Call 1 writes 120;
API Call 2 write 80;( instead of 100);

我知道有一个涉及锁定表或行的解决方案,这会解决我的问题吗?

我需要一个解决方案,其中API调用2不会失败,而是等待或重试。

[编辑]

我应该进一步详细说明我们正在做的事情。这是一个浏览器mmo游戏,它有2个部分。 PHP REST API和Java服务器。

浏览器提供AJAX GET API调用。 :以4万美元建造工厂 PHP API检查是否有足够的资金,并返回JSON。所以 - 玩家需要4万美元。

我们的服务器标记使用boneCP来更新值,例如基金。

因此,从我之前的示例中,CALL 1将是我们的PHP API,而CALL 2将是服务器滴答。

2 个答案:

答案 0 :(得分:3)

您需要了解transactionstransaction isolationexplicit row-level locking

select ... for update

在您的情况下,还要考虑使用表达式。如果您发布了类似的内容,那么您的生活会更加简单:

update account set amount = amount - 20 where id = ?

答案 1 :(得分:2)

您的API设计糟糕,需要修复。而不是:

  1. 用户有100美元。
  2. API调用1到ADD 20 1读取100。
  3. API Call 2 to Subtract 20读取100。
  4. API Call 1写入120;
  5. API Call 2写80;(而不是100);
  6. 你应该有一个像:

    这样的流程
    1. 用户有100美元
    2. API调用1到“将20添加到帐户1”,因此帐户1从100更改为120并返回新值120
    3. API调用2至“从帐户1减去20”,因此帐户1从120更改为100并返回新值100
    4. 同样,如果您在两个帐户之间进行转移,则总是使用执行传输的API调用而不是执行添加,然后单独减去或删除反之亦然。

      换句话说,您需要重新设计API,以便在每次API调用的开始和结束时数据库状态保持一致。要确保使用多个SQL语句的API调用一致,即使在中途中止,您必须wrap the API call's work up in a transaction并且如果您不打算使用SERIALIZABLE隔离,请执行相应的SELECT ... FOR UPDATE命令如果您要在事务中进行读取 - 修改 - 写入。

      您需要通过客户端应用程序避免read-modify-write cycles

      在读取 - 修改 - 写入不可避免的情况下,两个或多个API调用必须保持一致,您应该使用optimistic concurrency control来防止更新冲突。在这种情况下,您的方案将如下所示:

      1. 用户有100美元。
      2. API Call 1读取帐户1,获取值100和rowversion 1
      3. API Call 2读取帐户1,获取值100和rowversion 1
      4. API调用1将20添加到获取值100,发送新值120和rowversion 1.成功,因为发送的rowversion等于数据库内的rowversion。
      5. API调用2从获取的值100中减去20,发送新值80和新的rowversion 1. 失败并返回错误,因为数据库rowversion比发送的rowversion更新,所以其他人修改了行因为我们拿走了它。第二个API调用者必须再次获取该行并重新尝试。