如何在没有PHP Semaphore的情况下在PHP中实现信号量?

时间:2011-03-07 23:23:34

标签: php wordpress locking deadlock semaphore

问题:

如何在没有信号量包(http://php.net/manual/en/function.shm-get-var.php)的情况下在PHP中实现共享内存变量?

上下文

  • 我有一个简单的Web应用程序(实际上是WordPress的插件)
  • 这是一个网址
  • 然后检查数据库是否已存在该网址
  • 如果没有那么它会熄灭并做一些操作
  • 然后将记录写入数据库,并将url作为唯一条目

实际上发生的事情是4,5,6 ...会话同时请求url并且我在url的数据库中获得了9个重复的条目..(可能是9因为处理时间和数据库写入第一个条目需要足够的时间让其他9个请求通过)。之后,所有请求都会读取记录已存在的正确条目,这样就可以了。

由于它是一个WordPress插件,所有类型的共享主机平台上都会有许多用户使用PHP的可变编译/设置。

所以我正在寻找更通用的解决方案。我不能使用数据库或文本文件写入,因为这些将太慢。当我写入数据库时​​,下一个会话已经过去了。

fyi:数据库代码:http://plugins.svn.wordpress.org/wp-favicons/trunk/includes/server/plugins/metadata_favicon/inc/class-favicon.php

更新

在uri的新md5哈希上使用一个唯一键,并尝试捕获它似乎有效。

我找到了1个带

的重复条目
SELECT uri, COUNT( uri ) AS NumOccurrences
FROM edl40_21_wpfavicons_1
GROUP BY uri
HAVING (
COUNT( uri ) >1
)
LIMIT 0 , 30

所以我认为它没有用,但这是因为它们是:

http://en.wikipedia.org/wiki/Book_of_the_dead
http://en.wikipedia.org/wiki/Book_of_the_Dead

(首都咧嘴笑)

2 个答案:

答案 0 :(得分:3)

这可以通过MySQL实现。

您可以通过从读取访问锁定表来明确地执行此操作。这将阻止整个表的任何读访问,因此可能不是优选的。 http://dev.mysql.com/doc/refman/5.5/en/lock-tables.html

否则,如果表中的字段被归类为唯一,那么当下一个会话尝试将相同的URL写入表时会出现错误,您可以捕获该错误并继续,因为如果没有必要做任何事情,该条目已经存在。浪费的唯一时间是两个或多个会话创建相同URL的可能性,结果仍然是一条记录,因为数据库不会再次添加相同的唯一URL。

正如评论中所讨论的那样,因为URL的长度可能很长,固定长度的唯一散列可以帮助克服这个问题。

答案 1 :(得分:1)

PHP中还有其他共享内存模块(例如shmopAPC),但我认为您所说的是依赖于非标准/未预安装的问题库。

我的建议是,在你去做“其他操作”之前,你需要在数据库中创建一个条目,可能具有“编译”(或某种东西)的状态,因此你知道它仍然不可用。这样您就不会遇到多个条目的问题。我也确定你在可用时使用事务,因此你的提交是原子的。

然后,当您完成“其他操作”时,将数据库条目更新为“可用”并执行您需要执行的任何操作。