zoukankan      html  css  js  c++  java
  • PG TO Oracle 增量同步-外部表

    背景

      最近在负责公司数据Oracle转PG;老平台数据库:Oracle11g;新平台数据库:PostgreSQL12。由于平台统计规则有变动;所以正在推广的游戏数据无法全部迁移过来;只能在老平台上运行。而支付数据接口升级;统一进入新平台数据PG。需要将部分支付数据由PostgreSQL同步到Oracle。

      简而言之:PostgreSQL增量同步表到Oracle。首先声明我不是反“去IOE”潮流。我想到两种方案

    一、安装Oracle客户端

    1、下载地址
    http://www.oracle.com/technetwork/database/database-technologies/instant-client/overview/index.html
    2、 安装步骤
    2.1 创建安装目录
    [root@Postgres201 ~]# mkdir -p /u01/app/
    [root@Postgres201 ~]# cd /u01/app/
    2.2 上传软件包并解压
    [root@Postgres201 app]# unzip instantclient-basic-linux.x64-11.2.0.4.0.zip 
    [root@Postgres201 app]# unzip instantclient-sqlplus-linux.x64-11.2.0.4.0.zip 
    [root@Postgres201 app]# unzip instantclient-sdk-linux.x64-11.2.0.4.0.zip 
    [root@Postgres201 app]# mv instantclient_11_2/ oracle
    [root@Postgres201 app]# cd oracle
    2.3 配置网络文件
    [root@Postgres201 app]# cd oracle
    [root@Postgres201 oracle]# mkdir -p network/admin
    [root@Postgres201 oracle]# cd network/admin/
    [root@Postgres201 admin]# vi tnsnames.ora
    ora221 =
      (DESCRIPTION =
        (ADDRESS_LIST =
          (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.1.221)(PORT = 1521))
        )
        (CONNECT_DATA =
          (SERVICE_NAME = orcl)
        )
      )
    2.4 配置用户环境变量
    export  ORACLE_HOME=/u01/app/oracle
    export  TNS_ADMIN=$ORACLE_HOME/network/admin
    export  LD_LIBRARY_PATH=$ORACLE_HOME:$LD_LIBRARY_PATH
    export  PATH=$ORACLE_HOME:$PATH

    二、安装oracle_fdw

      从PostgreSQL9.3开始;Oracle_fdw支持在外部表执行 INSERT, UPDATE 和 DELETE等操作;正好符合我们PostgresQL TO Oracle的方案

    1、下载地址
    http://pgxn.org/dist/oracle_fdw/
    2、安装步骤
    [root@Postgres201 opt]# unzip oracle_fdw-2.0.0.zip
    [root@Postgres201 opt]# cd oracle_fdw-2.0.0
    #加载环境变量后执行 pg_config是否在对应PGHOME/bin目录下。编译后会在对应的目录下面
    [root@Postgres201 oracle_fdw-2.0.0]# source /home/postgres/.bashrc 
    [root@Postgres201 oracle_fdw-2.0.0]# pg_config
    [root@Postgres201 oracle_fdw-2.0.0]# make
    [root@Postgres201 oracle_fdw-2.0.0]# make install
    FAQ:执行make若出现“/usr/bin/ld: cannot find -lclntsh”;原因是找不到库liblclntsh文件;
    解决方案:
    1.    检查环境变量,看ORACLE有关的环境变量是否设置正确
    2.    是否文件名字后有oracle版本信息;需要改名字
    该文件在oracle安装目录下;本例是需要改名字即可
    [root@Postgres201 oracle]# ln -sv libclntsh.so.11.1 libclntsh.so
    [root@Postgres201 oracle_fdw-2.0.0]# make
    [root@Postgres201 oracle_fdw-2.0.0]# make install
    3、创建外部扩展
    adsas=# create extension oracle_fdw;
    ERROR:  could not load library "/app/pg12/lib/postgresql/oracle_fdw.so": libclntsh.so.11.1: cannot open shared object file: No such file or directory
    解决方案:
    1、创建文件/etc/ld.so.conf.d/oracle.conf
    2、添加内容;libclntsh.so.11.1文件所在的路径
    /app/oracle
    3、执行加载ldconfig
    4、再登录psql执行
    adsas=# create extension oracle_fdw;
    CREATE EXTENSION

    三、创建外部表

    CREATE FOREIGN TABLE fdw_game_pay_log (
    ID int8 OPTIONS(key 'true'),
    PAY_TIME timestamp NOT NULL,
    APPID int2 NOT NULL,
    QN varchar(20) NOT NULL,
    ACCOUNTID varchar(64) NOT NULL,
    AMOUNT decimal(6,2),
    ORDER_NO text NOT NULL,
    CP_ORDER_NO text
    ) server oradb OPTIONS (schema 'ADSAS', table 'TBL_GAME_PAY_LOG'); 

    注意的是:

    • 其中schemaname,tablename;需要大写
    • 需要指定在postgres9.3版本以后oracle_fdw支持对外部表的 Insert ,delete ,update ;增加表操作项 options(key 'true') (当值设置为 true|on|yes 表示不可以做增删改操作)

    四、限制

    1、不支持直接 insert ... select

    adsas=> insert into fdw_game_pay_log select * from tbl_game_pay_log;
    ERROR:  error executing query: OCIStmtExecute failed to execute remote query
    DETAIL:  ORA-08177: can't serialize access for this transaction

    这是远程oracle默认的事务隔离级别是repeatable read;不支持“can't serialize access for this transaction”

    解决方法:将语句添加到事务中

    adsas=> begin;
    BEGIN
    adsas=> insert into fdw_game_pay_log select * from tbl_game_pay_log;
    INSERT 0 1
    adsas=> end;
    COMMIT

    五、同步脚本

    CREATE OR REPLACE PROCEDURE "easou"."P_SYNC_TABLE_DATA" ()
        AS $BODY$
        /***********************************************************
         将表tbl_game_pay_log增量复制到fdw_game_pay_log;
         达到PG-Oracle数据增量同步
         ***********************************************************/
    DECLARE
        vn_old_id int8;
        vn_new_id int8;
    BEGIN
        BGEIN
        -- 获取上次提取的id
        SELECT
            lid INTO vn_old_id
        FROM
            easou.tbl_sync_record
        WHERE
            tbl_name = 'tbl_game_pay_log';
        -- 截取本次提取的最大id
        SELECT
            COALESCE(max(id), 0) INTO vn_new_id
        FROM
            easou.tbl_game_pay_log;
        -- 将本次提取的记录插入外部表
        INSERT INTO easou.fdw_game_pay_log (id, PAY_TIME, APPID, QN, ACCOUNTID, AMOUNT, ORDER_NO, CP_ORDER_NO)
        SELECT
            id,
            PAY_TIME,
            APPID,
            QN,
            ACCOUNTID,
            AMOUNT,
            ORDER_NO,
            CP_ORDER_NO
        FROM
            easou.tbl_game_pay_log
        WHERE
            id > vn_old_id;
        -- 更新本次提取的id
        UPDATE
            easou.tbl_sync_record
        SET
            lid = vn_new_id
        WHERE
            tbl_name = 'tbl_game_pay_log';
    END;
    EXCEPTION
        WHEN OTHERS THEN
            INSERT INTO tbl_error_log (error_time, error_desc, proc_name, deal_status)
                VALUES (now()::timestamp, SQLERRM, 'P_SYNC_TABLE_DATA', 0);
    END;
    
    $BODY$
    LANGUAGE plpgsql

    最后通过使用pg_cron或者go_cron添加一个任务。就可以完成准实时的增量同步

  • 相关阅读:
    scanf()常犯错误
    C语言,链表反转
    c语言: 冒泡排序
    判断一个数是否为2的若干次幂
    计算一个整数中含1的个数
    ELF文件的加载过程(load_elf_binary函数详解)--Linux进程的管理与调度(十三)
    Linux进程启动过程分析do_execve(可执行程序的加载和运行)---Linux进程的管理与调度(十一)
    Linux内核线程kernel thread详解--Linux进程的管理与调度(十)
    Linux下进程的创建过程分析(_do_fork do_fork详解)--Linux进程的管理与调度(八)
    Linux下2号进程的kthreadd--Linux进程的管理与调度(七)
  • 原文地址:https://www.cnblogs.com/lottu/p/12794672.html
Copyright © 2011-2022 走看看