代码之家  ›  专栏  ›  技术社区  ›  Matthew C

Postgres pg_转储缓存查找索引失败

  •  5
  • Matthew C  · 技术社区  · 7 年前

    我正在尝试使用以下命令创建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 不存在。有没有办法解决这个问题,或者忽略这个错误并继续,这样我就可以继续导出非- pg_catalog 数据

    3 回复  |  直到 7 年前
        1
  •  1
  •   Michel Milezzi    7 年前

    系统索引可能已损坏。我会尝试以下方法:

    1. 停止数据库服务器
    2. 在单用户模式下启动数据库,忽略系统和用户定义的索引:

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

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

    4. 重新启动数据库并再次尝试转储。。。

    更多信息: ignore_system_indexes , REINDEX , enable_bitmapscan/enable_indexscan , single-user mode ;

        2
  •  1
  •   Matthew C    7 年前

    我编写了一个快速脚本,将每个表分别转储到一个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
    
        3
  •  0
  •   Laurenz Albe    7 年前

    您的数据库已损坏,应该从备份中恢复。

    如果您不怕弄乱目录(请先进行物理备份!):

    设置配置参数 allow_system_table_mods on 因此,您可以修改系统目录。然后

    DELETE FROM pg_catalog.pg_index WHERE indexrelid = 1184605879;
    

    也许这会使您的数据库处于可以转储它的状态(减去该索引)。

    如果出现更多问题,您可能会使用 COPY