首页 > 解决方案 > Laravel 8:处理Mysql PDO连接超时的正确方法是什么

问题描述

Illuminate/Database/Connectors/Connector.php

    protected function createPdoConnection($dsn, $username, $password, $options)
    {
        if (class_exists(PDOConnection::class) && ! $this->isPersistentConnection($options)) {
            return new PDOConnection($dsn, $username, $password, $options);
        }

        return new PDO($dsn, $username, $password, $options);
    }

上述函数将永远在new PDO($dsn, $username, $password, $options)高丢包率的网络环境下执行。

我想要的是不要在 30 秒后继续等待并返回错误/抛出异常(为了澄清我想要这个的原因:之后我的应用程序将尝试连接到其他从属数据库)。

基线是我认为我不应该修改 Vendor 中的任何代码。

生成$options变量的逻辑设置在里面config/database.php,我做了以下事情:

'options' => extension_loaded('pdo_mysql') ? array_filter([
                ...
                PDO::ATTR_TIMEOUT => 1,
            ]) : [],

结果是会抛出异常,但会Connector.php在以下函数中被捕获:

    public function createConnection($dsn, array $config, array $options)
    {
        [$username, $password] = [
            $config['username'] ?? null, $config['password'] ?? null,
        ];

        try {
            return $this->createPdoConnection(
                $dsn, $username, $password, $options
            );
        } catch (Exception $e) {
            return $this->tryAgainIfCausedByLostConnection(
                $e, $dsn, $username, $password, $options
            );
        }
    }

new PDO()行将再次执行。基本上在那之后有一些类似的尝试捕获的东西,但基本上它从来没有真正将异常抛出到应用程序代码中,而是不断重新连接。

编辑:

PDO::ATTR_TIMEOUT实际上,我发现 Laravel 代码实际上在 4 次重试后抛出异常,但在大多数情况下,尽管设置了重试,但其中一次重试不会正确抛出异常。PDO::ATTR_ERRMODE也尝试过,但没有改变。

我怀疑由于丢包率是 95% 而不是 100%,所以连接正在建立过程中,但速度非常慢。

所以我想我现在的问题是,有没有办法在超时后强制终止正在建立的连接?

标签: mysqllaravelpdoconnection

解决方案


推荐阅读