Postgres pg_dump 缓存查找索引失败

5

我正在尝试使用以下命令(省略细节)创建postgres数据库的备份:

$ pg_dump -h $host -p 5432 -U $user $db > db.sql

一段时间后,我收到一个错误信息(已格式化)。
pg_dump: [archiver (db)] query failed: ERROR:  cache lookup failed for index 1184605879
pg_dump: [archiver (db)] query was: 
SELECT  t.tableoid, 
        t.oid, 
        t.relname AS indexname, 
        pg_catalog.pg_get_indexdef(i.indexrelid) AS indexdef, 
        t.relnatts AS indnkeys, 
        i.indkey, 
        i.indisclustered, 
        false AS indisreplident, 
        t.relpages, 
        c.contype, 
        c.conname, 
        c.condeferrable, 
        c.condeferred, 
        c.tableoid AS contableoid, 
        c.oid AS conoid, 
        pg_catalog.pg_get_constraintdef(c.oid, false) AS condef, 
        (SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, 
        t.reloptions AS indreloptions 
FROM pg_catalog.pg_index i 
JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) 
LEFT JOIN pg_catalog.pg_constraint c ON (i.indrelid = c.conrelid AND i.indexrelid = c.conindid AND c.contype IN ('p','u','x')) 
WHERE i.indrelid = '1184605870'::pg_catalog.oid AND i.indisvalid AND i.indisready 
ORDER BY indexname

我随后验证了pg_index中的索引ID不存在。是否有某种修复方法,或者忽略此错误并继续进行,以便我可以继续导出非pg_catalog数据?

3个回答

1
可能系统索引已损坏。建议尝试以下步骤:
  1. 停止数据库服务器
  2. 以单用户模式启动数据库,忽略系统和用户定义的索引:

    postgres --single -D /path/to/data --ignore_system_indexes=on --enable_indexscan=off --enable_bitmapscan=off <database>

  3. 重新创建整个数据库的索引(包括目录):REINDEX DATABASE <database>;

  4. 重新启动数据库并再次尝试导出...

更多信息:忽略系统索引, 重新创建索引, 启用位图扫描/索引扫描, 单用户模式


我尝试了这个方法,但是仍然出现了不同索引值的错误。由于还有其他系统在使用这个数据库,所以在确认没有其他系统自动重新连接到数据库后,我会再与您联系。 - Matthew C

1
我编写了一个快速脚本,将每个表格单独转储到一个SQL文件中,发现是一些临时登录信息导致缓存失败。我仅从导出中排除了该表格,问题就解决了。
我不是最好的Bash程序员,所以它肯定可以改进,但这是我用来逐个转储每个表格以查找哪个表格导致错误的脚本。
#!/bin/bash
host=$1
port=$2
user=$3
db=$4

# Get all table names that you will be dumping individually
query="SELECT tablename FROM pg_tables WHERE tableowner=$user;"
tables=( $(psql -h $host -p $port -U $user $d -c $query) )
mkdir db_dump

dump_command="pg_dump -h $host -p $port -U $user"
for table in $(tables[@]); do
    eval "$dump_command -t $table $db > db_dump/$table.sql"
done

0

您的数据库已经损坏,建议从备份中进行恢复。

如果您不怕操作目录(请先进行物理备份):

将配置参数allow_system_table_mods设置为on,以便您可以修改系统目录。然后执行以下操作:

DELETE FROM pg_catalog.pg_index WHERE indexrelid = 1184605879;

也许这会让你的数据库处于一种状态,以便你可以转储它(减去那个索引)。

如果还有更多问题,你可能最终需要使用COPY逐个提取表数据,并查看你还能挽救什么。


今天早上我重新测试了几次转储文件(没有更改任何内容),每次都会生成不同的索引号。我认为可能存在不同的潜在问题。我将尝试逐个提取每个表格,以确定哪个表格出现了问题。 - Matthew C
整个 pg_index 系统目录似乎已经损坏了。或者只是索引 pg_index_indrelid_index 出了问题,重新索引 pg_index 可以解决这个问题。 - Laurenz Albe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接