【问题标题】:Error while sending QUERY packet发送 QUERY 数据包时出错
【发布时间】:2015-08-25 13:09:05
【问题描述】:

我试图向数据库中插入一些数据,但我收到此错误“发送查询数据包时出错

$insertDeta = $conPat->prepare("insert into table1(data) VALUES(:data)");
$insertDeta->bindParam(':data',$data);
$conPat->beginTransaction();    
    $insertDeta->execute();
$conPat->commit();

但我认为问题在于 数据 的大小超过 16MB。
该列的数据类型设置为longtext,我认为可以将数据保持到4​​GB。

我不知道 PDO 是否在运行查询或将 16MB 数据传输到数据库时遇到问题。
这是我唯一能做的猜测,因为 mysql 可能会在 packets 中发送数据,而数据包不能容纳 16MB 的数据。

【问题讨论】:

  • 你最后做了什么来解决这个问题?我也一样

标签: php mysql


【解决方案1】:

在 php 中为命令行执行 fork 时遇到这样的问题。就我而言,php 有时会杀死子进程。要解决此问题,只需使用命令 pcntl_wait($status);

等待该过程完成

这是一段可视化示例的代码:

    #!/bin/php -n
    <?php
    error_reporting(E_ALL & ~E_NOTICE);
    ini_set("log_errors", 1);
    ini_set('error_log', '/media/logs/php/fork.log');
    $ski = substr(str_shuffle(str_repeat("0123456789abcdefghijklmnopqrstuvwxyz", 5)), 0, 5);
    error_log(getmypid().' '.$ski.' start my php');

    $pid = pcntl_fork();
    if($pid) {
    error_log(getmypid().' '.$ski.' start 2');
    // Wait for children to return. Otherwise they 
    // would turn into "Zombie" processes
    // !!!!!! add this !!!!!!
    pcntl_wait($status);
    // !!!!!! add this !!!!!!
    } else {
    error_log(getmypid().' '.$ski.' start 3');
    //[03-Apr-2020 12:13:47 UTC] PHP Warning:  Error while sending QUERY packet. PID=18048 in /speed/sport/fortest.php on line 22457
    mysqli_query($con,$query,MYSQLI_ASYNC);
error_log(getmypid().' '.$ski.' sleep child');
  sleep(15);
    exit;
    } 

   error_log(getmypid().' '.$ski.'end my php');
    exit(0);
    ?>

