【问题标题】:file locking in phpphp中的文件锁定
【发布时间】:2011-07-23 21:25:22
【问题描述】:

我让一个新人(隔壁的少年)编写了一些 php 代码来跟踪我网站上的一些使用情况。我对php不熟悉,所以我想问一些关于并发文件访问的问题。

我的本​​机应用程序(在 Windows 上)偶尔会通过点击包含我的 php 脚本的 URL 将一些数据记录到我的网站。原生应用不会检查返回的数据。

        $fh = fopen($updateFile, 'a') or die("can't open file");
        fwrite($fh, $ip);
        fwrite($fh, ', ');
        fwrite($fh, $date);
        fwrite($fh, ', ');
        fwrite($fh, implode(', ', $_GET));
        fwrite($fh, "\r\n");
        fclose($fh);

这是一个低流量的网站,数据并不重要。但是,如果两个用户发生冲突并且脚本的两个实例都尝试在文件中添加一行,会发生什么? php中是否有任何隐式文件锁定?

上面的代码是否至少不会被锁定并且永远不会将控制权返回给我的用户?文件会损坏吗?如果我让上面的脚本每月删除文件,如果脚本的另一个实例正在写入文件会发生什么?

【问题讨论】:

    标签: php locking


    【解决方案1】:

    你应该锁定文件:

    <?php
    $fp = fopen($updateFile, 'w+');
    if(flock($fp, LOCK_EX)) {
    fwrite($fp, 'a');
    flock($fp, LOCK_UN);
    } else {
    echo 'can\'t lock';
    }
    
    fclose($fp);
    

    【讨论】:

    • 正是我想要的,雷蒙德。谢谢。从我刚刚完成的其他阅读 (tuxradar.com/practicalphp/8/11/0) 来看,似乎永远无法达到回声语句。在第一个进程解锁文件之前,第二个进程不会阻塞群调用吗?羊群不需要 OR LOCK_NB 才能到达 echo 语句吗?
    • 我曾希望得到何先生或这里其他人的回应,以了解我观察到的上述回声声明是否会达到。
    • 是的,您需要在代码中添加一个|LOCK_NB,否则如果它已经被锁定,那么锁会被锁定:)
    • 请记住 flock() 在 Windows 上是强制性的(它总是会锁定文件)但在 Linux 上是建议性的(它可能实际上不会执行锁定),因此需要在任何非 Windows 上进行一些测试平台。
    • 澄清@Jason 的观点:advisory 的含义是您需要确保访问文件的all 代码调用flock。该文件实际上并未在操作系统级别“锁定”。例如,假设您在其他地方有代码正在访问该文件(可能是 php 以外的语言) - 您的 php 会相信它有锁,但它不会真的...
    【解决方案2】:

    为了记录,我在一个图书馆工作过:

    https://github.com/EFTEC/DocumentStoreOne

    它允许通过锁定文件来对文件进行 CRUD。我尝试了 100 个并发用户(同时对 PHP 脚本进行了 100 次调用)并且它工作正常。

    但是,它不使用flock而是mkdir:

    while (!@mkdir("file.lock")) {
       // use the file
       fopen("file"...)
       @rmdir("file.lock")
    }
    

    为什么?

    1. mkdir 是原子的,因此锁是原子的:只需一步,您锁定或不锁定。
    2. flock() 快​​。显然,flock 需要多次调用文件系统。
    3. flock() 取决于系统。
    4. 我进行了压力测试,结果奏效了。

    【讨论】:

    【解决方案3】:

    由于这是对文件的追加,最好的方法是在一个 fwrite() 中聚合数据并将其写入文件,前提是要写入的数据不大于文件缓冲区。当然你并不总是知道缓冲区的大小,所以flock();总是一个不错的选择。

    【讨论】:

    • 我会同时做这两件事:保持对单个fwrite()的写入锁定文件。在某些 Linux 平台和某些较旧的文件系统上,flock() 可能实际上并未锁定文件。
    猜你喜欢
    • 2015-04-14
    • 1970-01-01
    • 2014-09-04
    • 1970-01-01
    • 2015-01-26
    • 2011-08-24
    • 2013-03-04
    • 2013-05-23
    • 2018-08-22
    相关资源
    最近更新 更多