提问人:user2113177 提问时间:9/5/2017 最后编辑:user2113177 更新时间:9/16/2017 访问量:1444
PHP警告:在macOS终端中转储MySQL后,“MySQL服务器已消失”
PHP Warning: "MySQL server has gone away" after MySQL dump in macOS Terminal
问:
我正在使用 CLI 中的 PHP 脚本下载远程 MySQL 数据库 (gzip) 并将它们直接解压缩到我的 MacBook 的 MySQL 5.7(不是 MAMP)服务器。 它工作正常,但作为副作用,我的PHP应用程序(MAMP Pro)在CLI脚本中间丢失了MySQL连接,并发出警告
PHP Warning: mysqli::__construct(): MySQL server has gone away in ...
这发生在十几个数据库之后(无法重现确切的数量)。当 CLI 脚本运行时,“系统偏好设置”中的 MySQL 窗格在每次 CLI 转储后都会从绿色/正在运行变为红色/停止,然后再次变为绿色/正在运行,这首先不会与浏览器中的 PHP 应用程序冲突。但是在某些时候,PHP应用程序显然会失去连接。
我玩了 my.cnf 并设置了
[mysqld]
max_allowed_packet=128M
max_connections=1024
或其他金额,但它似乎没有改变任何事情。
当我在CLI脚本完成后在System Preferences中手动停止并启动MySQL时,PHP再次继续正常工作。
有什么想法吗?
编辑:
到目前为止,谢谢,但它仍然没有修复。所以这是原则上的脚本:
$tmpPath = '/tmp/'
For each of 30 databases with different size:
$dbName = database name
exec('ssh [email protected] "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)
就像我说的,终端中的PHP CLI脚本根本没有抱怨! 这是我的 PHP 应用程序(Angular 前端应用程序的后端)由于上述错误而在 30 个转储中间的某个地方停止工作。
答:
我有类似的问题,只需在mysql.conf中添加max_connections = 1024即可解决
我们遇到了类似的问题,并使用了这个,如果连接消失,它会重新连接:
<?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;
}
}
你可以调整它。DBCredentials类只是一个普通的PHP类,带有驱动程序,主机名,用户,密码,数据库名称的getters和setters,如果您愿意,您可以将其更改为仅将参数作为字符串。
如果向服务器发送查询,也可能会收到这些错误 不正确或太大。如果 mysqld 收到的数据包太大。 或者乱序,它假设 client 并关闭连接。
为了避免这个问题,您必须确保在mysqld服务器中设置max_allowed_packet比在客户端中设置的更大,并且所有客户端都使用相同的值进行max_allowed_packet。 请记住在该!!!之后重新启动服务器
评论
创建 mysqldump 时,会锁定表。我认为这是主要问题,这就是为什么您的应用程序出现该错误的原因。使用以下选项:
--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.
原始答案在这里:
并尝试在转储命令之间对用户进行一些“睡眠”。
评论
--lock-tables
mysqldump
gzip
gzip -q -dc '.$tmpPath.$dbName.'.sql.gz | mysql -u root -proot '.$dbName
评论
SHOW GLOBAL VARIABLES LIKE '%timeout%';
和SHOW SESSION VARIABLES LIKE '%timeout%';