这样做,免费从Oracle同步数据
点击▲关注 “数据和云” 给公众号标星置顶
更多精彩 第一时间直达
刘伟
刘伟,云和恩墨软件开发部研究院研究员;前微博DBA,主要研究方向为开源数据库,分布式数据库,擅长自动化运维以及数据库内核研究。
不得不承认的一点是,当前数据库的使用趋势,至少在国内,是逐渐从Oracle转向MySQL(扩大化概念的话,就是包括PG等在内的开源数据库,以及rds类的云数据库服务,后文统一以MySQL代指),但在实际的操作层面,如果涉及到现有业务改造,躲避不开的一点是,如何让现有业务平滑地从Oracle切换到MySQL.
如果把这个问题局限在DBA的范畴,不考虑应用开发的难处,处理这个问题的普遍思路是,首先把Oracle做一个一致性备份,全量导入到MySQL,然后从这个一致性的备份作为起点,对Oracle与MySQL同时进行业务操作(一般称为双写),直到某个时间点(一般是两边数据库数据同步时间差距比较小的时候),进行一次业务stop the world,然后切换过去.
在”双写”这个的处理上,就是八仙过海各显神通了.有的是在程序入口分流,通过发布订阅队列直接分开两边程序去跑,有的是在程序写入的时候,DAO层隔离上层应用后,自己直接写两边数据库.等等方式,实际上手段太多了.
而本文讨论的,则是在假设不对应用进行改造(队列化,DAO双写等)的情况下,从Oracle直接同步数据到MySQL的手段.
并且是不花钱的.
当然Oracle本体的授权必须得买,省掉的,是Oracle GoldenGate这个”下船税”.
对于并不关心全文细节的读者,建议直接翻到文章最后面,下载我写的测试脚本验证.
Logminer介绍
如果是一个MySQL DBA,那他最常用的命令行程序之一,必然有mysqlbinlog这个,查故障,数据恢复等等用处简直不要太多了.
而Oracle自带的logminer,就是Oracle世界的mysqlbinlog.主要用途,就是去分析redo日志(当然也包括归档日志),从中提取出来数据的变更,解决故障,恢复数据.
比如oracle的确是支持闪回,但具体恢复到哪个scn编号,就得需要logminer来确定了.
而本文要用的的功能,则是用这种日志分析,来处理”近”实时的数据同步问题.
Oracle作为闭源的数据库,其redo格式虽然文档中有所提及,但实际上真的去做二进制文件分析代价实在太大,这一领域最早的成功者GoldenGate转手就被Oracle收了,并且考虑到法律问题,logminer就成了上帝给开的最后一扇窗户了.
限制条件
曾经业内一位前辈说过,看技术先看限制条件,否则匆匆忙忙研究到最后,却发现自己需求没有满足,就不好了.下文是我目前整理的一些logminer的注意点,以及限制以供参考.
如果是分析非本实例产生的日志,则分析用的实例必须与日志的源实例为同一个硬件平台(注意不是操作系统),并且得是独立的实例,版本号必须等于或者大于源实例,并且数据库的字符集必须与源实例一致或者是超集(处理mysqlbinlog的字符集问题被坑一脸血的人应该对着限制深有感触).
Logminer的运行目录,仅能包含一个源数据库的redo日志,不能一个目录下混合来自多个数据库的redo日志.
所有的redo日志必须有相同的RESETLOGSSCN.并且得是8.0以上版本(部分功能得9.0.1以上版本)的Oracle产生的.
当然,最重要的,就是源数据库必须打开归档模式以及supplemental log.
在具体的数据类型以及表存储类型支持上:
不支持BFILE.
不支持ADT(抽象数据类型)
不支持集合类型的列(嵌套表或者varry类型)
不支持引用对象.
不支持使用了表压缩的表
不支持安全文件.
除了这些之外,同通常的数据类型,以及表存储类型都是支持的.
运行结构
Logminer在用法上,是Oracle内置的一套PL/SQL包,因此所有的运行,都是在Oracle实例内部的,其支持两种模式,简单概括来说,一个是直接分析当前自己数据库的归档以及redo日志,另外一个,是分析其他Oracle数据库的归档以及redo日志.
操作步骤
前面说过,本文讨论的是近实时同步,当然躲不开得写程序(程序全文参考后文),而在写程序之前,先得明白的是,人工执行每个命令的话,需要怎么做.
在执行所有动作之前,需要设置归档模式以及supplemental log,但和本文主题关系不大,就不展开步骤了,网上这方面资料太多了.
就执行logminer,简单来说,有五步.
指定logminer的运行目录
添加所需要分析的日志文件进入分析队列.
启动logminer.
分析redo日志.
关闭分析会话.
以下就来详细解释每一步.
注意:下文假设操作都是在sqlplus操作.如果从程序调度,需要用begin end而非execute调用程序包.
1.指定logminer的运行目录
在决定哪个目录作为分析目录之前,首先需要决定分析期间使用的数据字典用哪个.
Logminer提供了两个选项(文档中的第三个选项flat file已经废弃,不进行多余讨论),一个是直接使用当前数据库作为数据字典来源,而另外一个,是使用独立的logminer字典.
官方有个图很好地说明了这两个选项的选择路线:
如果需要第一种:
EXECUTE DBMS_LOGMNR.START_LOGMNR(
OPTIONS => DBMS_LOGMNR.DICT_FROM_ONLINE_CATALOG);
如果需要第二种:
EXECUTE DBMS_LOGMNR_D.BUILD(
OPTIONS=>DBMS_LOGMNR_D.STORE_IN_REDO_LOGS);
需要注意的是,如果使用第二种方式,需要通过语句确定哪些redo日志中保存了数据字典,语句如下:
SELECT NAME FROM V$ARCHIVED_LOG WHEREDICTIONARY_BEGIN='YES';
SELECT NAME FROM V$ARCHIVED_LOG WHEREDICTIONARY_END='YES';
分析的时候,需要添加这些日志进入分析流.
第二种方式需要定时执行以同步数据字典(比方DDL变更表结构之后),需要注意,否则会导致解析识别错误.
2.添加需要分析的日志文件进入分析队列
这部分执行的,是DBMS_LOGMNR.ADD_LOGFILE这个存储过程,这个存储过程有两个参数,一个是LogFileName,一个是options.
LogFileName是将要被分析的日志的绝对路径(分析过程中实际使用的目录是启动logminer时候指定的,在此处尚未指定)
Options则是可以指定两个选项,一个是NEW,就是结束分析并开始新的分析流.
EXECUTE DBMS_LOGMNR.ADD_LOGFILE( -
LOGFILENAME => '/oracle/logs/log1.f', -
OPTIONS => DBMS_LOGMNR.NEW);
而ADDFILE就是添加指定的redo日志到当前的分析流中.
EXECUTE DBMS_LOGMNR.ADD_LOGFILE( -
LOGFILENAME => '/oracle/logs/log2.f', -
OPTIONS => DBMS_LOGMNR.ADDFILE);
除了这种手动人工的添加方式之外,如果logminer是分析自己数据库的日志,就可以做到自动寻找日志并进行分析,而不需要人工指定.
具体办法是,在启动logminer调用DBMS_LOGMNR.START_LOGMNR的时候,增加CONTINUOUS_MINE选项,这个选项会让logminer从所有归档日志以及redo日志中,从指定的scn或者时间开始分析日志,直到到达指定的结束scn编号,如果没有指定结束时间/scn,那么分析程序会一直维持分析状态,任何数据库实时写入的数据,都会被”近”实时地分析到(在这里,作者遇到的问题是,事务commit之后,并不会马上被分析到,而是等几分钟之后才会被分析到,目前尚未确认原因,如果有人知道,望不吝赐教).
V$LOGMNR_LOGS视图包含了当前已经添加的日志文件,包括自动发现的日志文件
3.启动logminer
终于到启动logminer,这个存储过程的参数描述如下:
DBMS_LOGMNR.START_LOGMNR (
startScn IN NUMBERdefault 0,
endScn IN NUMBERdefault 0,
startTime IN DATE default'01-jan-1988',
endTime IN DATE default'31-dec-2110',
DictFileName IN VARCHAR2 default'',
Options INBINARY_INTEGER default 0 );
抛开显而易见的start,end的四个参数,首先简单说一下dictfilename.前文提到过,为了同步元数据,需要做几个选择,如果当时选择的是第三种,也就是废弃掉的使用文件作为表元数据字典的话,就需要在这个参数指定那个文件.
Options就非常多了,我们逐个梳理下,根据实际需求选择.下面列出表格提供参考.
COMMITTED_DATA_ONLY |
如果选择了这个选项,那么就不会看到回滚或者执行中的事务生成的redo记录对应的导出内容,仅能看到提交成功的数据修改的操作记录. |
SKIP_CORRUPTION |
如果扫描期间,遇到redo内数据块(非redo头)损坏的,就直接跳过 |
DDL_DICT_TRACKING |
前文中有提到当分析的数据库是另外的数据库的话,需要使用redo或者文件存储数据字典,这个选项会在此基础上,根据redo的记录更新内部的数据字典,避免ddl执行导致的数据字典不一致的情况. |
DICT_FROM_ONLINE_CATALOG |
使用内部数据字典作为表元数据字典,仅适用于本实例分析,与DDL_DICT_TRACKING选项冲突. |
DICT_FROM_REDO_LOGS |
结合前文提到BUILD阶段的REDO存储数据字典的选项使用 |
NO_SQL_DELIMITER |
输出的SQL不包含分号,方便导出的语句可以直接执行 |
NO_ROWID_IN_STMT |
默认情况下,生成的SQL语句会包含ROW ID,对于仅关心实际数据的话,可以打开这个选项,但对于没有主键或者唯一键的表,可能会导致错误的更新 |
PRINT_PRETTY_SQL |
格式化输出的SQL,方便阅读,但不能直接用于执行 |
CONTINUOUS_MINE |
让logminer自动发现并扫描日志文件,启动程序仅需要提供scn或者日期.从Oracle 10.1开始,支持Oracle RAC环境下的日志解析,还有一个注意点,Oracle 12.2开始,这个参数转为废弃,后续可能得想别的变通办法处理这个问题. |
调用的时候,options字段,不同的选项以+连接,如下:
EXECUTE DBMS_LOGMNR.START_LOGMNR(OPTIONS=> -
DBMS_LOGMNR.DICT_FROM_ONLINE_CATALOG + -
DBMS_LOGMNR.COMMITTED_DATA_ONLY);
4.分析redo日志
当启动logminer之后,就可以提取分析出来的日志了,方式很简单,就是去查V$LOGMNR_CONTENTS表(需要select any dictionary权限),就可以按照顺序获取到所需要的日志解析内容了.由于原表列数量非常多,我仅提取出来几个一般会需要关注的字段,详细的描述的话,还是参考官方文档吧.
SCN |
数据库当前记录的SCN |
START_SCN |
当前事务开始的SCN,仅在COMMITTED_DATA_ONLY选项启用后有意义. |
COMMIT_SCN |
事务提交时候对应的SCN,仅在COMMITTED_DATA_ONLY选项启用后有意义. |
TIMESTAMP |
数据变更对应的操作系统时间 |
START_TIMESTAMP |
事务的开始时间,仅在COMMITTED_DATA_ONLY选项启用后有意义. |
COMMIT_TIMESTAMP |
事务的提交时间,仅在COMMITTED_DATA_ONLY选项启用后有意义. |
XID |
事务ID |
OPERATION |
SQL操作,这部分内容非常多,一般需要关心的,是INSERT,UPDATE,DELETE,DDL,COMMIT,ROLLBACK, 与事务以及数据操作直接相关的 |
SEG_OWNER |
操作的数据段的拥有者,一般对应实际的表拥有者 |
SEG_NAME |
数据段名称,对应实际的表名称或者表分区等 |
TABLE_NAME |
操作的表名称 |
SEG_TYPE_NAME |
操作的段的类型,一般有表,索引以及分区等类型 |
TABLE_SPACE |
操作的数据块对应的表空间 |
ROW_ID |
操作对应的ROW ID |
USERNAME |
事务的执行者,也就是运行SQL语句的用户名称 |
SQL_REDO |
对于非临时表,此处会生成数据操作对应的SQL语句 |
SQL_UNDO |
对于非临时表,此处会生成反转操作的SQL语句,比如insert对应delete.delete对应insert,update更新新数据为老数据 |
CSF |
如果超过4000字节的SQL,则这个标记为1,表示下一行依然对应这一行的数据变更 |
SRC_CON_NAME |
使用PDB的话,此处为PDB名称 |
Oracle对这个视图的查询执行,看似是查视图,实际上对应的是对日志的顺序扫描.
因此对这个视图的select,切忌不要直接select * from之后,等拿到所有结果集再行处理,而应该以批次分段的形式处理,否则会导致连接oracle的客户端程序占用过多内存,(比如select的时候,python用fetchmany或者fetchone接口,而非fetchall).
另外就是,如果未指定stop scn/时间的话,当查到最新行的时候,sql会话会一直阻塞住,直到有下一行数据产生.
在进一步的使用上, 通过DBMS_LOGMNR.MINE_VALUE处理REDO_VALUE/ UNDO_VALUE列可以用来处理并比较修改的数据,另外一个函数COLUMN_PRESENT则可用来保证MINE_VALUE函数的计算必定非null.示例如下:
SELECT
(XIDUSN || '.' || XIDSLT || '.' || XIDSQN) AS XID,
(DBMS_LOGMNR.MINE_VALUE(REDO_VALUE, 'HR.EMPLOYEES.SALARY') -
DBMS_LOGMNR.MINE_VALUE(UNDO_VALUE, 'HR.EMPLOYEES.SALARY')) AS INCR_SAL
FROM V$LOGMNR_CONTENTS
WHERE
OPERATION = 'UPDATE' AND
DBMS_LOGMNR.COLUMN_PRESENT(REDO_VALUE, 'HR.EMPLOYEES.SALARY') = 1 AND
DBMS_LOGMNR.COLUMN_PRESENT(UNDO_VALUE, 'HR.EMPLOYEES.SALARY') = 1;
5.关闭分析会话
简单来说,就是调用DBMS_LOGMNR.END_LOGMNR函数,没有别的花巧.
Demo代码
https://pan.baidu.com/s/1BiFrrV1EyBOMTIcZT23Rkw
附件文件oracle_dumper.py,是一个基于logminer写的一个每分钟表变更行数量计算的脚本程序,作为后续编程处理的参考.文中忽略的oracle用户授权,supplementlog打开等命令均在代码注释中,提供给感兴趣的人参考.
资源下载
关注公众号:数据和云(OraNews)回复关键字获取
2018DTCC , 数据库大会PPT
2018DTC,2018 DTC 大会 PPT
DBALIFE ,“DBA 的一天”海报
DBA04 ,DBA 手记4 电子书
122ARCH ,Oracle 12.2体系结构图
2018OOW ,Oracle OpenWorld 资料
产品推荐
云和恩墨Bethune Pro企业版,集监控,巡检,安全于一身,你的专属数据库实时监控和智能巡检平台,漂亮的不像实力派,你值得拥有!
云和恩墨zData一体机现已发布超融合版本和精简版,支持各种简化场景部署,零数据丢失备份一体机ZDBM也已发布,欢迎关注。
很“好看”
这样做,免费从Oracle同步数据相关推荐
- Oracle同步数据到MySQL
Oracle同步数据到MySQL 1.首先在TreeSoft数据库中配置两个数据源信息 2.配置数据同步任务,并执行任务 3.同步结果数据查看确认 4.目前TreeSoft支持以下数据同步方案 1.M ...
- oracle同步数据adg_数据库周刊31丨华为openGauss 正式开源;7月数据库排行榜发布......
墨天轮数据库周刊第31期发布啦,每周1次推送本周数据库相关热门资讯.精选文章.干货文档. 热门资讯 1.openGauss 正式开源,华为公开发布源代码 [摘要]6月1日,华为正式宣布开源数据库能力, ...
- oracle同步数据adg_[adg数据库同步机制]三分钟读懂Oracle数据库容灾架之DataGuard
在线QQ客服:1922638 专业的SQL Server.MySQL数据库同步软件 Oracle数据库目前依然处于商用数据库的霸主地位. 运行在Oracle数据库上的核心业务及核心数据的安全性尤为重要 ...
- 通过DataX从Oracle同步数据到MySQL-安装配置过程
DataX DataX 是阿里巴巴集团内被广泛使用的离线数据同步工具/平台,实现包括 MySQL.SQL Server.Oracle.PostgreSQL.HDFS.Hive.HBase.OTS.OD ...
- 《手摸手带你学ClickHouse》之Oracle同步数据到Clickhouse
本文同步发表于我的微信公众号,扫一扫文章底部的二维码或在微信搜索 chaodev 即可关注. 文章目录 前文回顾: <手摸手带你学ClickHouse>之安装部署 <手摸手带你学Cl ...
- 使用DataX从ORACLE同步数据到MYSQL
[前提]安装python3.7 oracle版本:oracle 11g mysql版本:mysql5.7 1.下载DataX wget http://datax-opensource.oss-cn-h ...
- Oracle通过kafka同步数据到MySQL
场景 Oracle同步数据最佳的解决方案是自家的ogg,但是考虑到成本,需要找到其他的解决方案.如果是MySQL通过kafka同步,问题简单的多,因为阿里巴巴的开源数据同步方案--canel是最佳的解 ...
- DataX oracle同步mysql(全量和增量)
本篇博客说说DataX如何进行全量和增量数据同步,虽然用演示oracle同步到mysql,但其他数据库之间的同步都差不多 1.DataX介绍 DataX 是一个异构数据源离线同步工具,致力于实现包括关 ...
- redis和oracle同步方案,redis与oracle之间怎么实现数据同步?
redis与oracle之间怎么实现数据同步? 更新时间:2019-03-12 16:02 最满意答案 没有直接同步的方法,这个依赖于你的架构设计. 插入时同步,比如先更新了oracle,再更新red ...
最新文章
- H标签对网站SEO优化是不可或缺的!
- bt5重启网卡命令_Linux文件的常用操作命令
- 如何代替set get方法
- mssql 跨库获取mysql
- eclipse检测不到android的手机
- Android 系统(200)---Android build.prop参数详解
- Windows学习总结(4)——Host文件的作用和如何修改Host文件
- layui鼠标放上图片局部放大_老照片修复教程之—裁剪图片大小
- sql server 2005练习集(基础)
- retinex算法小感
- 从闪迪的一个U盘看整个行业
- 安装sqlserver 2017安装 需要安装oracle JRE7 更新 51(64位)或更高版本(已解决)
- FI-SAP财务成本知识点汇总
- 一段话加省略号怎么写html,HTML 应用 文字省略号的表示
- 总结了一些微信小程序推广方法
- 可以当零食吃的排骨——椒盐排骨
- Python列表、元组、字典相关练习题记录——第三天
- matlab 类写法,matlab中函数表达式的写法
- 在Ubuntu系统上挂载4T大硬盘的流程
- Javascript函数柯里化及其应用场景
热门文章
- 印度 语言简称_保存印度的语言和文化:图卢维基百科的诞生
- Gnome即将满18岁,适用于Docker,Kali Linux 2.0的新工具以及更多新闻
- docker 虚拟化_如果没有虚拟化,Docker将提供什么?
- openstack安装指南_6种管理OpenStack的新指南
- Bootstrap响应式测试用例
- php网站商品图片上传代码,PHP实现图片上传代码
- openresty json mysql_openresty 前端开发入门五之Mysql篇
- requirejs 多页面,多js 打包代码,requirejs多对多打包
- Flask之Flask实例有哪些参数
- CentOS 6.6 搭建Zabbix 3.0.3 过程