介绍需求背景:业务系统众多,其数据库之间相互独立,俗称数据孤岛。为了对数据进行统计分析,需要将这些数据收集到数据库中。比如数据仓库,多表关联查询,方便开发数据应用。希望有这样一个工具,指定两个数据库和表名,就可以将表从源数据库复制到目标数据库。具体要求如下:表结构可以自动同步,比如源表增加字段,目标表自动增加字段。支持数据的增量或全量复制,如按日期复制数据。支持同步指定字段,只同步关注的字段。支持主流关系型数据库:mysql、db2、postgresql、oracle、sqlserver源表和目标表的表名可以不同,字段名也可以不同(如果目标表已经存在)。因为要用,所以自己写了一个,顺便熟悉下java开发(之前一直在用Python,不得不说,Java太浪费时间了)。本方案最大的用途是构建市场或数据仓库所需的基础层数据源。欢迎有兴趣的朋友加入。程序Docker模式使用方法:这里使用了三个容器:app是主程序本身,app容器使用的程序文件是release目录下的文件,已经绑定。mysql测试,作为源数据库,已经预先放置了7000条测试数据的表somenzz_users。对于postgres测试,作为目标数据库,没有数据。先部署,执行docker-composeup-d自动完成应用和数据库的部署:$gitclonehttps://github.com/somenzz/database-sync.git$cddatabase-sync$docker-composeup-dCreatingdatabase-sync_postgres_1...doneCreatingdatabase-sync_app_1...doneCreatingdatabase-sync_mysql_1...done三个容器启动。使用dockerps-a|grepdatabase-sync可以看到三个运行中的容器:现在直接使用dockerexec-idatabase-sync_app_1java-jardatabase-sync-1.3.jar执行程序:mysql容器有测试数据,release/config/config.json里面已经配置好了数据库连接,可以直接试试,下面演示从mysql复制表和数据到postgres:1.全量复制,自动建表:dockerexec-idatabase-sync_app_1java-jardatabase-sync-1.3.jarmysql_testtestdbsomenzz_userspostgres_testpublicusers--sync-ddl如果不想每次都输入dockerexec-idatabase-sync_app_1可以在容器内部进入执行:(py38env)?database-syncgit:(master)?dockerexec-itdatabase-sync_app_1/bin/bashroot@063b1dc76fe1:/app#lsconfigdatabase-sync-1.3.jarliblogsroot@063b1dc76fe1:/app#java-jardatabase-sync-1.3.jarmysql_testtestdbsomenzz_userspostgres_testpublicusers-sd2。增量复制:root@063b1dc76fe1:/app#java-jardatabase-sync-1.3.jarmysql_testtestdbsomenzz_userspostgres_testpubliczz_users"create_at>='2018-01-09'"3.指定字段:root@063b1dc76fe1:/app#java-jardatabase-sync-1.3.jarmysql_useridtestdbsomenzz_userspostgres_testpublicz="publiczpostgres_testpublicz="userspostname,gres_test,age"-tf="user_id,name,age""create_at>='2018-01-09'"正常模式运行程序前,确保已经安装了java1.8及以上版本,maven已经安装,并且然后clone源码打包:gitclonehttps://gitee.com/somenzz/database-sync.gitcddatabase-syncmvnpackage此时会看到target目录,把lib目录和database-sync-1.3.jar复制到下面target,把它们放在同一个目录下,然后再新建一个config目录,在config下新建一个config.json文件写入配置信息,然后压缩这个目录,就可以发送到服务器运行了,请注意首先要全面测试,jdk需要1.8+[aaron@hdp002/home/aaron/App/Java/database-sync]$ls-ltrtotal48drwxr-xr-x2aaronaaron4096Apr232020lib-rwxrw-r--1aaronaaron157Jun232020run.shdrwxrwxr-x2aaronaaron4096Jul32020logs-rw-rw-r--1aaronaaron24773Mar162021database-sync-1.3.jardrwxr-xr-x7aaronaaron4096Aug32020jdk1.8.0_231drwxrwxr-x2aaronaaron4096Feb1917:07config也可以直接下载我打包好的应用database-sync,操作方法如下:(py38env)?targetgit:(master)?java-jardatabase-sync-1.3.jar-hUsage:java-jardatabase-sync-1.0.jar[选项]{fromDB}{fromSchema}{fromTable}{toDB}{toSchema}{toTable}[whereClause]options:-vor--version:printversionthenexit-hor--help:printhelpinfothenexit-sdor--sync-ddl:autosynchronizetablestructure-ff=col1,col2or--from-fields=col1,col2:specifyfromfields-tf=col3,col4or--to-fields=col3,col4:specifytofields--no-featureor-nf:willnotusedatabase'sfeaturehelp说明:[]方括号中的内容表示可选,例如[options]表示options下的参数不是必须的。1、options参数解释如下:--sync-ddl或-sd:加入该参数会自动同步表结构。--from_fields=col1,col2or-ff=col1,col2:指定原表的字段顺序,注意=前后不能有空格。--to_fields=col3,col4or-tf=col3,col4:指定目标表的字段顺序,注意=前后不能有空格。2、whereClause表示where条件,用于增量更新。在插入数据之前,程序首先根据where条件清理数据,然后根据where条件从原表中读取数据。whereClause最好用双引号括起来,表示一个完整的参数。例如:"jyrq='2020-12-31'"{}大括号中的内容表示必填。fromDb是指config.json中配置的数据库信息的key,如果有如下配置文件:{"postgres":{"type":"postgres","driver":"org.postgresql.Driver","url":"jdbc:postgresql://localhost:5432/apidb","user":"postgres","password":"aaron","encoding":"utf-8"},"aarondb":{"type":"mysql","driver":"com.mysql.cj.jdbc.Driver","url":"jdbc:mysql://localhost:3306/aarondb?useSSL=false&characterEncoding=utf8&serverTimezone=UTC","user":"aaron","password":"aaron"}}fromDb,toDb可以是aarondb或postgres。fromSchema读取数据的表的schema名,可以填“”。fromTable读取数据的指示,必须提供。toSchema写入数据表的schema名称,可以填“”,可以与fromSchema不同。toTable要写入数据表的表名,必须提供。当写入的表不存在时,会根据读取表的表结构自动创建,可以与fromTable不同。full、incremental、specified字段的使用示例请参考Docker方法。配置文件说明配置文件位于config/config.json如下:{"sjwb":{"type":"db2","driver":"com.ibm.db2.jcc.DB2Driver","url":"jdbc:db2://192.168.1.*:50000/wbsj","user":"****","password":"****","tbspace_ddl":"/*可以放在这里指定表空间的语句*/","encoding":"utf-8"},"dw_test":{"type":"db2","driver":"com.ibm.db2.jcc.DB2Driver","url":"jdbc:db2://192.168.169.*:60990/dwdb","用户":"****","密码":"****","编码":"gbk"},"postgres":{"type":"postgres","driver":"org.postgresql.Driver","url":"jdbc:postgresql://10.99.**.**:5432/apidb","用户":"****","密码":"****","tbspace_ddl":"WITH(压缩=no,orientation=orc,version=0.12)\ntablespacehdfs\n","encoding":"utf-8"},"aarondb":{"type":"mysql","driver":"com.mysql。cj.jdbc.Driver","url":"jdbc:mysql://localhost:3306/aarondb?useSSL=false&characterEncoding=utf8&serverTimezone=UTC","user":"****","password":"****","encoding":"utf-8"},"buffer-rows":100000}配置文件说明:type表示数据库类型,均为小写:mysqlpostgresdb2oraclesqlservertbspace_ddl表示自动建表时指定的表creationSpace,这个选项不是必须的,可以deletebuffer-rows表示读取多少行,逐条写入目标数据库,根据服务器内存大小调整,10万行一次提交,满足大部分情况.encoding用于表结构同步决定字段的长度例如源库的字段是gbkvarchar(10),目标库是utf-8,那么就应该是varchar(15)。这样,如果字段中包含中文,就不会出现截断或插入失败的问题,这里的程序是2次,即varchar(20),这样字段的长度就没有小数位了。最后,为了提高数据库之间表的复制效率,如果不需要转换源表的字段,则丢弃低效的datastage和kettle。