【讨论】:

    【解决方案2】:

    如果变量wait_timeout 太小,也可能出现此错误。

    如果是这样,您可以将其设置得更高:

    SET GLOBAL wait_timeout=10;
    

    这是针对我的情况的相同错误的解决方案。

    【讨论】:

    • 注意这个变量的低值。我花了太多时间才意识到脚本深处的某个地方是 sleep(70);这导致 DB 连接丢失,因此“发送 QUERY 数据包时出错”。因此,要么考虑将其设置为至少几分钟,要么 ping() 您的数据库以保持连接处于活动状态。
    【解决方案3】:

    如果由于数据库服务器的max_allowed_packet 设置而导致插入“过多数据”失败,则会引发以下警告:

    SQLSTATE[08S01]: Communication link failure: 1153 Got a packet bigger than 
    'max_allowed_packet' bytes
    

    如果此警告被捕获为异常(由于设置的错误处理程序),则数据库连接(可能)丢失,但应用程序不知道这一点(插入失败可能有多种原因)。 下一个查询,可以很简单:

    SELECT 1 FROM DUAL
    

    然后会因为这个 SO-question 开始的错误而失败:

    Error while sending QUERY packet. PID=18486
    

    重现我的解释的简单测试脚本,尝试使用和不使用错误处理程序以查看影响差异:

    set_error_handler(function($errno, $errstr, $errfile, $errline, array $errcontext) {
        // error was suppressed with the @-operator
        if (0 === error_reporting()) {
            return false;
        }
    
        throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
    });
    
    try
    {
        // $oDb is instance of PDO
        var_dump($oDb->query('SELECT 1 FROM DUAL'));
    
        $oStatement = $oDb->prepare('INSERT INTO `test` (`id`, `message`) VALUES (NULL, :message);');
        $oStatement->bindParam(':message', $largetext, PDO::PARAM_STR);
        var_dump($oStatement->execute());
    }
    catch(Exception $e)
    {
        $e->getMessage();
    }
    var_dump($oDb->query('SELECT 2 FROM DUAL'));
    

    【讨论】:

      【解决方案4】:

      我在 cygwin 中遇到了一个罕见的边缘情况,在查询之前的某处执行 exec('rsync'); 时会出现此错误。可能是一般的 PHP 问题,但我只能在 cygwin 中使用 rsync 重现此问题。

      $pdo = new PDO('mysql:host=127.0.0.1;dbname=mysql', 'root');
      var_dump($pdo->query('SELECT * FROM db'));
      exec('rsync');
      var_dump($pdo->query('SELECT * FROM db'));
      

      生产

      object(PDOStatement)#2 (1) {
         ["queryString"]=>
         string(16) "SELECT * FROM db"
      }
      PHP Warning:  Error while sending QUERY packet. PID=15036 in test.php on line 5
      bool(false)
      

      https://cygwin.com/ml/cygwin/2017-05/msg00272.html 中报告的错误

      【讨论】:

      • 得到同样的错误
      【解决方案5】:

      /etc/my.cnf 中添加:

        max_allowed_packet=32M
      

      它对我有用。您可以通过进入 PHPMyAdmin 并打开 SQL 命令窗口并执行来验证:

      SHOW VARIABLES LIKE  'max_allowed_packet'
      

      【讨论】:

        【解决方案6】:

        您可以通过以下几个步骤解决此问题:

        1) 打开终端窗口

        2) 请在终端输入以下命令

        ssh root@yourIP port
        

        3) 输入root密码

        4) 现在使用以下命令编辑您的服务器 my.cnf 文件

        nano /etc/my.cnf  
        

        如果无法识别命令,请先执行此操作或尝试 vi 然后重复:yum install nano。

          vi /etc/my.cnf 
        

        5) 在 [MYSQLD] 部分下添加该行。 :

        max_allowed_packet=524288000 (obviously adjust size for whatever you need) 
        wait_timeout = 100
        

        6) Control + O(保存)然后 ENTER(确认)然后 Control + X(退出文件)

        7) 然后通过以下命令重启你的mysql服务器

        /etc/init.d/mysql stop
        /etc/init.d/mysql start
        

        8) 您可以通过进入 PHPMyAdmin 或打开 SQL 命令窗口并执行来验证:

        SHOW VARIABLES LIKE 'max_allowed_packet'
        

        这对我有用。我希望它对你有用。

        【讨论】:

        • default valuewait_timeout 是 28800 秒。为什么要降到 100?
        • 对上面的评论有任何答案吗?我有兴趣了解为什么只有 100... 我在 max_allowed_pa​​cket 中有 500MB,wait_timeout 100 并且它仍然因相同的错误消息而崩溃。会是什么?
        • 也许,100 高于某些主机的自定义默认值?但这只是猜测。
        • 注意如果您在 AWS:我必须执行 sudo vi /etc/my.cnf 并重新启动 mysql 我必须改为执行 sudo service mysqld restart
        【解决方案7】:

        INSERT 语句中不能有 WHERE 子句。

        insert into table1(data) VALUES(:data) where sno ='45830'

        应该是

        insert into table1(data) VALUES(:data)


        更新:您已将其从代码中删除(我假设您错误地复制了代码)。您想增加允许的数据包大小:

        SET GLOBAL max_allowed_packet=32M

        根据需要向上/向下更改32M(32 兆字节)。 Here is a link to the MySQL documentation on the subject.

        【讨论】:

        • SET GLOBAL max_allowed_pa​​cket=32M 在 mysql 中不起作用,它说参数无效。但如果我发起查询 SET GLOBAL max_allowed_pa​​cket=524288000;我收到此错误“检查与您的 MySQL 服务器版本相对应的手册,以在第 1 行的 'SET GLOBAL max_allowed_pa​​cket=524288000' 附近使用正确的语法”
        • 您可以运行SHOW VARIABLES LIKE 'max_allowed_packet' 来查看您的最大值实际上是多少。你在共享主机上吗?如果是,那么它可能会为您禁用。
        • 这个是持久的还是要在mysql重启后再做一次?
        • @chill
        • 这是错误的-即使您链接的页面也明确指出 “在服务器启动时设置变量时可以使用指定值乘数的后缀,但不能在运行时使用 SET 设置值"。换句话说,你可以做到32*1024*1024,但不能 32M
        【解决方案8】:

        您猜对了,MySQL 对数据大小有限制,您需要将查询分解为一小组记录,或者您可以使用 SET GLOBAL max_allowed_packet=524288000; 更改您的 max_allowed_pa​​cket

        【讨论】:

        • 我在 my.ini 文件中将 max_allowed_pa​​cket 设置为 256M,但它不起作用。
        • 如果我向 SET GLOBAL max_allowed_pa​​cket=524288000 发起查询;我收到此错误“检查与您的 MySQL 服务器版本相对应的手册,以了解在第 1 行的 'SET GLOBAL max_allowed_pa​​cket=524288000' 附近使用的正确语法
        • 是否有记录触发此警告的查询?
        • 哇,它对我有用。我虽然它来自日志,但也要确保在 php.ini 中检查你的 post_max_size 和 upload_max_filesize
        猜你喜欢
        • 2018-04-22
        • 1970-01-01
        • 2017-08-10
        • 2019-06-03
        • 2017-05-14
        • 1970-01-01
        • 2014-05-20
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多