暂无图片
暂无图片
5
暂无图片
暂无图片
暂无图片

Oracle OGG Mysql 同步示例

原创 布衣 2026-04-22
353

一、前言

最近在做Oracle 迁移Mysql 项目,涉及到一套数据库多个用户,500+张表的项目,涉及到各种数值转换。根据此次的迁移经验,总结了此次测试,供大家参考。

二、环境准备

1、数据库信息

IP 数据类型 OGG版本 数据库 用户
192.168.1.10 Oracle 11.2.0.3 ogg_12.3.0.1.4_for_oracle twodb two
192.168.1.11 Mysql 8.35 ggs_Linux_x64_MySQL_64bit twodb root

2、表信息

  • 注:不考虑表涉及的合理性,此示例仅展示不同数据之间的转换
    image.png
  • 其它需求
1、迁移近1周的数据,迁移完成后不丢数据接同步操作;

3、Oracle端

-- Oracle CREATE TABLE SOURCE_TEST ( ID NUMBER(10) PRIMARY KEY, PHONE_NO VARCHAR2(20), -- 原始手机号 USER_ID NUMBER(10), -- 数字ID AMOUNT_STR VARCHAR2(20), -- 字符串金额 CREATE_DATE DATE, -- 创建时间 UPDATE_DATE DATE, -- 更新时间 REMARK VARCHAR2(100) );
  • 存储过程:每秒插入1条数据,每5秒更新1条数据(amt随机± 随机金额)
- 赋权 GRANT EXECUTE ON SYS.DBMS_LOCK TO two; -- 序列 CREATE SEQUENCE seq_source_test MINVALUE 1 MAXVALUE 9999999 START WITH 1 INCREMENT BY 1; - 存储过程 CREATE OR REPLACE PROCEDURE proc_source_test_demo AS v_id NUMBER(10); -- 主键ID v_phone_no VARCHAR2(20); -- 手机号 v_user_id NUMBER(10); -- 用户数字ID v_amount_str VARCHAR2(20); -- 金额字符串 v_rnd_amount NUMBER; -- 随机变动金额 v_update_id NUMBER(10); -- 要更新的ID BEGIN -- 无限循环 WHILE TRUE LOOP -- ============================================= -- 1. 每秒插入 1 条 -- ============================================= v_id := seq_source_test.NEXTVAL; -- 生成随机11位手机号 v_phone_no := '1' || FLOOR(DBMS_RANDOM.VALUE(3, 9)) || LPAD(FLOOR(DBMS_RANDOM.VALUE(0, 999999999)), 9, '0'); -- 随机用户ID 1~100000 v_user_id := FLOOR(DBMS_RANDOM.VALUE(1, 100000)); -- 随机金额(字符串类型) v_amount_str := TO_CHAR(FLOOR(DBMS_RANDOM.VALUE(1, 100000))); -- 插入数据 INSERT INTO SOURCE_TEST ( ID, PHONE_NO, USER_ID, AMOUNT_STR, CREATE_DATE, UPDATE_DATE, REMARK ) VALUES ( v_id, v_phone_no, v_user_id, v_amount_str, SYSDATE, SYSDATE, '自动生成数据' ); COMMIT; DBMS_LOCK.SLEEP(1); -- 等待1秒 -- ============================================= -- 2. 每5秒更新1条(每第5次循环执行) -- ============================================= IF MOD(seq_source_test.CURRVAL, 5) = 0 THEN -- 随机取一条已存在的ID SELECT id INTO v_update_id FROM (SELECT id FROM SOURCE_TEST ORDER BY DBMS_RANDOM.VALUE) WHERE ROWNUM = 1; -- 随机波动 ±10 ~ ±1000 v_rnd_amount := FLOOR(DBMS_RANDOM.VALUE(-1000, 1000)); -- 更新:金额字符串加减后重新赋值 + 更新时间 UPDATE SOURCE_TEST SET AMOUNT_STR = TO_CHAR(TO_NUMBER(AMOUNT_STR) + v_rnd_amount), UPDATE_DATE = SYSDATE, REMARK = '自动更新金额: ' || v_rnd_amount WHERE ID = v_update_id; COMMIT; END IF; END LOOP; END; / -- 后台运行,脚本:vim proc.sh #!/bin/sh source /home/oracle/.bash_profile export con_user='sqlplus -s two/two' result=`$con_user << EOF set serveroutput on ; BEGIN proc_source_test_demo; END; / EOF` echo $result [oracle@MyOracledb ~]$ sh proc.sh &

4、Mysql端

-- 建目标表 CREATE TABLE TARGET_TEST ( ID int(10) PRIMARY KEY, PHONE_NO VARCHAR(20), PHONE_SHORT VARCHAR(10), -- 截取前3位 PHONE_MASK VARCHAR(20), -- 替换后 USER_NO_STR VARCHAR(10), -- 数字转字符串 AMOUNT_NUM decimal(18,2),-- 字符转数字 UPT_TIME datetime, -- 空值判断 OP_TIME datetime, -- OGG当前时间 REMARK VARCHAR(100) )ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;

三、配置并启动同步

-- where 条件 TABLE two.SOURCE_TEST,sqlpredicate "where CREATE_DATE>to_date('2026-03-23','yyyy-mm-dd')";

3.1、Oracle 端

3.1.1 添加表级TRANDATA

ggsci >dblogin userid ggm,password oracle >add trandata two.SOURCE_TEST sqlplus / as sysdba ALTER TABLE two.SOURCE_TEST add SUPPLEMENTAL LOG DATA (ALL) COLUMNS;

3.1.2 配置Extract进程

ggsci >ADD EXTRACT ext1, TRANLOG, BEGIN now, THREADS 2 -- 用add exttrail 命令创建本地 trail 文件 >add exttrail ./dirdat/e1,extract ext1 >edit params ext1 EXTRACT ext1 SETENV (ORACLE_HOME = "/u01/oracle/11.2.0.4/product") SETENV (NLS_LANG=AMERICAN_AMERICA.UTF8) SETENV (NLS_LANGUAGE=AMERICAN_AMERICA.UTF8) SETENV (NLS_TERRITORY=AMERICAN_AMERICA.UTF8) SETENV (LD_LIBRARY_PATH=$ORACLE_HOME/lib:/lib:/usr/lib) SETENV (NLS_DATE_FORMAT = "YYYY-MM-DD HH24:MI:SS") SETENV (NLS_TIMESTAMP_FORMAT = "YYYY-MM-DD HH24:MI:SS.FF6") USERID GGM@twodb, PASSWORD oracle TRANLOGOPTIONS ASMUSER sys@ASM,ASMPASSWORD oracle THREADOPTIONS MAXCOMMITPROPAGATIONDELAY 20000 EXTTRAIL ./dirdat/e1 DISCARDFILE ./dirrpt/ext1.dsc,APPEND,MEGABYTES 1024 DYNAMICRESOLUTION table two.SOURCE_TEST;

3.1.3 配传输进程

# 用 add extract 指定本地 trail 文件 >add extract pump1,exttrailsource ./dirdat/e1,BEGIN now # 用 add rmttrail 指定远程 trail 文件 >ADD RMTTRAIL ./dirdat/e1, EXTRACT pump1 >edit params pump1 EXTRACT pump25 rmthost 192.168.1.11,mgrport 7809 RMTTRAIL ./dirdat/c7 PASSTHRU table two.SOURCE_TEST;

3.2、Mysql 端-配置replicat

ggsci > dblogin sourcedb ogg@192.168.1.11:3306userid ogg,PASSWORD oracle; > add replicat rep1,exttrail ./dirdat/e1,begin now,checkpointtable ogg.ggs_checkpoint -- 配置rep1进程 > EDIT PARAMS rep1 REPLICAT rep1 DYNAMICRESOLUTION HANDLECOLLISIONS SOURCEDEFS ./dirdef/cross.def targetdb ogg@172.16.254.5:3006,userid ogg,password oracle DISCARDFILE ./rep1.dsc, purge, MEGABYTES 100 sqlexec "SET FOREIGN_KEY_CHECKS=0" MAP two.SOURCE_TEST, TARGET paydb.TARGET_TEST, COLMAP ( ID = ID, PHONE_NO = PHONE_NO, -- 截取前3位 PHONE_SHORT = @STREXT(PHONE_NO, 1, 3), -- 替换 123 → xx PHONE_MASK = @STRSUB(PHONE_NO, "123", "xx"), -- 数字转字符串,左侧补0,总长10 USER_NO_STR = @STRNUM(USER_ID, RIGHTZERO, 10), -- 字符串转数字 AMOUNT_NUM = @NUMSTR(AMOUNT_STR), -- 空值判断:CREATE_DATE为空用UPDATE_DATE UPT_TIME = @IF(@ISNULL(CREATE_DATE), UPDATE_DATE, CREATE_DATE), -- OGG 当前时间 OP_TIME = @DATENOW(), REMARK = REMARK );

3.3 同步及迁移操作的启动顺序

  • 1、开启同步的抽取和传输进程
> start ext1 > start pump1
  • 2、开启迁移操作,避免数据丢失
> start e_two
  • 3、当迁移完成后启动rep1
    冲突跳过参数:HANDLECOLLISIONS,当同步完成后,删除此参数
> start rep1

四、ggsci 命令

  • 修改进程参数
>alter replicat rep1,exttrail ./dirdat/e1, BEGIN 2026-03-30 16:12 -- 可定义抽取时间进行抽取: >ALTER EXTRACT ext1, TRANLOG, BEGIN 2026-03-31 19:07
  • STATS EXTRACT ext1
    输出你会看到:
    Total inserts:插入总条数
    Total updates:更新总条数
    Total deletes:删除总条数
    Total operations:总操作数(总行数)
    Bytes processed:处理字节量(数据量)
    Rate:每秒处理速度
# 打印到文件 ggsci << EOF > /home/oracle/ext1_total.log STATS ext1, TOTAL EOF
  • SEND ext1, STATUS
    当前读取的日志
    处理的 RBA 偏移量(字节数)
    延迟
    已处理数据大小

  • 查看 pump 当前运行状态 + 真实配置

191>info pump1 detail EXTRACT PUMP1 Last Started 2026-03-31 19:07 Status RUNNING Checkpoint Lag 00:00:00 (updated 00:00:09 ago) Process ID 38645 Log Read Checkpoint File /u01/backup/ogg12c/dirdat/a1000000000 2026-03-31 19:11:33.000000 RBA 4764421 Target Extract Trails: Trail Name Seqno RBA Max MB Trail Type ./dirdat/a1 0 4730233 500 RMTTRAIL Extract Source Begin End /u01/backup/ogg12c/dirdat/a1000000000 2026-03-31 15:56 2026-03-31 19:11 ./dirdat/a1000000000 * Initialized * 2026-03-31 15:56 /u01/backup/ogg12c/dirdat/a1000000002 * Initialized * First Record /u01/backup/ogg12c/dirdat/a1000000002 * Initialized * First Record /u01/backup/ogg12c/dirdat/a1000000002 * Initialized * 2026-03-31 15:55 /u01/backup/ogg12c/dirdat/a1000000002 2026-03-31 15:55 2026-03-31 15:55 ./dirdat/a1000000000 * Initialized * 2026-03-31 15:55 Current directory /u01/backup/ogg12c Report file /u01/backup/ogg12c/dirrpt/PUMP1.rpt Parameter file /u01/backup/ogg12c/dirprm/pump1.prm Checkpoint file /u01/backup/ogg12c/dirchk/PUMP1.cpe Process file /u01/backup/ogg12c/dirpcs/PUMP1.pce Error log /u01/backup/ogg12c/ggserr.log

五、 针对多表表,规则简单,批量映射

  • MAP拼接SQL:对’crt_time’,'upt_time’2个字段值=@DATENOW(),其它字段不变,此SQL仅记录,与测试无关
mysql -P 3306 -u ogg -p'oracle' -e " SET SESSION group_concat_max_len = 102400; SELECT REPLACE( REPLACE( CONCAT( 'map twodb.', TABLE_NAME, ' , TARGET twodb.', TABLE_NAME, ',', 'COLMAP (', GROUP_CONCAT( CONCAT(COLUMN_NAME, ' = ', IF(COLUMN_NAME IN ('crt_time','upt_time'), '@DATENOW()', COLUMN_NAME)) ), ');' ), '\n', ''), -- 去掉换行 '\r', '') -- 去掉回车 AS result FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'twodb' and table_name in ('t') group by TABLE_NAME ORDER BY ORDINAL_POSITION;" > map.txt

六、问题

OGG-00768

ERROR OGG-00768 DYNSQL: Preparing SQL statement (ID = 0) failed. SQL error (1064). You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '%T SET %S WHERE %W' at line 1. ERROR OGG-01668 PROCESS ABENDING.

OGG-00768 + MySQL 1064 语法错误,报错信息:%T SET %S WHERE %W 非法 SQL,进程异常终止,多发生在 UPDATE 主键 场景

  • 根本原因
    HANDLECOLLISIONS 参数与 MySQL 不兼容
    该参数在遇到更新主键时,会把 UPDATE 转成非法的 Oracle 风格 SQL 模板
    MySQL 无法识别 %T/%S/%W 占位符,直接报 1064
  • 解决:删除参数:HANDLECOLLISIONS

OGG-02171

ERROR OGG-02171 Error reading LCR from data source. Status 509, data source type 0. ERROR OGG-02191 Incompatible record 101 in /data/ogg/dirdat/b2000000000, rba -2 when getting trail header.

trail 文件 b2000000000 格式不兼容、版本不对、已损坏REPLICAT 无法读取,直接崩溃。

  • 解决:
-- 将b2000000000 删除,调整pump参数重新传输,重新应用 -- 目标端 stop rep11 rm -rf b2000000000 -- 源端 stop pump11 alter extract pump11,exttrailsource ./dirdat/b2,BEGIN 2026-04-01 14:36 start pump11 -- 目标端 alter replicat rep11,exttrail ./dirdat/b2, BEGIN 2026-04-01 14:36 start rep11

update 转换为insert 导致数据重复

  • 方法1:对无主建键表创建主键;
ALTER TABLE two.t_info ADD PRIMARY KEY (id);
  • 方法1:KEYCOLS (业务唯一列);
    无规划主键的表,可以指示单列或多列做为唯一性处理
MAP two.t_info, TARGET two.t_info, KEYCOLS (业务唯一列); <-- 比如 id、order_no、request_id ;
  • 方法2:APPLYNOOPUPDATES:
    按全表所有列更新增加参数
参数 作用 备注
ALLOWNOOPUPDATES 无主键表 跳过 UPDATE 会丢数据
APPLYNOOPUPDATES 无主键表 强制执行 UPDATE 会丢数据丢数据,但用所有列更新
REPLICAT rep11 APPLYNOOPUPDATES <-- 加这行 SQLEXEC "SET FOREIGN_KEY_CHECKS=0" ...

欢迎赞赏支持或留言指正
image.png

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

文章被以下合辑收录

评论