| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 大数据 -> oracle异构迁移mysql方案实施(含原理)——已迁移成功 -> 正文阅读 |
|
[大数据]oracle异构迁移mysql方案实施(含原理)——已迁移成功 |
目录 一、迁移原由 二、迁移目标 三、迁移方案落地 1.协同高层确定项目目标 2.制定迁移计划 四、迁移工具选型(含功能实现原理) (1)SQL LOAD (2)OGG (3)KETTLE (4)DATAX (5)ADAM STUDIO (6)DTS 五、对象兼容性改写 1.oracle与mysql数据类型转换详情 2.大小写敏感参数 3.数据库对象不兼容改写方案 (1)view (2)物化视图 (3)Trigger、存储过程、package (4)分页语句 (5)JOIN (6)group by语句 (7)bitmap位图索引 (8)分区表(Partitioned table) (9)角色 (10)表情和特殊字符 六、全量数据校验方案 1.全量数据验证逻辑流图 2.全量数据验证脚本逻辑 3.数据验证注意事项 七、压力测试 八、迁移演练 九、正式迁移 ?重复数据处理方案 1).重复数据出现原因: 2).解决方案 十、迁移后性能调优 1.上线后持续关注目标端数据库性能 2.参数调优 innodb_flush_log_at_trx_commit sync_binlog max_allowed_packet innodb_log_file_size innodb_log_buffer_size innodb_buffer_pool_size innodb_buffer_pool_instances 一、迁移原由?“去O”,是近些年来一直很火的一个话题。但2019年,也许有着更加特殊的意义。随着国家监管要求、外部环境变化、国产数据库兴起等多种因素,相信今年会是“去O”井喷发展的一年。去O更详细的说是去IOE。
二、迁移目标
三、迁移方案落地1.协同高层确定项目目标这里需要确定的包括迁移源端(如哪几个oracle数据库)、目标端(如迁移到RDS For MySQL、或者机房自建MySQL) 2.制定迁移计划这里的迁移计划指的是整个迁移过程的整体排期,包含:
那么下面就按照该部分迁移计划中的步骤,叙述详细内容及关键点 四、迁移工具选型(含功能实现原理)大家再迁移前,可以了解到,迁移涉及到结构迁移和数据迁移,那么在迁移工具选型的时候,需要考虑的几点:
这里简单聊几个目前常见的oracle迁移mysql的工具及与原理: (1)SQL LOAD这里使用的是powerdesigner,使用该工具迁移结构,首先在plsql中将oracle数据库中的表结构导出csv/sql,使用powerdesigner加载导出的oracle结构语法转换为mysql结构语法,转换后的结构语法存在大量改写:
(2)OGGOracle?GoldenGate(OGG)可以在多样化和复杂的?IT?架构中实现实时事务更改数据捕获、转换和发送;其中,数据处理与交换以事务为单位,并支持异构平台,例如:DB2,MSSQL等
但OGG有一个缺陷,做不到全量数据对比! (3)KETTLEKettle是一款国外开源的ETL工具,可以在Windows、Linux、Unix上运行,纯java编写。该工具使用前需要做代码改造,以适用现有的业务场景。 (4)DATAXDataX 是阿里巴巴集团内被广泛使用的离线数据同步工具/平台,实现包括 MySQL、Oracle、HDFS、Hive、OceanBase、HBase、OTS、ODPS 等各种异构数据源之间高效的数据同步功能。DataX采用了框架 + 插件 的模式,目前已开源,代码托管在github。 DATAX底层原理:
(5)ADAM STUDIO阿里云官方描述:ADAM推出Oracle数据库平滑迁云解决方案,覆盖Oracle迁移的全生命周期,包括数据库与应用评估(兼容性、关联关系、性能、风险点、应用改造点)、转换(转换不兼容点、引擎特征优化转换)、结构迁移、数据迁移、一致性校验、SQL仿真回放、割接、优化。
(6)DTS
关于DTS同步数据的原理可以类比于OGG,给大家放一张图,如需要深入了解,可以看本人的这篇博客【阿里云DTS原理】 https://blog.csdn.net/qq_44714603/article/details/105205150 这里补充几个在DTS在迁移过程中需要改造的几个点:
五、对象兼容性改写对于对象兼容性这部分,大家需要兼顾人员分配。
1.oracle与mysql数据类型转换详情2.大小写敏感参数我们较为了解的是表结构大小写敏感参数lower_case_table_names,但是数据内容区分大小写敏感参数(collate)参数使用可能较少,由于oracle默认是区分数据大小写的,为达到迁移前后一致性,所以我们需要对这个参数做显式修改。(该参数非常关键!!) Collate参数在官方文档中的解释:https://dev.mysql.com/doc/refman/5.7/en/charset-binary-collations.html
3.数据库对象不兼容改写方案(1)view在MySQL里view是不可以嵌套子查询的: ?????? create view v_ceshi?as select * from (select * from test) t; ?????? ERROR 1349 (HY000): View's SELECT contains a subquery in the FROM clause 解决方法就是view的嵌套: ?????? create view v_test as select * from test; ?????? Query OK, 0 rows affected (0.02 sec) ?????? create view v_ceshi?as select * from v_test; ?????? Query OK, 0 rows affected (0.00 sec) (2)物化视图物化视图用于预先计算并保存表连接或聚集等耗时较多的操作结果,这样在执行查询时,就可以避免进行这些耗时的操作,而从快速得到结果。但是MySQL里没有这个功能。通过事件调度和存储过程模拟物化视图,实现的难点在于更新物化视图,如果要求实时性高的更新,并且表太大的话,可能会有一些性能问题。 (3)Trigger、存储过程、package1)Oracle创建触发器时允许or,但是MySQL不允许。所以迁移时如果有需要写两个。 2)两种数据库定义变量的位置不同,而且MySQL里不支持%type。这个在Oracle中用得太频繁了,是个好习惯。 3)elseif的逻辑分支语法不同,并且MySQL里也没有for循环。 4)在MySQL中不可以返回cursor,并且声明时就要赋对象。 5)Oracle用包来把存储过程分门别类,而且在package里可以定义公共的变量/类型,既方便了编程,又减少了服务器的编译开销。可MySQL里根本没有这个概念。所以MySQL的函数也不可以重载。 6)预定义函数。MySQL里没有to_char() to_date()之类的函数,也并不是所有的Oracle都是好的,就像substring()和load_file()这样的函数,MySQL有,Oracle却没有。 7)MySQL里可以使用set和=号给变量赋值,但不可以使用:=。 而且在MySQL里没 || 来拼接字符串。 ?8)MySQL的注释必须要求-- 和内容之间有一个空格。 9)MySQL存储过程中只能使用leave退出当前存储过程,不可以使用return。 10)MySQL异常对象不同,MySQL同样的可以定义和处理异常,但对象名字不一样。 业务SQL中如果有下面的函数使用,需要改写成mysql支持的:对于mysql不建议使用存储过程 oracle与mysql之常用函数的区别: nvl(xx, 0) ==> coalesce(xx, 0) 说明:返回第一个非空值。 to_char(xx) ==> cast(xx as char) 说明:转换为char类型 to_char(xx,'yyyymmdd') ==> date_format(xx, '%Y%m%d') 说明:日期格式化,date_format具体参数查询文档 to_char(xx,'yyyyq') ==> concat(date_format(xx, '%Y'), quarter(xx)) 说明:mysql date_format无法格式化季度,需要借助quarter函数 to_number(xx) ==> cast(xx as unsigned integer) 说明:转换为数字类类型,unsigned integer为无符号整数 sysdate ==> now()或者用current_timestamp代替,由于oracle在TIMESTAMP是有时区信息,这块改成mysql后不带时区的,所以对于高精度这块mysql不能完全解决。 说明:获取当前时间 decode(cond, val1, res1, default) ==> case when cond = val1 then res1 else default end 说明:根据cond的值返回不同结果 trunc(xx, 2) ==> convert(xx, decimal(6,2)) 说明:保留2位小数 wm_concat(xx) ==> group_concat(xx) 说明:列转行 over() ==> 无 说明: mysql没有开窗函数,需要代码实现 oracle与mysql之语法的区别: connect by…start with ==> 无 说明: mysql没有递归查询,需要代码实现 rownum ==> limit 说明:分页 'a'||'b' ==> concat('a', 'b') 说明:字符串拼接 select xx from (select xx from a) ==> select xx from (select xx from a) t1 说明:from后的子查询必须有别名 nulls last ==> 无 说明:mysql排序时,认为null是最小值,升序时排在最前面,降序时排在末尾 group by (a, b) ==> group by a, b 说明:mysql group by 字段不能加括号 begin end; ==> begin; commit; 说明:mysql事务控制begin后需要加分号执行,提交使用commit。P.S.禁止在sql中进行事务控制 select 1, 1 from dual union select 1, 1 from dual ==> select 1 as a, 1 as b from dual union select 1 as a, 1 as b from dual 说明:mysql的union查询的每个字段名必须不同 null值在oracle和mysql中的差异 说明:在oracle和mysql中null都表示为空的意思,但是两者之间还是有差异的,oracle中null与''是等价的,但是在mysql中null与''则不是等价的,在不同的数据库中,''与null是有差异的。oracle中的''与 null是等价的,但是我们在写sql时不能使用''=null这种方式,只能是'' is null这种方式;而在mysql中''与not null是等价的,同理我们在写sql时不能使用'' <> null这种方式,只能用'' is not null。 Oracle中date类型对应 MySQL 时间类型以及空值的处理 Oracle数据库的date类型和mysql的date类型是不一样的,Oracle为yyyy-mm-dd hh:mi:ss和mysql中的datetime类型匹配, 而mysql 为 yyyy-mm 。当在存在空值的时候,mysql的time 类型可以使用0零来插入,而date,datetime,timestamp可以使用null 来插入,但是timestamp即使为null,也会默认插入当前时间戳。 (4)分页语句MySQL中使用的是limit关键字,但在Oracle中使用的是rownum关键字。所以每有的和分页相关的语句都要进行调整。 (5)JOIN如果你的SQL里有大量的(+),这绝对是一个很头疼的问题。需要改写。 (6)group by语句Oracle里在查询字段出现的列一定要出现在group by后面,而MySQL里却不用。只是这样出来的结果可能并不是预期的结果。造成MySQL这种奇怪的特性的归因于sql_mode的设置,一会会详细说一下sql_mode。不过从Oracle迁移到MySQL的过程中,group by语句不会有跑不通的情况,反过来迁移可能就需要很长的时间来调整了。 (7)bitmap位图索引在Oracle里可以利用bitmap来实现布隆过滤,进行一些查询的优化,同时这一特性也为Oracle一些数据仓库相关的操作提供了很好的支持,但在MySQL里没有这种索引,所以以前在Oracle里利于bitmap进行优化的SQL可能在MySQL会有很大的性能问题。 目前也没有什么较好的解决方案,可以尝试着建btree的索引看是否能解决问题。要求MySQL提供bitmap索引在MySQL的bug库里被人当作一个中级的问题提交了上去,不过至今还是没有解决。 (8)分区表(Partitioned table)需要特殊处理,与Oracle的做法不同,MySQL会将分区键视作主键和唯一键的一部分。为确保不对应用逻辑和查询产生影响,必须用恰当的分区键重新定义目标架构。 (9)角色MySQL8.0以前也没有role的对象。在迁移过程中如果遇到的角色则是需要拼SQL来重新赋权。不过MySQL更好的一点是MySQL的用户与主机有关。 (10)表情和特殊字符在Oracle里我们一般都选择AL32UTF8的字符集,已经可以支付生僻字和emoji的表情了,因为在迁移的时候有的表包含了大量的表情字符,在MySQL里设置了为utf8却不行,导过去之后所有的都是问号,后来改成了utf8mb4才解决问题,所以推荐默认就把所有的DB都装成utf8mb4吧。 Oracle和MySQL差异远远不止这些,像闪回、AWR这些有很多,这里只谈一些和迁移工作相关的。 六、全量数据校验方案前面我们在迁移工具选型的时候,就了解到,目前很多迁移工具是做不到数据校验的,甚至少部分可以校验的迁移工具也仅仅是做针对约束列的数据校验,所以,我们这里采用开发自主脚本实现全量的数据校验 1.全量数据验证逻辑流图2.全量数据验证脚本逻辑
从上面的脚本逻辑中可以看到,该自主研发脚本是做不到动态验证数据的,所以要求必须在停服后,导出静态数据,对比两端,所以为了节省更多的时间,数据验证脚本这步可以采用并行导出数据的方案。 3.数据验证注意事项
七、压力测试这里在压力测试的时候,研发更加熟悉业务,DBA更加擅长数据库性能优化,所以该步骤建议DBA协助研发同学执行测试过程 八、迁移演练注意事项:
九、正式迁移在DBA迁移演练和研发测试可以验收后,在业务低峰期的范围内确定停服时间进行正式迁移
?重复数据处理方案1).重复数据出现原因:迁移工具在重放update时,是delete+insert操作,但是delete操作丢失,insert成功,导出重复数据的出现 2).解决方案1.添加主键、唯一键 2.Group by或者distinct去重导出临时表,rename原表为test_bak,在rename临时表为test (1)所有列去重
(2)部分列去重
对于标准的sql_mode: 对于不标准的sql_mode: 迁移当天:
二者相等的情况下,说明col1,col3这两列没有重复数据,在阿里云以group by col1,col3导出,再导入到腾讯云(不丢失数据),再建立组合唯一索引 讨论: ?????如果上面情况,二者不等,说明col1,col3这两列有重复数据,如何处理? ??????????????? 1.组合唯一索引增加一列col2,以确定唯一性 ??????????????? 2.前提:如果允许删除col1,col3重复,col2不重复的行(保留唯一键重复的首行) ????????????????? (1)那么可以通过增加一列自增主键列,保留重复行主键号最小的一行进行删除(删除效率很低)
???????????????? (2)逻辑上拼主键,having出来的都是重复数据,然后现在有了重复数据的起始主键值a,和重复行数b,要删除的主键值就是(a+1~a+b-1)这个段,然id等于这部分,直接删。(如果重复行,主键号不连续,该方法不可行) 十、迁移后性能调优DBA在正式迁移完数据后,需要协助研发做最终的回归测试,测试验证通过后,启服上线! 1.上线后持续关注目标端数据库性能如出现慢查询等导致CPU或IO骤升骤减的情况,请及时优化SQL 2.参数调优我们可以在导入数据的时候预先的修改一些参数,来获取最大性能的处理,比如可以把自适应hash关掉,Doublewrite关掉,然后调整缓存区,log文件的大小,把能变大的都变大,把能关的都关掉来获取最大的性能,我们接下来说几个常用的: innodb_flush_log_at_trx_commit如果innodb_flush_log_at_trx_commit设置为0,log buffer将每秒一次地写入log file中,并且log file的flush(刷到磁盘)操作同时进行。该模式下,在事务提交时,不会主动触发写入磁盘的操作。 如果innodb_flush_log_at_trx_commit设置为1,每次事务提交时MySQL都会把log buffer的数据写入log file,并且flush(刷到磁盘)中去。 如果innodb_flush_log_at_trx_commit设置为2,每次事务提交时MySQL都会把log buffer的数据写入log file。但是flush(刷到磁盘)的操作并不会同时进行。该模式下,MySQL会每秒执行一次 flush(刷到磁盘)操作。 注意:由于进程调度策略问题,这个“每秒执行一次 flush(刷到磁盘)操作”并不是保证100%的“每秒”。 sync_binlogsync_binlog 的默认值是0,像操作系统刷其它文件的机制一样,MySQL不会同步到磁盘中去,而是依赖操作系统来刷新binary log。 当sync_binlog =N (N>0) ,MySQL 在每写N次 二进制日志binary log时,会使用fdatasync()函数将它的写二进制日志binary log同步到磁盘中去。 注:如果启用了autocommit,那么每一个语句statement就会有一次写操作;否则每个事务对应一个写操作。 max_allowed_packet在导大容量数据特别是CLOB数据时,可能会出现异常:“Packets larger than max_allowed_packet are not allowed”。这是由于MySQL数据库有一个系统参数max_allowed_packet,其默认值为1048576(1M),可以通过如下语句在数据库中查询其值:show VARIABLES like '%max_allowed_packet%';? 修改此参数的方法是在MySQL文件夹找到my.cnf文件,在my.cnf文件[MySQLd]中添加一行:max_allowed_packet=16777216 innodb_log_file_sizeInnoDB日志文件太大,会影响MySQL崩溃恢复的时间,太小会增加IO负担,所以我们要调整合适的日志大小。在数据导入时先把这个值调大一点。避免无谓的buffer pool的flush操作。但也不能把 innodb_log_file_size开得太大,会明显增加 InnoDB的log写入操作,而且会造成操作系统需要更多的Disk Cache开销。 innodb_log_buffer_sizeInnoDB用于将日志文件写入磁盘时的缓冲区大小字节数。为了实现较高写入吞吐率,可增大该参数的默认值。一个大的log buffer让一个大的事务运行,不需要在事务提交前写日志到磁盘,因此,如果你有事务比如update、insert或者delete 很多的记录,让log buffer 足够大来节约磁盘I/O。 innodb_buffer_pool_size这个参数主要缓存InnoDB表的索引、数据、插入数据时的缓冲。为InnoDN加速优化首要参数。一般让它等于你所有的innodb_log_buffer_size的大小就可以, innodb_log_file_size要越大越好。 innodb_buffer_pool_instancesInnoDB缓冲池拆分成的区域数量。对于数GB规模缓冲池的系统,通过减少不同线程读写缓冲页面的争用,将缓冲池拆分为不同实例有助于改善并发性。 |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/24 12:07:24- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |