使用kettle,定时将需要同步的数据,生成insert语句的sql文件,通过ftp方式传入专网;专网使用kettle,定时执行sql文件,将数据写入数据库;
使用触发器,实现pgsql的replace into操作,处理update数据;
具体的方案,往下看,当前仅介绍数据的来源跟去向流程,一些监控手段就不做介绍了。
备注:
kettle怎么安装,怎么用,请自行百度。
从数据库到文件:
从文件到数据库:
关键步骤解析:
获取表名称
ctrl_column: 控制增量的字段,用于拼接查询sql,where条件
ctrl_value: 控制增量字段的取值,用于拼接查询sql,where条件取值
column_type: 控制增量字段的类型,用于拼接查询sql,强转where条件取值的类型
column_list: 表的字段list,用于拼接查询sql,调整查询数据格式、字段名称等;非必须
例如拼接后查询语句: select id, ower_id …… from t_com_dictionary where id > ‘0’::integer
sync_flag: 控制是否同步该表数据
-- pgsql获取所有表名称:
select tablename from pg_tables where schemaname='模式名称' order by tablename
-- pgsql获取指定表字段(也可以通过kettle获取表字段):
SELECT col_description(a.attrelid,a.attnum) as comment,format_type(a.atttypid,a.atttypmod) as type,a.attname as name, a.attnotnull as notnull
FROM pg_class as c,pg_attribute as a
where c.relname = '表名称' and a.attrelid = c.oid and a.attnum>0
表名称放入变量
通过js脚本,获取前一个节点查询到的表名称list,将数据放到kettle内存变量里面
var tableRows=previous_result.getRows();
if (tableRows == null && (tableRows.size()==0)){
false; //提示参数异常
} else {
parent_job.setVariable("tables", tableRows);//ArrayList存储表名变量
parent_job.setVariable("size", tableRows.size());//存储执行表的总数量
parent_job.setVariable("i", 0);//循环控制变量
var tableRow = tableRows.get(0); //将第一行数据放到内存变量
parent_job.setVariable("table_name", tableRow.getString("table_name",""));
parent_job.setVariable("ctrl_column", tableRow.getString("ctrl_column",""));
parent_job.setVariable("ctrl_value", tableRow.getString("ctrl_value",""));
parent_job.setVariable("column_type", tableRow.getString("column_type",""));
parent_job.setVariable("column_list", tableRow.getString("column_list",""));
true;
}
检验字段值
更新标志位
生成sql文件
控制循环
var tableRows=previous_result.getRows();
var size = new Number(parent_job.getVariable("size"));
var i = new Number(parent_job.getVariable("i"))+1;
if(i < size){
var tableRow = tableRows.get(i); //循环将每一行数据放到内存变量
parent_job.setVariable("table_name", tableRow.getString("table_name",""));
parent_job.setVariable("ctrl_column", tableRow.getString("ctrl_column",""));
parent_job.setVariable("ctrl_value", tableRow.getString("ctrl_value",""));
parent_job.setVariable("column_type", tableRow.getString("column_type",""));
parent_job.setVariable("column_list", tableRow.getString("column_list",""));
true;
}
parent_job.setVariable("i",i); //重置i的值,用于校验字段值节点,控制循环
true;
sql文件写入数据库
replace into 触发器
CREATE OR REPLACE FUNCTION fn_replace_into() RETURNS TRIGGER AS $BODY$
DECLARE
strSQL VARCHAR;
BEGIN
strSQL = 'DELETE FROM '||TG_TABLE_NAME||' WHERE ID = ' || NEW.ID;
EXECUTE strSQL;
RETURN NEW;
END;
$BODY$ LANGUAGE plpgsql;
CREATE TRIGGER trg_t_system_user BEFORE INSERT ON t_system_user FOR EACH ROW EXECUTE PROCEDURE fn_replace_into();
下载地址:
https://download.csdn.net/download/weixin_42686388/11224766
遇到的问题:
部署Linux需要自行修改一些配置、去掉文件中文名称等;可能这并不是最好的方案,但是我咨询过专业的DBA,网上了查了很多资料,都没找到更适合这种需求的方案,所以整理发出来大家一些交流学习下吧。这个方案目前已经在生产环境运行了将近半年多,还算稳定
觉得写的好的给个赞;觉得有待改进的,请留言一起学习,非喜勿喷。