备份是使用 从一个采用 UTF-8 编码的数据库创建的pg_dump
。备份的格式为tar
。
然后我使用以下命令在另一台运行相同版本 PostgreSQL(8.2.4)的服务器上创建了一个新数据库:
createdb -E utf8 db1
运行时pg_restore
出现以下错误:
pg_restore: [archiver (db)] Error from TOC entry 1667; 0 14758638 TABLE DATA table1 db1
pg_restore: [archiver (db)] COPY failed: ERROR: invalid byte sequence for encoding "UTF8": 0xc520
原始数据库不再可用。
我如何恢复这些数据或者找到导致问题的字节序列?
答案1
我通过以下步骤解决了这个问题:
pg_restore -f db1.sql-v db1.tar
然后我从db1.sql
文件中删除了除table1
复制命令之外的所有内容。然后运行:
psql -d db1 < db1.sql
然后,它给了我文件中发生错误的确切行号。然后我打开文件,删除问题字符,并重新运行脚本。
答案2
较旧版本的 Postgres 允许将无效的字节序列输入数据库。最近的一篇博文中提到了这个问题,并提出了修复建议。发行公告:
一些用户在将 UTF-8 数据加载到 8.1.X 时遇到了问题。这是因为以前的版本允许将无效的 UTF-8 字节序列输入数据库,而此版本仅接受有效的 UTF-8 序列。更正转储文件的一种方法是运行命令 iconv -c -f UTF-8 -t UTF-8 -o cleanfile.sql dumpfile.sql。-c 选项可删除无效的字符序列。两个文件的差异将显示无效的序列。iconv 将整个输入文件读入内存,因此可能需要使用 split 将转储拆分为多个较小的文件进行处理。
如果数据库不是很大或很复杂,在进行新的转储之前,可能更容易在原始数据库中找到有问题的文本并更正它。包含用户输入或包含从其他来源导入的数据的字段可能是罪魁祸首。
答案3
这个小小的 Perl 脚本也许能帮你节省时间: 修复混合 UTF-8 和 ISO-8859-1 的损坏文档
将脚本输出重定向到新文件。所有非法字符都应被替换为正确的 UTF-8 形式。脚本也会逐行读取输入,因此它不需要太多内存。
答案4
这可能是我曾经遇到过的问题,当时我从 7.4 db 迁移到 8.2 db。我使用了此说明网络文章解决问题。这假设您仍然可以访问原始数据库。否则,您可能可以在旧版本的 Postgresql 中恢复它并尝试该过程。