PHP&;会话:有没有办法禁用PHP会话锁定?

PHP&;会话:有没有办法禁用PHP会话锁定?,php,session,locking,Php,Session,Locking,在使用默认会话处理程序时,有没有办法禁用PHP中的会话锁定 [编辑:]或者在调用session\u write\u close()之后,是否至少有一种方法可以重新启动会话会话\u start()将不起作用。除了使用?据我所知没有。您不想禁用它。。。如果你这样做,你可能会遇到各种各样的奇怪问题,你在一个窗口登录,在另一个窗口注销,然后在一个不一致的状态结束。。。锁在那里是有原因的 相反,如果您知道不打算在该请求中写入会话,请尽早关闭会话。一旦启动它,即使在调用session\u write\u c

在使用默认会话处理程序时,有没有办法禁用PHP中的会话锁定


[编辑:]或者在调用
session\u write\u close()
之后,是否至少有一种方法可以重新启动会话<如果已将任何输出发送到浏览器,则代码>会话\u start()将不起作用。

除了使用?据我所知没有。

您不想禁用它。。。如果你这样做,你可能会遇到各种各样的奇怪问题,你在一个窗口登录,在另一个窗口注销,然后在一个不一致的状态结束。。。锁在那里是有原因的

相反,如果您知道不打算在该请求中写入会话,请尽早关闭会话。一旦启动它,即使在调用
session\u write\u close
之后,您也可以从中读取整个请求(除非您重新启动它或执行其他特殊操作)。因此,您要做的是检查该请求是否为写请求,如果不是,请在打开它之后立即关闭它。请注意,如果您稍后尝试写入会话(用于验证码或CSRF保护或其他),这可能会产生一些不利影响,因此请谨慎使用


但是,我不会试图绕过它,而是努力缩短请求长度(以减少锁争用),或者对那些根本不需要会话的请求发出无Cookie请求…

无法从php会话禁用锁。这是一个非常重要的锁定用例。摆脱会话和/或php的唯一方法。作为一个临时解决方案,您可能希望使用riak会话处理程序:它是无锁的,并且工作正常


memcached session handler的最新版本也引入了锁定,原因很疯狂,无法禁用它。

如果PHP即使在调用session\u write\u close之后也没有异步处理请求,那么它可能就是xdebug。我不知道这是否是你的问题,但我总是被这件事绊倒,让自己为之疯狂,所以我想如果其他人也有同样的问题,我会发布它:)

你可以通过在会话后调用会话开始()来重新启动会话。然而,这将导致多个小岛屿发展中国家。我通过在刷新输出之前从标头中删除多个SID来解决这个问题


请看这个例子:

我有一个报告页面,花费了2分钟(超过80个AJAX请求)。通过移除会话锁定,我将时间缩短到30秒以下是的,上天禁止您删除文件锁定,因为这样您就有了竞争条件。如果您不了解竞争条件,也不知道会对您的会话产生什么影响,那么就不要删除文件锁定。但是,如果您知道会话中有哪些数据,并且知道比赛条件的作用,觉得没有任何数据会受到比赛条件的不利影响,从而产生错误……您比其他任何人都更了解您的环境,那么就去做吧

MySQL、REDIS和Memcache

另外,请注意,如果您切换到MySQL进行会话管理,IMHO有99%的可能性,即您从读取到写入时都没有锁定行。因此,使用MySQL仍然存在相同的竞争条件(如果决定锁定行,则存在锁定问题)

根据我能找到的信息,使用PHP Redis的人使用的是一个非锁定的应用程序,很容易出现竞争情况……根据下面的线程……他们将速度作为他们喜欢这个“功能”的原因之一:

Memcached在3.0.4版之前不支持会话锁定…所以它最初也很容易出现争用情况

显然,随着这些选项的成功,竞争条件并不是程序员面临的最大问题

最终问题是

所有并发请求将始终受到竞争条件的约束,除非您执行了文件锁定,在这一点上,它们 不再是并发请求

会话和锁定与并发性和竞争条件的重要区别在于了解您的应用程序,了解竞争条件是否会破坏您的应用程序……并设计适合您的应用程序的解决方案。如果您所做的只是将userId存储在会话中,并在所有后续请求中读取它,那么您可能不需要担心竞争条件。如果您存储了详细的数据历史记录,如果出现故障或数据可能丢失,这些历史记录将中断,请在读取和写入之间锁定文件,并尝试在读取后尽快写入,以限制文件锁定的时间

最佳选择

然而,对于并发请求来说,无会话API会更好。然而,如果您没有时间重构到这样一个API…那么请继续阅读

一种权宜之计解决方案,可继续使用PHP会话文件并停止锁定

要继续以默认方式使用PHP会话,停止锁定,并基本上快速解决复杂问题,您可以实现PHP网站的SessionHandler示例实现

我在一个每分钟有上万个连接的站点的生产环境中运行了下面的代码,我还没有遇到竞争条件方面的任何问题,但我也没有存储竞争条件可能破坏的数据。正如我所说的,这段代码得到了一份报告,从2分钟到30秒,而且它花了几分钟来实现。没有要创建的MySQL模式,没有要安装的Memcache或Redis

这是PHP文档()中提供的示例实现,在读取会话文件时不会锁定它

注意正如另一位在本评论中指出的那样,除非将文件保存到单个服务器,否则在分布式系统中,这将不起作用

<?php
class MySessionHandler implements SessionHandlerInterface
{
    private $savePath;

    public function open($savePath, $sessionName)
    {
        $this->savePath = $savePath;
        if (!is_dir($this->savePath)) {
            mkdir($this->savePath, 0777);
        }

        return true;
    }

    public function close()
    {
        return true;
    }

    public function read($id)
    {
        return (string)@file_get_contents("$this->savePath/sess_$id");
    }

    public function write($id, $data)
    {
        return file_put_contents("$this->savePath/sess_$id", $data) === false ? false : true;
    }

    public function destroy($id)
    {
        $file = "$this->savePath/sess_$id";
        if (file_exists($file)) {
            unlink($file);
        }

        return true;
    }

    public function gc($maxlifetime)
    {
        foreach (glob("$this->savePath/sess_*") as $file) {
            if (filemtime($file) + $maxlifetime < time() && file_exists($file)) {
                unlink($file);
            }
        }

        return true;
    }
}
$handler = new MySessionHandler();
session_set_save_handler($handler, true);
session_start();