所有请求之间的PHP关键部分

时间:2011-10-19 12:50:44

标签: php synchronization

我正在使用php建立一个网站,我想在其中出售一些费用数字。对于每个请求,我必须执行原子操作:

  • 向数据库询问可用的费用编号
  • 将费用编号标记为已售出
  • 增加一个数字(在文件或数据库中),显示客户的数量有一个收费号

我知道如何进行这些操作,如果有帮助,我使用的是mysql。但我的问题是如何在所有请求之间做这些操作原子?我是说如何强制web服务器(apache)和php解释器为所有请求逐个运行这个部分,而不是以并行方式运行?

P.s:请通过php解决问题,而不是与数据库相关的解决方案。

3 个答案:

答案 0 :(得分:5)

所有这些操作都依赖于数据库。因此,您并不需要在关键部分中运行PHP代码;它足以在数据库中序列化这些操作。

执行此操作时,最简单的方法是LOCK TABLES ... WRITE;这保证了只有一个脚本可以同时与数据库通信。

另一种方法是SET TRANSACTION ISOLATION LEVEL SERIALIZABLE并在关闭自动提交的事务中运行所有操作(即使您决定使用表锁,也应该使用事务来确保数据完整性。)

更新:如果您绝对必须在PHP中执行此操作,那么您可以使用flock实现目标:

$fp = fopen('sunc_file', 'r+');
if (flock($fp, LOCK_EX)) {
    // Perform database ops here
    flock($fp, LOCK_UN); // release the lock
}
else {
    die("Couldn't get the lock!");
}
fclose($fp);
独占模式下的

flock将阻止任何其他进程锁定保护文件,从而让您的脚本执行严格序列化,但请阅读手册页上的巨红警告!< / p>

答案 1 :(得分:5)

使用面向PHP的解决方案是不利的,而且你只能在一台机器上保证这一点。您当然可以将其锁定到关键区域中的单个进程,但仅限于一台计算机上。如果你有2个前端apache / php服务器和一个后端mysql服务器,这个解决方案将失败。到目前为止,MySQL事务是更好的解决方案..

然而,想象只有一台机器运行此代码,可以使用Jon发布的解决方案(使用文件作为锁),或者如果您使用的是linux / unix服务器,也可以使用IPC方法,创建一个长度为1(互斥锁)的系统V信号量。

# in your scripts setup/init phase:
define('MUTEX_KEY', 123456); # the key to access you unique semaphore
sem_get( MUTEX_KEY, 1, 0666, 1 );
# later on, you reach the critical section:
# sem_acquire will block until the mutex has become availible
sem_acquire( ($resource = sem_get( MUTEX_KEY )) );
# queries here ...
sem_release( $resource );
# now that sem_release has been called, the next processes that was blocked
# on the sem_acquire call may enter the critical region

虽然基于文件的解决方案更具可移植性(适用于Windows服务器),但是mutex / sem_ *解决方案更快更安全(auto_release,例如,如果某个应用程序由于某种原因在关键区域崩溃不会阻止所有进一步的请求)

干杯

答案 2 :(得分:-1)

以下是关键部分http://www.bogan.cz/programovani/kriticka-sekce-v-php/的示例代码。寻找代码部分。