Apache服务之前是否读取锁定文件?

时间:2012-01-26 16:48:17

标签: php json apache locking

我有一个移动应用程序,它读取存储在Apache服务器上的JSON文件。如果通过GUI更改了某些内容,则会重新生成该JSON文件的内容(使用PHP脚本)。

我担心尝试在Apache服务的过程中覆盖JSON文件可能会导致问题。

Apache在提供文件之前是否获得了读锁定?如果没有,如果我在服务的同时尝试写它会发生什么?

2 个答案:

答案 0 :(得分:9)

没有。在与POSIX兼容的系统上,所有锁都是建议性的,所以即使apache获得读锁定,另一个进程也可以写入文件。

您可以使用strace确定:

[pid  7246] open("/var/www/file.json", O_RDONLY|O_CLOEXEC) = 11
[pid  7246] fcntl(11, F_GETFD)          = 0x1 (flags FD_CLOEXEC)
[pid  7246] mmap(NULL, 20, PROT_READ, MAP_SHARED, 11, 0) = 0x7f53f93da000
[pid  7246] munmap(0x7f53f93da000, 20)  = 0
[pid  7246] writev(10, [{"HTTP/1.1 200 OK\r\nDate: Thu, 26 J"}, ...) = 365
[pid  7246] close(11)                   = 0

因此,您的JSON文件只能部分写入。要避免此问题,请将JSON文件写入同一文件系统上的临时文件,并使用原子rename覆盖该文件。

这样,如果open成功,apache将继续提供旧文件。如果renameopen之前完成,则apache将获取新的已完成文件。

如果您担心一致性(在电源故障等情况下),您可能还希望在关闭之前调用写入JSON文件的应用程序中的fsync

答案 1 :(得分:2)

你正在考虑使用* nix平台的错误范例。您想要的是原子文件写入脚本中的JSON文件。您可以通过将文件写入目标目录中的唯一临时文件名,然后使用rename()将此文件移动到旧文件上来执行此操作。文件移动操作是原子操作。异步进程将打开旧的JSON文件或新的JSON文件,但不打开混合。

有多种方法可以构建临时文件名。请参阅tempnam()上的PHP文档用户注释。我的系统会生成一个请求唯一ID,因此我只使用$_SERVER["UNIQUE_ID"]作为基础。