【问题标题】:PHP multiple requests at once are creating incorrect database entriesPHP一次多个请求正在创建不正确的数据库条目
【发布时间】:2014-09-29 20:39:35
【问题描述】:

我在这里运行的是一个图形文件管理器,类似于 OneDrive 或 OpenCloud 或类似的东西。文件、文件夹、帐户和主要服务器设置都作为 JSON 编码的对象存储在数据库中(是的,我确实删除了支持 json 的列)。问题是多个请求同时使用同一个对象,它通常会保存不正确的数据,因为请求显然无法相互传达更改。

例如,当有人开始下载时,它会加载该文件所有者的帐户对象,增加其带宽计数器,然后在下载结束时将其编码/保存回数据库。但是假设我一次下载了 3 次同一个文件,它们都会加载同一个帐户对象,根据需要更改数据,并保存他们的数据,而不考虑其他重叠的数据。在这种情况下,3 次下载将显示为 1。

除了下载和带宽不计其数之外,我还遇到了一个问题,我试图创建一个维护函数来加载服务器对象并且可能在几分钟内不保存它 - 这显然不会在进行下载并同时操作服务器对象时无法正常工作,因为当维护功能完成时,所有这些都将被旧数据覆盖。

基本上这是一个线程问题。我研究了 PHP APC,希望我可以让对象在线程之间全局持久化,但这不起作用,因为它只是为每个请求序列化/反序列化数据,而不是实际上让每个请求指向内存中的一个对象。

如果不完全设计一个完全不同的新系统,我完全不知道如何解决这个问题......这很糟糕。

任何关于我应该如何去做的想法都很棒。

谢谢!

【问题讨论】:

  • 需要更多地了解流程才能提供任何建议
  • 对象存储为 JSON。请求加载它们,进行更改并在几秒钟后将其保存回来。如果一次发生多个请求,请求 2 将在请求 1 更改数据之前加载数据,然后在将其保存回来时,它将覆盖请求 1 对其所做的任何事情。我不知道如何更好地表达它。
  • 核弹(从轨道上),重新开始
  • @user3068322 标准数据库结构?那么 SQL DBMS 的 ACID 保证会为您解决这个问题。
  • 您写回的内容之一是“下载”计数,而不是您有一个表格,您可以在其中为每次下载添加一行,当您需要时 - 您选择行数 -没有竞争条件

标签: php json multithreading object


【解决方案1】:

这不是线程问题。您的数据库不符合构建数据库的任何标准,甚至包括第一个范式:每个单元格必须只包含一个值。当您在 DB 中存储 JSON 数据时,您无法编写 SQL 请求来使该事务原子化。所以,是的,您需要将该代码放入垃圾箱。

如果您确实需要让该代码正常工作,您可以使用一些互斥锁来同步正在运行的 PHP 脚本。 PHP 中最常见的实现是file mutex

【讨论】:

    【解决方案2】:

    您可以尝试使用flock,我猜您在从数据库获取JSON 之前已经有一个用户ID。

    $lockfile = "/tmp/userlocks/$userid.txt";
    $fp = fopen($lockfile, "w+");
    if (flock($fp, LOCK_EX)) {
      //Do your JSON update
    
      flock($fp, LOCK_UN); //unlock
    }else{
       // lock exist 
    }
    

    你需要弄清楚当有锁时该怎么办,可能等待0.5秒并尝试再次获得锁,或者发送消息“只允许同时下载”或......

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-05-05
      • 1970-01-01
      • 2016-01-03
      • 1970-01-01
      • 1970-01-01
      • 2020-08-11
      • 1970-01-01
      相关资源
      最近更新 更多