我需要在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
答案 0 :(得分:0)
问题是列类型为blob
,因为我认为blob
是MySQL支持的最大数据类型。事实证明,当我实际查看并看到数据库中出现的大小为65535字节时,我理解数据被截断。 转移到longblob
解决了问题。