【问题标题】:[Warning]: PDO::__construct(): MySQL server has gone away - wait_timeout not the cause?[警告]: PDO::__construct(): MySQL server has gone away - wait_timeout 不是原因?
【发布时间】:2011-09-01 09:31:00
【问题描述】:

我希望这里的人可以帮助解决我在网络服务器上遇到的问题。目前,该服务器托管一个我们购买的用于帮助台的 Web 应用程序。每隔 8 小时,当有人导航到该页面时,他们就会看到此错误:

[Warning]: PDO::__construct(): MySQL server has gone away (Database/class.SWIFT_Database.php:334)

我已尝试将 wait_timeout 设置为 /etc/my.cnf 文件中的最大值,即;

wait_timeout=31536000

我也从 mysql 中将全局 wait_timeout 设置为该值,并将会话 wait_timeout 设置为相同。

我注意到一些奇怪的行为,当你重新启动 mysql 服务时,等待超时重置为默认值 28800,尽管它是在 my.cnf 中设置的。我找不到任何其他 mysql 配置文件,但很高兴看看是否有人能指出我的方向。

今天早上,当我登录服务器并运行以下命令时,会话 wait_timeout 值已恢复!

mysql> select @@global.wait_timeout, @@session.wait_timeout;
+-----------------------+------------------------+
| @@global.wait_timeout | @@session.wait_timeout |
+-----------------------+------------------------+
|              31536000 |                  28800 |
+-----------------------+------------------------+
1 row in set (0.00 sec)

我发现这对于很多在线上运行在 mysql 上的各种 webapps 的人来说是一个问题,但似乎没有人能解决这个问题。很多在线建议都指向 wait_timeout ,但它似乎并没有改变我看到的错误。我已经尝试了mysql手册上关于这个问题的修复,但仍然没有运气(链接:http://dev.mysql.com/doc/refman/5.0/en/gone-away.html

任何建议将不胜感激。服务器详细信息和产品版本如下:

服务器:OpenSuse 11.4 MySql 版本:5.1.53

提前致谢!

【问题讨论】:

    标签: mysql pdo


    【解决方案1】:

    Drupal.org 上的This article 可能对您的情况有所帮助:

    MySQL 带有它要使用的资源的默认配置,在安装 MySQL 期间在“my.cnf”(Linux)或“my.ini”(Windows)中指定。

    在 Linux 中,此文件位于 /etc/my.cnf 以设置全局选项,或 /usr/local/var/mysql-data-dir/my.cnf 以设置特定于服务器的选项。

    在 Windows 中,此文件默认位于 C:\Program Files\MySQL\MySQL Server X.Y\my.ini

    默认配置允许的资源通常不足以运行资源密集型应用程序。如果以下资源规范在您的原始配置文件中可用,则必须修改它们,如果尚未指定,则必须将它们添加到配置文件中(因为默认情况下不存在):

    重要提示:请记住在做任何事情之前保留备份文件!更改这些配置文件后,您还必须重新加载 MySQL 服务。

    MyISAM 规范:

    [mysqld]
    port = 3306
    socket = /tmp/mysql.sock
    skip-external-locking
    key_buffer = 384M
    max_allowed_packet = 64M
    table_cache = 4096
    sort_buffer_size = 2M
    read_buffer_size = 2M
    read_rnd_buffer_size = 64M
    myisam_sort_buffer_size = 64M
    thread_cache_size = 8
    query_cache_size = 32M
    

    InnoDB 规范:

    innodb_buffer_pool_size = 384M
    innodb_additional_mem_pool_size = 20M
    innodb_log_file_size = 10M
    innodb_log_buffer_size = 64M
    innodb_flush_log_at_trx_commit = 1
    innodb_lock_wait_timeout = 180
    

    注意:这里假设您使用的是 InnoDB 数据库表,因为 Drupal 是一个资源密集型应用程序。如果您没有使用 InnoDB 数据库表,请尝试更改此设置,因为您收到警告:MySQL 服务器已消失 - 显然意味着您的设置是资源密集型的。

    【讨论】:

      【解决方案2】:

      虽然不是很优雅,但以下 sn-p 帮助我摆脱了超时并保持持久连接。如果连接连续失败 $limit 次,它将抛出异常,但如果问题是超时,则最多只需要重试 1 次。

      $db = null;
      $limit = 10;
      $counter = 0;
      while (true) {
          try {
              $db = new PDO('mysql:host=' . db_host . ';dbname=' . db_name, db_user, db_pass);
              $db->exec( "SET CHARACTER SET utf8" );
              $db->setAttribute( PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC ); 
              $db->setAttribute( PDO::ATTR_PERSISTENT, true );
              break;
          }
          catch (Exception $e) {
              $db = null;
              $counter++;
              if ($counter == $limit)
                  throw $e;
          }
      }
      

      【讨论】:

      • 这确实有效!也必须坚持持久连接。尽管如此,我还是犹豫在这里使用while() 循环。有人对利弊有什么看法吗?
      【解决方案3】:

      连接关闭的原因有多种。

      参考: https://dev.mysql.com/doc/refman/5.0/en/gone-away.html

      我在使用 PDO 时也遇到了类似的问题,如果主机管理员在睡眠超过一分钟时会终止连接。因此我想出了我自己的类来包装 PDO 类。这将检测连接是否已关闭,并在查询执行时尝试重新连接。

      在下面回答

      PDO: MySQL server has gone away

      【讨论】:

      • 虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接的答案可能会失效。
      • 为什么要投反对票。我已经回答了一个类似的问题。
      猜你喜欢
      • 2012-08-06
      • 1970-01-01
      • 2019-10-13
      • 1970-01-01
      • 2014-09-13
      • 2013-12-16
      • 2011-12-11
      • 2011-02-04
      • 2016-02-15
      相关资源
      最近更新 更多