3

在我的 PHP 代码中,我打开一个文件并向其附加文本。我使用这段代码:

$ourFileHandle = fopen($ourFileName, 'a') or die("can't open file");

加载 PHP 页面时会发生这种情况。现在如果两个人同时加载 PHP 页面会发生什么?此代码是否适用于其中一个人,而对于另一个人,它会执行die()吗?一般来说,什么时候会fopen失败?

谢谢。

4

3 回答 3

6

TL;DR - 只需使用数据库

这不是一个简单的主题。对于多个并发请求,您正在做的事情肯定不会按预期工作,因为大多数系统将允许所有请求打开文件,并且可能多个脚本将能够同时写入文件,您最终可能会如果你这样做,文件中有垃圾。

可能的解决方法很多,但我将在这里介绍我认为最可行的三个。

  1. 使用数据库。这几乎可以肯定是您尝试做的任何事情的最佳解决方案。RDBMS 将毫不犹豫地处理所有这些并发问题,如果您这样做,您将永远不会遇到任何并发问题。

  2. 使用 请求对文件的排他锁flock()。此功能使用咨询锁定来防止多个并发进程同时访问文件。这将满足您对多个 PHP 进程的需求,但如果其他外部程序不支持 PHP 使用的同一类型的咨询锁定系统,它可能无法与其他外部程序一起使用。
    flock()“阻塞”,直到在文件上获得锁定。这意味着它会损害请求的并发性——一次只有一个请求能够写入文件。此外,它不能保证锁会按照它们被请求的顺序提供服务,因此您可能最终会遇到这样一种情况,即一个请求永远不会获得文件上的锁,而后来到达的其他请求却得到满足。

  3. 使用后台进程来处理文件访问,并让您的脚本与该进程进行通信。这有点像滚动你自己的 1) 版本,它不适合胆小的人,但如果做得正确,它可以发挥很大的作用。
    使用此模型,可以使用某种形式的进程间通信将需要写入文件的数据中继到后台(持久)进程。然后,此后台进程管理对文件的写入,确保消息以正确的顺序完整写入。通常(当使用 PHP 时)此类 IPC 将使用套接字实现。这是非常重要的,但可能是最强大的解决方案。


从更一般的角度来看,fopen()通常由于权限问题或低级操作系统问题而失败。操作系统也可以提供“真正的”锁定机制,以防止其他程序打开文件。然而,fopen()很难提供一个真正的“可能失败的原因列表”,因为有很多可能性。

显然,如果您尝试以读取模式打开文件并且该文件不存在,这将失败。但是,您上面的代码是以写入模式打开文件 - 如果文件不存在,这不一定会失败 - 如果目录路径存在并且调用进程有权写入该目录,则将创建文件。

于 2013-03-08T23:56:37.973 回答
2

fopen将失败主要是因为以下原因:

  • 文件不存在
  • 文件权限不允许打开此文件(写入、读取、执行等)
  • 文件被另一个进程使用(即第 3 方应用程序)
  • 文件被另一个 PHP 脚本/资产锁定
于 2013-03-08T23:37:21.700 回答
1

fopen如果您没有权限或存在其他低级操作系统问题,可能会失败,fopen多次 ing 没问题,但同时写入会导致“条带化”,因此请使用 (blocking) flock

于 2013-03-08T23:41:15.987 回答