备份是使用pg_dump通过UTF-8编码从数据库创build的。 备份是以tar格式。
然后我使用这个命令在运行相同版本的PostgreSQL(8.2.4)的另一台服务器上创build了一个新的数据库:
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
原始数据库不再可用。
我怎样才能恢复这个数据或find导致问题的字节序列?
较早的Postgres版本会允许将无效的字节序列input到数据库中。 有一个关于这个和在最近发布的说明suggsted修复注意:
一些用户在将UTF-8数据加载到8.1.X中时遇到问题。 这是因为之前的版本允许将无效的UTF-8字节序列input到数据库中,并且此版本只能正确接受有效的UTF-8序列。 一种纠正转储文件的方法是运行命令iconv -c -f UTF-8 -t UTF-8 -o cleanfile.sql dumpfile.sql。 -c选项删除无效的字符序列。 两个文件的差异将显示无效的序列。 iconv将整个input文件读入内存,因此可能需要使用split将转储分解为多个较小的文件进行处理。
如果数据库不是很大或者很复杂,那么在原始数据库中find有问题的文本并在进行新的转储之前纠正它可能会更容易。 具有用户input的input或包含从其他来源导入的数据的字段可能是罪魁祸首。
我通过以下步骤解决了这个问题:
pg_restore -f db1.sql-v db1.tar
然后,我从db1.sql文件中删除了除table1 copy命令之外的所有内容。 然后跑:
psql -d db1 < db1.sql
然后,这给了我错误发生的文件内的确切行号。 然后,我打开文件,并删除问题字符,并重新运行脚本。
这个小Perl脚本可能会节省您: 修复混合UTF-8和ISO-8859-1的破损的文档
将脚本输出redirect到一个新文件。 所有非法字符都应该被replace为正确的UTF-8版本。 脚本也一行一行地读取input,所以它不需要太多的内存。
这可能是我曾经从7.4到8.2分贝迁移的同一个问题。 我用这个networking文章的说明来解决这个问题。 这假定您仍然可以访问原始数据库。 否则,你可以在Postgresql的旧版本中恢复它,并尝试使用该过程。