所以我的团队正在用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将是服务器滴答。
答案 0 :(得分:3)
您需要了解transactions,transaction isolation和explicit row-level locking:
select ... for update
在您的情况下,还要考虑使用表达式。如果您发布了类似的内容,那么您的生活会更加简单:
update account set amount = amount - 20 where id = ?
答案 1 :(得分:2)
您的API设计糟糕,需要修复。而不是:
你应该有一个像:
这样的流程同样,如果您在两个帐户之间进行转移,则总是使用执行传输的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来防止更新冲突。在这种情况下,您的方案将如下所示: