如何从Postgres 9.4转储大对象数据,然后将其导入Postgres8.x?

时间:2016-12-06 10:30:45

标签: postgresql blob greenplum

我使用import {Output} from '@angular/core' import {EventEmitter} from '@angular/core' @Component({ selector: 'page-login', templateUrl: 'login.html' }) export class LoginPage { @Output() on_user_has_logged_in : EventEmitter<any> = new EventEmitter() login(MyValue) { this.on_user_has_logged_in.emit(MyValue) } } 从Postgres 9.4中导出包括大对象(LO)的数据,如下所示:

pg_dump

我生成的$ pg_dump fhir -O -b > fhir.sql 中的LO语句是这样的:

fhir.sql

当我在Postgres8.2中执行SET standard_conforming_strings = on; SELECT pg_catalog.lowrite(0, '\x1f8b0800000000000000a5903b6ec3300c86efa2d9b1dad5a728daa2'); 时,我收到了这个错误:

\i fhir.sql

当我ERROR: invalid input syntax for type bytea 时,插入了数据,但是我收到了警告,我SET standard_conforming_strings = off表中的数据是:

pg_largeobject

原始14 | 0 | \0378b0800000000000000a5903b6ec3300c86efa2d9b1dad5a728daa2 已更改为\x1f,我进行了测试,它不再是我原来的zip文件...

我该如何解决这个问题?

更新

我使用Hibernate程序将相同的原始数据插入Greenplum(基于Postgresql8.2),然后使用\037导出它,其格式如下:

pg_dump

2 个答案:

答案 0 :(得分:1)

问题是转储使用函数pg_catalog.lowrite(integer, bytea)来创建大对象,并且PostgreSQL中表示bytea文字的默认语法在版本9.0中已更改。

参数bytea_output可以设置为escape以旧版格式输出bytea以及后来的Pos​​tgreSQL版本。唉,pg_dump在创建转储时不尊重该参数,它总是使用“新”hex格式。

结果是包含PostgreSQL版本9.0或更高版本的大型对象的转储无法恢复到9.0之前的数据库中。

您可能需要以其他方式传输这些大型对象,可能是通过编写迁移程序。

您可以(在pgsql-hackers邮件列表上)建议允许为转储设置pg_dump的{​​{1}}选项,但是您可能会遇到阻力,因为从以后的PostgreSQL恢复转储不支持旧版本的版本。

答案 1 :(得分:0)

<强> UPDATA

我发现了一种更简单的工作方式:只需使用pg_dump -b -Fc将包含LO的数据导出到自定义文件中,稍后使用pg_restore相同版本的pg_dump导出数据以将自定义文件数据导入greenplum。

脚本:

$ pg_dump fhir -O -a -Fc  -f fhir.dump
$ pg_restore -h mdw -d fhir -U gpadmin -a fhir.dump > errors.log 2>&1

我错过的一个事实是lo_export导出二进制数据,它能够完美地导入到greenplum中。

我的解决方案(针对我的情况):

  1. 分别从Postgres9.4导出普通数据(使用pg_dump,排除LO)和LO数据(使用lo_export)。
  2. 将纯数据转储导入Greenplum
  3. 使用lo_import导入LO数据,这将生成一些新的oidlo_import oid从Postgres8.4开始,同时更新相应的{{1}使用这些新oid引用的表。
  4. 示例脚本:

    1. 从Postgres9.4导出普通数据

      oid
    2. 从包含LO数据的某个表中导出LO,使用原始oid命名导出的文件

       $ pg_dump fhir -O -a -n public -f fhir.dmp
      
    3. 将普通数据导入Greenplum

      SELECT lo_export(res_text, '/usr/local/pgsql/export/res_lo/'||res_text) FROM hfj_resource;
      
    4. 在Greenplum中创建一个函数以导入LO并更新引用的oid

      \i fhir.dmp
      
    5. 导入LO

      CREATE FUNCTION import_lo(tab_name text, lo_path text) RETURNS void AS $$
      
       DECLARE
      
          res record;
      
          new_oid oid;
      
       BEGIN
      
          FOR res in EXECUTE 'select res_text from '||$1 LOOP
      
              new_oid := lo_import($2||'/'||res.res_text);
      
              RAISE NOTICE 'res_text from % to %', res.res_text, new_oid;
      
              EXECUTE 'update '||$1||' set res_text='||new_oid||'where res_text='||res.res_text;
      
          END LOOP;
      
          RAISE NOTICE 'import large object into % finished .....', $1;
      
       END;
      
       $$ LANGUAGE plpgsql;