存储在MySQL中的二进制数据已损坏

时间:2013-11-24 21:31:28

标签: php mysql sql pdo binary-data

我需要在MySQL数据库中存储50个KiB - 500 KiB二进制文件(实际上是zlib压缩文本文件)。假设有充分的理由这样做而不是将它们写入文件系统,我在数据库中损坏数据时遇到了麻烦。我已经用PHP和Python推出了它,都表明数据已损坏。

我曾尝试使用PHP模拟的预处理语句和非模拟的预处理语句来输入数据,以及简单地将数据放在查询中,就好像它是一个字符串一样。所有这些导致了数据损坏。

准备好的陈述:

$options = array('PDO::ATTR_EMULATE_PREPARES' => FALSE);
$dsn = 'mysql:host=localhost;dbname=qb_cache;charset=utf8';
$pdo = new PDO($dsn, 'root', 'hunter2', $options);

$sql = 'INSERT INTO cache (body) VALUES (:body)';
$stmt = $pdo->prepare($sql);
$stmt->bindValue(':body', $body);

使用模拟准备好的陈述:

$dsn = 'mysql:host=localhost;dbname=qb_cache;charset=utf8';
$pdo = new PDO($dsn, 'root', 'hunter2');

$sql = 'INSERT INTO cache (body) VALUES (:body)';
$stmt = $pdo->prepare($sql);
$stmt->bindValue(':body', $body);

直接进入数据库:

$dsn = 'mysql:host=localhost;dbname=qb_cache;charset=utf8';
$pdo = new PDO($dsn, 'root', 'hunter2');

$sql = "INSERT INTO cache (body) VALUES ('{$body}')";
$stmt = $pdo->prepare($sql);

请注意,二进制数据没有PDO PDO::PARAM_* constant!顺便说一句,我不相信我达到MySQL字段的大小限制:

mysql> show variables like 'max_allowed_packet';
+--------------------+----------+
| Variable_name      | Value    |
+--------------------+----------+
| max_allowed_packet | 16777216 |
+--------------------+----------+
1 row in set (0.00 sec)

这是我尝试解码时的结果:

$ zlib-flate -uncompress < output_from_database
...snip...
74 ARP4s0B64R9P6oZOpe6262E}C k3A AFD001 Si IL4A57sflate: inflate: data: invalid block type


$ cat output_from_database | openssl zlib -d > decoded
140438369359520:error:29065064:lib(41):BIO_ZLIB_READ:zlib inflate error:c_zlib.c:570:zlib error:data error

使用Python从MySQL中提取数据我看到该字段大小合适,但我无法解压缩它::

>>> pprint(zlib.decompress(row[0]))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
zlib.error: Error -5 while decompressing data: incomplete or truncated stream

1 个答案:

答案 0 :(得分:0)

问题是列类型为blob,因为我认为blob是MySQL支持的最大数据类型。事实证明,当我实际查看并看到数据库中出现的大小为65535字节时,我理解数据被截断。 转移到longblob解决了问题。

对于下一个人:MySQL Data Type Storage Requirements