mysqli send_long_data失败

时间:2013-05-30 13:28:41

标签: php mysqli

我想当我需要通过mysqli向数据库插入超过max_allowed_packet大小的BLOB时,我可以使用send_long_data。这似乎适用于所有人(请参阅thisthisthis)。这是一个(不)工作的最小例子:

<?php
   # Establishing connection
   $db = new mysqli('localhost', 'user', 'password', 'database');
   $db->query('SET CHARACTER SET "utf8"');
   # Get max value
   $res = $db->query('SHOW VARIABLES WHERE `Variable_name` = "max_allowed_packet"');
   $max = (int)$res->fetch_assoc()['Value'];
   $res->free();
   # Prepare
   $content = file_get_contents('C:\\file.png');
   $stmt = $db->prepare('UPDATE `table` SET `field` = ? WHERE `id` = ?');
   $null = null;
   $id   = 1;
   $stmt->bind_param('bi', $null, $id);
   # send_long_data
   $m = $max -8;
   $p = -$m;
   $l = strlen($content) + $p;
   while($p < $l)
      $stmt->send_long_data(0, substr($content, $p += $m, $m));
   if(!$stmt->execute())
      echo "{$db->errno}: {$db->error}";
   # finalize
   $stmt->close();
   $db->close();
?>

如果包装尺寸小于max_packet_size,则效果非常好。如果没有,有几个问题:

  • 如果我只是将$m设置为$max,则无效。错误消息为2006: MySQL server has gone away;在此之前,会发出警告:Warning: Error while sending STMT_SEND_LONG_DATA packet. ... on line 20(20为$stmt->send_long_data
  • 所以我必须从这个max_packet_size中减去至少8的值。为什么8?它取决于某些东西吗?为什么不简单max_packet_size
  • 但是好的,我减去8.然后是以下错误:1105: Parameter of prepared statement which is set through mysql_send_long_data() is longer than 'max_allowed_packet' bytes
  • substr肯定会返回字节数,为mbstring.func_overload = 0
  • 如果我不使用while循环,则传输图像也可以工作 - 但是当然不会传输图像的一部分。我认为send_long_data的目的恰恰是为了传输超过max_packet_size个字节!
  • 顺便说一句:为什么错误消息告诉我一些关于mysql_send_long_data而不是mysqli_send_long_data的内容?
  • 我认为这可能是MySQL的错误,所以我从5.5更新到5.6.11(当前);这没有解决任何问题。
  • 我使用的是PHP 5.4.12。
  • 数据库字段的类型为LONGBLOB,并且能够保存数据。如果我增加max_packet_size,一切正常。但我不能依赖于访问服务器变量的操作。

如何传输超过max_packet_size字节的内容?

2 个答案:

答案 0 :(得分:0)

根本无法绕过max_packet_size(不修改它)。

请参阅MySQL文档: http://dev.mysql.com/doc/refman/5.5/en/packet-too-large.html

  

客户端和服务器都有自己的max_allowed_pa​​cket   变量,所以如果你想处理大数据包,你必须增加它   在客户端和服务器中都是变量。

答案 1 :(得分:0)

你需要像这样修改它:

SET GLOBAL max_allowed_packet = 32 * 1048576; // 32 MB

我认为PHP会缓存send_long_data()发送的块,然后尝试一次性发送数据包。所以分块或发送一个警示,send_long_data()仍取决于@@max_allowed_packet MySQL变量定义的大小。

其中,恕我直言,这太奇怪了。