PHP多个请求一次创建不正确的数据库条目

时间:2014-09-29 20:39:36

标签: php json multithreading object

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

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

除了下载和带宽不计数之外,我还遇到了一个问题,即我试图创建一个加载服务器对象的维护功能,并且没有将其保存为可能的几个分钟 - 这显然不会在下载过程中发挥作用并同时操纵服务器对象,因为在维护功能完成时它只会被旧数据覆盖。

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

我完全不知道如何在没有完全设计一个完全不同的新系统的情况下解决这个问题....这很糟糕。

关于我应该怎么做的任何想法都会很棒。

谢谢!

2 个答案:

答案 0 :(得分:1)

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

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

答案 1 :(得分:-1)

您可以尝试使用flock,我猜您在从DB获取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秒并尝试再次获得锁定,或者发送消息“只允许同时下载一次”或....