Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/249.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/61.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 多个应用程序访问同一数据_Php_Mysql_Database_Postgresql - Fatal编程技术网

Php 多个应用程序访问同一数据

Php 多个应用程序访问同一数据,php,mysql,database,postgresql,Php,Mysql,Database,Postgresql,所以我的团队正在用PHP开发一个API。 我主要关心的是两个人打电话更新同一行时会发生什么 因此,如果一个API调用先读取然后处理信息,然后写入,那么如果另一个API调用对同一行数据执行相同的操作,会发生什么情况。我们正在使用Postgres或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 Ca

所以我的团队正在用PHP开发一个API。 我主要关心的是两个人打电话更新同一行时会发生什么

因此,如果一个API调用先读取然后处理信息,然后写入,那么如果另一个API调用对同一行数据执行相同的操作,会发生什么情况。我们正在使用Postgres或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游戏,它有两个部分。一个PHP REST API和Java服务器

该浏览器使AJAX获得API调用,例如:以4万美元的价格构建工厂 PHP API检查是否有足够的资金,并返回JSON。所以-玩家提供4万美元

我们的服务器使用boneCP进行并发数据库调用,以更新资金等价值

因此,从我前面的示例中,调用1将是我们的PHP API,调用2将是服务器标记。

您需要了解,并且:

在您的情况下,还要考虑使用表达式。如果你发布以下信息,你的生活会简单得多:

update account set amount = amount - 20 where id = ?
您需要了解,以及:

在您的情况下,还要考虑使用表达式。如果你发布以下信息,你的生活会简单得多:

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

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

  • 用户有100美元
  • API调用1添加20 1读取100
  • API调用2减去20读取100
  • API调用1写入120
  • API调用2写80;(而不是100) 相反,您应该有如下流:

  • 用户有100美元
  • API调用1“将20添加到帐户1”,因此帐户1从100更改为120并返回新值120
  • API调用2“从帐户1中减去20”,因此帐户1从120变为100,并返回新值100
  • 类似地,如果您在两个帐户之间进行转账,您将始终使用进行转账的API调用,而不是执行加法,然后使用单独的减法,反之亦然

    换句话说,您需要重新设计API,以便在每个API调用的开始和结束时,数据库状态保持一致。要确保使用多个SQL语句的API调用是一致的,即使中途中止,您必须这样做,如果您不打算使用
    SERIALIZABLE
    隔离,请执行适当的
    SELECT。。。对于更新
    命令,如果要在事务中执行读-修改-写操作

    您需要避免由客户端应用程序执行

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

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

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

  • 用户有100美元
  • API调用1添加20 1读取100
  • API调用2减去20读取100
  • API调用1写入120
  • API调用2写80;(而不是100) 相反,您应该有如下流:

  • 用户有100美元
  • API调用1“将20添加到帐户1”,因此帐户1从100更改为120并返回新值120
  • API调用2“从帐户1中减去20”,因此帐户1从120变为100,并返回新值100
  • 类似地,如果您在两个帐户之间进行转账,您将始终使用进行转账的API调用,而不是执行加法,然后使用单独的减法,反之亦然

    换句话说,您需要重新设计API,以便在每个API调用的开始和结束时,数据库状态保持一致。要确保使用多个SQL语句的API调用是一致的,即使中途中止,您必须这样做,如果您不打算使用
    SERIALIZABLE
    隔离,请执行适当的
    SELECT。。。对于更新
    命令,如果要在事务中执行读-修改-写操作

    您需要避免由客户端应用程序执行

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

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

  • 重新考虑酸的性质,并确保它们得到保存。之后,使用可序列化隔离级别检查SS2PL和Postgres将防止您写入错误的值(尽管您必须处理错误),重新考虑ACID属性并确保它们被保留。之后,使用可序列化隔离级别检查SS2PLWith Postgres将防止您写入错误的值(您必须处理