金仓的数据迁移工具不会用?教你手搓一个万能数据迁移工具。
为什么要手搓一个自己的数据库迁移工具
在国产数据库领域,金仓数据库算是比较知名的了,它们都是号称百分百兼容Oracle的,也基本百分百兼容MySQL等数据库,能“无缝”迁移。对这个问题我凭着良心说,金仓等国产数据库在这方面的确很努力,如果这事不努力国人为什么要用你的数据库?努力归努力,是不是真的百分百兼容,是不是真的很好用都要用过才知道,我只能说我不太会用,每次用着用着就卡壳了,不得不求助于金仓的技术支持人员,每次寻求他们支持都要沟通很久,虽说最终都能解决问题但有时候开发任务太紧急,不是每次都有足够时间来寻求他们的支持,于是我决定自己手搓一个数据库迁移工具,而且我这个工具还能反向迁移,即从金仓迁移到MySQL等各种数据库,而不是金仓自己的工具只能从Oracle,SQL Server,MySQL,PostgreSQL这几种数据库迁移到金仓。
我做这个工具的背景介绍完了,现在开始正题。
关于数据迁移,以前工作中经常进行,因此积累了一定的经验,而且还把这些经验写到《SOD框架“企业级”应用数据架构实战》这本书里面了。下面介绍一下怎么使用SOD框架手搓一个数据迁移工具,开始之前必须先了解数据迁移有哪些问题,才能明白手搓一个自己的迁移工具的必要性。
数据迁移的常见问题
数据迁移的第一个问题就是数据量很大,我们往往希望把一个有几百万行、几千万行的表数据从一个小型数据库迁移到一个大中型的数据库中,比如把一个单机MySQL数据库中的数据迁移到金仓数据库集群中;或者将上百万的数据迁移到历史数据库中存档给原来的库瘦身。
第二个问题就是不同类型数据库之间进行迁移,比如从MySQL迁移到金仓、从金仓迁移到Oracle,由于源数据库和目标数据库类型不同,它们支持的字段类型、表类型甚至SQL语法都有差异。有些数据库厂商从商业上考虑可能只愿意提供将别的数据库迁移到自家数据库来的功能而不支持反向迁移。
第三个问题是同一种数据库不同版本之间进行数据迁移。按理说数据库不同版本之间应该保持兼容,至少是高版本兼容低版本的,但国产数据库很牛,它不同版本之间的数据类型是可能不兼容的,导致数据无法直接迁移,这个问题让我明白了金仓数据库迁移工具为何使用起来那么复杂我总是学不会。
第四个问题是数据迁移过程可能还伴随数据筛选、数据清洗和转换,这个属于ETL的范畴了,有一些成熟的ETL工具可以使用,但这些工具使用复杂并且不一定免费。
接下来我们自己手搓迁移工具看怎么解决上面这些问题。
迁移方案设计
- 迁移的数据量很大,所以不能读取太多的数据到内存,最好从源数据读取一部分就写入目标数据库一部分数据;
- 不同种类数据库之间进行数据迁移,由于数据库之间SQL语法、字段类型有差异,所以最好不要直接采用编写SQL语句的方式来实现,用ORM框架可以完美解决这个问题;
- 数据库不同版本之间的数据迁移,注意采用兼容的数据类型即可,如果不能兼容也有办法;
- 第四个问题好办了,由于是自己手搓的工具,迁移前后可以自定义自己的处理逻辑,进行数据筛选、清洗和转换工作都不在话下了。
根据这个迁移方案,采用SOD框架来实现是很合适的,它的设计就是为了解决这些问题而来的。下面我们逐个介绍怎么实现。
准备工作
首先我们需要明确源数据库和目标数据库的类型、版本,数据库连接信息,要迁移的表和视图数据。比如本文的例子以从金仓数据库迁移到MySQL数据库为例,使用VS先创建一个控制台项目,目标框架选择.NET8,然后项目中添加两个Nuget包,在目文件中添加下面的包引用代码:
<PackageReference Include="PWMIS.SOD.Kingbase.Provider.Net6V9" Version="6.0.1" /><PackageReference Include="PWMIS.SOD.MySQL.Provider" Version="6.0.3" />
或者使用Nuget包管理工具,查找 PWMIS.SOD 关键字,然后安装SOD框架的金仓数据库访问提供程序和MySQL数据库访问提供程序:
Install-Package PWMIS.SOD.Kingbase.Provider Install-Package PWMIS.SOD.MySQL.Provider
然后在解决方案资源管理器选择项目名称,右键菜单“添加-新建项-常规”,然后选择“应用程序配置文件”,添加一个 app.config文件,内容如下:
<?xml version="1.0" encoding="utf-8"?> <configuration><appSettings><!--PDF.NET.SOD SQL 日志记录配置(for 4.0)开始记录执行的SQL语句,关闭此功能请将SaveCommandLog 设置为False,或者设置DataLogFile 为空;如果DataLogFile 的路径中包括~符号,表示SQL日志路径为当前Web应用程序的根目录;如果DataLogFile 不为空且为有效的路径,当系统执行SQL出现了错误,即使SaveCommandLog 设置为False,会且仅仅记录出错的这些SQL语句;如果DataLogFile 不为空且为有效的路径,且SaveCommandLog 设置为True,则会记录所有的SQL查询。在正式生产环境中,如果不需要调试系统,请将SaveCommandLog 设置为False 。--><add key="SaveCommandLog" value="True" /><add key="DataLogFile" value="Log\SqlLog.txt" /><!--LogExecutedTime 需要记录的时间,如果该值等于0会记录所有查询,否则只记录大于该时间的查询。单位毫秒。--><add key="LogExecutedTime" value="500" /><!--PDF.NET SQL 日志记录配置 结束--></appSettings><connectionStrings><add name="SourceDb"connectionString="Server=127.0.0.1;User Id=system;Password=system;Port=54321;Database=mydb;"providerName="PWMIS.DataProvider.Data.Kingbase,PWMIS.KingbaseClient.Net6V9" /><add name ="TargetDb"connectionString="server=127.0.0.1;User Id=root;password=123456;DataBase=mydb;"providerName="PWMIS.DataProvider.Data.MySQL,PWMIS.MySqlClient" /></connectionStrings></configuration>
有关如何配置连接字符串的详细内容,请移步框架的Nuget下载页面:NuGet Gallery | PWMIS.SOD 6.0.3
注意金仓数据库访问程序的选择不同版本有点差异,可以移步SOD的金仓数据库Nuget下载页面详细了解:NuGet Gallery | PWMIS.SOD.Kingbase.Provider 6.0.7
到此使用SOD框架开发数据迁移工具的准备工作已经完成,下面正式开始编写实现代码。
创建目标数据库
数据迁移通常都是目标数据库已经存在的情况下进行的,但这里为什么要强调创建目标数据库呢?这是因为很可能既有的目标数据库的数据表和表字段与源数据库是不兼容的,比如目标数据库的字符编码是UTF8,而源数据库是GB2312,目标表的字段类型是int而源表字段的类型是long,或者表字段都是varchar类型但是源表和目标表该字段的长度却不相同,当然更夸张的是连字段名都可能不相同(字段业务含义是一样的),这些千奇百怪的问题只有你想不到没有你遇不到的。所以最佳办法是由迁移工具自动创建一个目标数据库。
SOD框架的Code First方案可以由实体类创建表,它在第一次连接数据库的时候检查表是否存在,如果不存在才创建表,如果表已经存在则跳过以避免意外更改表结构。实现此过程很简单,只需要继承DbContext即可,比如对于本文的目标数据库,创建一个TargetDbContext类:
public class TargetDbContext : DbContext {public TargetDbContext () : base("TargetDb"){}protected override bool CheckAllTableExists(){CheckTableExists<UserInfo>();//创建其它表。。。return true;} }
在上面的代码中,DbContext类的构造函数参数值“TargetDb” 就是app.config中配置的连接名称,重载方法CheckAllTableExists 中 CheckTableExists泛型方法的类型参数UserInfo是一个SOD实体类,它可以根据实体类指定的表名称来创建目标表。
这样,当TargetDbContext类型的对象被实例化的时候就会自动创建好迁移数据的目标表了。
是否插入标识字段
标识字段是用来唯一标识一行数据的,通常标识字段也是主键,但主键不一定是标识字段。在SQLServer等数据库中,标识字段一般用作自增字段,其它数据库也是类似。自增字段通常在插入数据的时候不需要设置值,但在数据迁移的时候,必须将自增字段的值也迁移过去,除非自增字段没有被别的表在逻辑上被引用。在创建表的过程中有一个细节必须注意,就是是否迁移源表的标识字段值,因为在插入一个实体类数据到数据库的时候,通常表的标识字段的数据是不会插入到目标表的,但是如果表的标识字段被其它表引用了那么迁移这个表数据的时候就必须迁移标识字段的数据,这需要在SOD实体类中做一点小小的改进。
大数据量查询
数据复制
批量插入
更新序列值
进度信息
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/952856.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!