0

我想当我需要通过 mysqli 向数据库插入超过max_allowed_packet-size 的 BLOB 时,我可以使用send_long_data. 这似乎对每个人都有效(见这个这个这个)。这是一个(不)工作的最小示例:

<?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 is $stmt->send_long_data)
  • 所以我必须从中减去至少 8 的值max_packet_size。为什么是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字节?

4

2 回答 2

0

根本没有办法绕过 max_packet_size (不修改它)。

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

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

于 2013-06-02T14:40:31.690 回答
0

您需要像这样修改它:

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

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

恕我直言,这太奇怪了。

于 2013-07-12T13:26:33.290 回答