简体   繁体   English

PHP警告:在MySQL转储到macOS终端后,“MySQL服务器已经消失”

[英]PHP Warning: “MySQL server has gone away” after MySQL dump in macOS Terminal

I am using a PHP script from CLI to download remote MySQL databases (gzip) and extract them directly to my MacBook's MySQL 5.7 (not MAMP) server. 我使用CLI的PHP脚本下载远程MySQL数据库(gzip)并将它们直接提取到我的MacBook的MySQL 5.7(不是MAMP)服务器。 It works fine, but as a side effect, my PHP apps (MAMP Pro) lose the MySQL connection in the middle of the CLI script with the warning 它工作正常,但作为副作用,我的PHP应用程序(MAMP Pro)在CLI脚本中间丢失了MySQL连接并带有警告

PHP Warning:  mysqli::__construct(): MySQL server has gone away in ...

This happens after roundabout a dozen databases (can't reproduce the exact amount). 这种情况发生在十几个数据库(无法重现确切数量)之后。 While the CLI script is running, the MySQL pane in System Preferences goes from green/running to red/stopped to again green/running after each CLI dump, which first does not conflict with the the PHP apps in the browser. 在CLI脚本运行时,系统首选项中的MySQL窗格从每次CLI转储后的绿色/运行变为红色/停止再次变为绿色/运行,这首先与浏览器中的PHP应用程序不冲突。 But at some point the PHP apps obviously lose the connection. 但在某些时候,PHP应用程序显然失去了连接。

I played around with my.cnf and set 我和my.cnf一起玩了

[mysqld]
max_allowed_packet=128M
max_connections=1024

or other amounts, but it doesn't seem to change anything. 或其他金额,但似乎没有任何改变。

When I manually stop and start MySQL in System Preferences after the CLI script has finished, the PHP continues to work normal again. 当CLI脚本完成后,我在“系统偏好设置”中手动停止并启动MySQL时,PHP将继续正常工作。

Any ideas? 有任何想法吗?

EDIT: 编辑:

Thanks so far, but it's still not fixed. 谢谢到目前为止,但它仍然没有修复。 So here's the script in principal: 所以这是主要的脚本:

$tmpPath = '/tmp/'

For each of 30 databases with different size:

$dbName = database name

exec('ssh user@server.com "mysqldump --login-path=local --lock-tables=false '.$dbName.' | gzip" > '.$tmpPath.$dbName.'.sql.gz');
exec('gzip -q -dc '.$tmpPath.$dbName.'.sql.gz | mysql -u root -proot '.$dbName)

Like I said, the PHP CLI script in Terminal doesn't complain at all! 就像我说的,终端中的PHP CLI脚本根本不会抱怨! It's my PHP apps (backend for Angular frontend apps) that somewhere in the middle of the 30 dumps stop working because of the mentioned error. 这是我的PHP 应用程序 (Angular前端应用程序的后端),由于上述错误,30个转储中间某处停止工作。

我有类似的问题,并通过在mysql.conf中添加max_connections = 1024来修复

We had a similar problem, and used this which reconnects if the connection goes away: 我们遇到了类似的问题,并使用了这个问题,如果连接消失,它会重新连接:

<?php

use Exception;
use PDO;
use Our\Package\Common\Config\DbCredentials;

class DbConnectionManager
{
    private $credentials;

    /** @var PDO $connection */
    private $connection;

    /**
     * DbConnectionManager constructor.
     * @param DbCredentials $credentials
     */
    public function __construct(DbCredentials $credentials)
    {
        $this->credentials = $credentials;
        $this->reconnect();
    }

    /**
     * @return PDO
     */
    public function getConnection()
    {
        if (!$this->isConnected()) {
            $this->reconnect();
        }
        return $this->connection;
    }

    /**
     * @return bool
     */
    private function isConnected()
    {
        try {
            return $this->connection->query('SELECT 1 + 1;');
        } catch (Exception $e) {
            return false;
        }
    }

    /**
     *  Reinitialise the connection to MySQL
     */
    private function reconnect()
    {
        $dsn = $this->credentials->getDriver()
            .':host='.$this->credentials->getHost()
            .';port='.$this->credentials->getPort()
            .';dbname='.$this->credentials->getDbName()
        ;
        $connection = new PDO($dsn, $this->credentials->getUser(), $this->credentials->getPassword(), array(
            PDO::ATTR_TIMEOUT => 28800,
            PDO::ATTR_EMULATE_PREPARES => false,
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        ));
        $this->connection = $connection;
    }
}

You can tweak this. 你可以调整一下。 The DBCredentials class is just a plain PHP class with getters & setters for driver, hostname, user, password, db name, you could change it to just take arguments as strings if you like. DBCredentials类只是一个普通的PHP类,包含驱动程序,主机名,用户,密码,数据库名称的getter和setter,如果您愿意,可以将其更改为仅将参数作为字符串。

You can also get these errors if you send a query to the server that is incorrect or too large. 如果向服务器发送不正确或太大的查询,也可能会出现这些错误。 If mysqld gets a packet that is too large . 如果mysqld获取的数据包太大 or out of order, it assumes that something has gone wrong with the client and closes the connection. 或者不按顺序,它假定客户端出现问题并关闭连接。

To avoid this problem ,You must ensure that max_allowed_packet is set bigger in the mysqld server than in the client and that all clients uses the same value for max_allowed_packet. 要避免此问题,必须确保mysqld服务器中的max_allowed_pa​​cket设置得比客户端大,并且所有客户端都使用相同的max_allowed_pa​​cket值。 And Remember to restart your server after that !!!! 并记得在那之后重新启动服务器!!!!

When you create a mysqldump you lock the tables. 创建mysqldump时,锁定表。 I think that is the main problem and that is why your applications is getting that error. 我认为这是主要问题,这就是为什么你的应用程序出错了。 Use this options: 使用此选项:

--lock-tables, -l

Lock all tables before dumping them. The tables are locked with READ
LOCAL to allow concurrent inserts in the case of MyISAM tables. For
transactional tables such as InnoDB and BDB, --single-transaction is
a much better option, because it does not need to lock the tables at
all.

The original answer here: 原来的答案在这里:

Run MySQLDump without Locking Tables 运行MySQLDump而不锁定表

And try user some "sleep" between dump commands. 并尝试用户在转储命令之间“睡眠”。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM