【问题标题】:How to solve General error: 2006 MySQL server has gone away如何解决一般错误:2006 MySQL server has gone away
【发布时间】:2016-01-19 22:15:18
【问题描述】:

我正在执行将数百条记录插入 MySQL 数据库的操作。

准确插入 176 条记录后,我收到此错误:

[PDOException] SQLSTATE[HY000]: 一般错误:2006 MySQL server has gone away

关于如何解决它的任何想法?

这个过程是用PHP的。

【问题讨论】:

  • 您在共享服务器上吗?
  • 是的。去吧爸爸。有关系吗?
  • 可能。 WebHostingHub 经常遇到同样的问题。我还没有运气弄清楚“为什么”。如果您发布您的代码,可能更容易告诉what might be going on.
  • 查看您帖子“相关”下的顶部链接(获得 58 票)。 The post
  • 只是为了好奇你能运行这个:SHOW VARIABLES LIKE '%timeout%';

标签: php mysql pdo


【解决方案1】:

我敢说问题出在wait_timeout。在我的共享主机上设置为 30 秒,在我的本地主机上设置为 28800。

我发现我可以为会话更改它,因此您可以发出查询:SET session wait_timeout=28800

更新 OP 确定他还需要更改变量interactive_timeout。每个人都可能需要也可能不需要。

下面的代码显示了更改前后的设置,以验证是否已更改。

所以,在查询开始时设置 wait_timeout=28800(和 interactive_timeout = 28800),看看它是否完成。

记得插入你自己的数据库凭证来代替DB_SERVER, DB_USER, DB_PASS, DB_NAME

更新此外,如果这确实有效,您希望通过将 wait_timeout 设置得更高来清楚自己在做什么。将它设置为 28800 是 8 小时,而且很多。

以下来自this site。它建议将 wait_timeout 设置为 300 - 我将尝试报告我的结果(几周后)。

wait_timeout 变量表示 MySQL 将等待的时间量 在杀死空闲连接之前等待。默认的wait_timeout 变量为 28800 秒,即 8 小时。太多了。

我在不同的论坛/博客中看到将 wait_timeout 设置得太低 (e.g. 30, 60, 90) 会导致 MySQL has gone away 错误信息。所以 你必须决定你的配置。

<?php

$db = new db();

$results = $db->query("SHOW VARIABLES LIKE '%timeout%'", TRUE);
echo "<pre>";
var_dump($results);
echo "</pre>";

$results = $db->query("SET session wait_timeout=28800", FALSE);
// UPDATE - this is also needed
$results = $db->query("SET session interactive_timeout=28800", FALSE);

$results = $db->query("SHOW VARIABLES LIKE '%timeout%'", TRUE);
echo "<pre>";
var_dump($results);
echo "</pre>";


class db {

    public $mysqli;

    public function __construct() {
        $this->mysqli = new mysqli(DB_SERVER, DB_USER, DB_PASS, DB_NAME);
        if (mysqli_connect_errno()) {
            exit();
        }
    }

    public function __destruct() {
        $this->disconnect();
        unset($this->mysqli);
    }

    public function disconnect() {
        $this->mysqli->close();
    }

    function query($q, $resultset) {

        /* create a prepared statement */
        if (!($stmt = $this->mysqli->prepare($q))) {
            echo("Sql Error: " . $q . ' Sql error #: ' . $this->mysqli->errno . ' - ' . $this->mysqli->error);
            return false;
        }

        /* execute query */
        $stmt->execute();

        if ($stmt->errno) {
            echo("Sql Error: " . $q . ' Sql error #: ' . $stmt->errno . ' - ' . $stmt->error);
            return false;
        }
        if ($resultset) {
            $result = $stmt->get_result();
            for ($set = array(); $row = $result->fetch_assoc();) {
            $set[] = $row;
            }
            $stmt->close();
            return $set;
        }
    }
}

【讨论】:

  • 它在 WebHostingHub 上确实如此,它们似乎是等价的。我必须说我很惊讶它起作用了。
  • 它对我不起作用。将不得不尝试别的东西。还是谢谢。
  • 是没有改变wait_timeout还是改变了wait_timeout但是2006的错误还是发生了?
  • 我能够将当前事务中的 wait_timeout 设置为 28800,但该过程仍然失败。我想知道这是否与另一个值有关。
  • 添加了评论@mseifert。我接受了你的帖子作为有效答案,因为你给了我解决这个问题的想法和部分解决方案。谢谢!
【解决方案2】:

谢谢@mseifert。

你的想法是通过对两个变量做同样的事情来实现的。

interactive_timeout & wait_timeout

我从本地数据库复制了配置:

SHOW VARIABLES LIKE  '%timeout%'

本地数据库:

远程数据库:

我在连接和断开连接中做了这个并且工作:

mysql_query("SET SESSION interactive_timeout = 28800;");
$result = mysql_query("SHOW VARIABLES LIKE 'interactive_timeout';");
$row = mysql_fetch_array($result);
$interactive_timeout = $row["Value"];
echo("interactive_timeout" . " = " . $interactive_timeout . "\n");

mysql_query("SET SESSION wait_timeout = 28800;");
$result = mysql_query("SHOW VARIABLES LIKE 'wait_timeout';");
$row = mysql_fetch_array($result);
$wait_timeout = $row["Value"];
echo("wait_timeout" . " = " . $wait_timeout . "\n");

令人惊讶的是,它与 GoDaddy 合作。

我会接受你的回答为有效的@mseifert,因为你给了我最初的想法。

非常感谢。

让我们希望这对其他开发人员将来解决 2006 MySQL 错误有用。

【讨论】:

  • 这很有趣。我读到 interactive_timeout 用于 mysql shell 会话,如 mysqldump 或 mysql 命令行工具。无论如何,在解决问题方面做得很好。我将更新我的答案以包含此信息,因为您已将其设为已接受的答案。
  • 对了,我还要补充一点。我所做的大量 sql 插入可以通过 Web 浏览器通过 REST API 调用,也可以通过控制台 - 命令行调用。也许这就是我必须添加这两个选项的原因。
【解决方案3】:

假设您的代码是:

// your codes
$pdo = db::connection()->getPdo();
$stmt = $pdo->prepare($sql);
$result = $stmt->execute($params);

所以在你的 sql 查询之前添加以下代码:

$pdo = db::connection()->getPdo();

// Increase interactive_timeout
$prepend_sql = "SET SESSION interactive_timeout = 28800;";
$stmt = $pdo->prepare($prepend_sql);
$stmt->execute($params);

// Increase wait_timeout 
$prepend_sql = "SET SESSION wait_timeout = 28800;";
$stmt = $pdo->prepare($prepend_sql);
$stmt->execute($params);

// your codes
/* $pdo = db::connection()->getPdo(); */
$stmt = $pdo->prepare($sql);
$result = $stmt->execute($params);

【讨论】:

  • $params?那是错误的。你没有在那里绑定任何东西!
【解决方案4】:

就我而言,当我在客户端收到此错误时,服务器端是

(Got a packet bigger than 'max_allowed_packet' bytes)

所以我增加了 max_allowed_pa​​cket 的值,到目前为止,没有更多问题。

在 Google Cloud Platform 上,我编辑数据库并添加一个数据库标志并将值设置为 max_allowed_pa​​cket=134217728

(即 2^27 = 128M)

因为你只能输入数字。

在常规情况下,您可以在此处关注文档:

https://dev.mysql.com/doc/refman/8.0/en/packet-too-large.html

【讨论】:

    猜你喜欢
    • 2019-10-13
    • 2015-12-02
    • 2013-12-16
    • 2011-12-11
    • 2011-02-04
    • 2020-06-15
    • 2020-05-28
    • 1970-01-01
    相关资源
    最近更新 更多