Doctrine实体管理器和多个线程更新数据库

时间:2012-02-27 21:55:12

标签: php concurrency doctrine symfony

我目前有一个XHR请求可以从客户端触发N次。此请求由服务器处理,每个请求通常在数据库中创建一个新行(所有doctrine / xml)。

在我坚持()对象之前,我确定是否有一个唯一的文件名(我正在上传资源),我这样做是通过覆盖persist(),调用我的getUniqueFilename()然后调用parent :: persist。

当我执行具有相同文件名的多个XHR请求时,我遇到了竞争条件。如果多个线程在同一时间运行并检查数据库是否有重复项以生成唯一文件名,会发生什么。

  • 上传文件
  • 检查数据库是否存在文件名
  • 增加文件名(例如:filename_1)

但是,当多个线程中发生多个XHR请求时,会发生竞争条件,其中多个文件以相同的名称插入数据库(filename_1多次生成)。

我认为解决这个问题的方法是

  • 一个mysql触发器
  • 为表格添加唯一约束,并在代码中包含try / catch

你会做什么?

2 个答案:

答案 0 :(得分:4)

添加唯一约束是确保数据一致的最安全方法。 PHP级别的任何内容都可能具有某些竞争条件,除非您有其他形式的锁定,效率会降低。

您还可以通过确保文件名使用其他属性(例如来自用户的文件名)或保留版本历史记录来使其看起来几乎同时出现新版本,从而避免此问题。< / p>

答案 1 :(得分:2)

我建议使用不同的策略:使用mysql auto_increment获取id,将资产保存到数据库,检索id,然后将其添加到文件名中。所有其他方法都有缺点,你必须执行部分回滚,处理出版的文件名等。

我还建议不要使用原始文件名来存储对象:在不同的操作系统上遇到禁用字符以及字符编码的麻烦,可能由于某些原因而被公开(例如因为数据库是case_sensitive所在的文件系统不是)。可能还有其他一些缺点,例如最大文件名长度等,您现在可能还不知道。

我的解决方案是使用mysql自动增量作为文件名。如果你考虑它就有意义了。自动增量用作唯一的idenfitier。如果您确保只将一个表中的故事对象放到一个文件夹中,那么识别不同的资产,文件名等就没有问题。

如果你坚持按照自己的方式行事,你可以在数据库中使文件名唯一,然后按照你的建议重新启动失败的同花。