您的位置:首页 > 数据库

数据库表记录的一种同步方案

2014-01-10 16:07 274 查看
涉及到多个数据库之间的同步,由于某些原因(某些数据库只需要表内部分数据;数据库类型目前为MySQL,但可能后期部分数据库采用Oracle),不能采用MySQL的主从同步机制。由于对同步的实时性要求不高,记录个数也不是太多,另外做了一种简易的同步方案。

 一、 通过触发器生成数据表版本号

将数据表的每次更新时间记录到另一张版本表中。

drop table if exists Tab_Version_Tab;
create table Tab_Version_Tab
(
Tab_Name			char(40)	not null,		#表名  #
TrigVersion			int			null,		#触发版本号#
SourceVersion			int			null,		#源版本号#
LocalVersion			int			null,		#本地版本号#
constraint pk_Tab_Version_Tab primary key(Tab_Name)
);
delete from Tab_Version_Tab;
insert into Tab_Version_Tab values("Demo1_Tab", 0, 0, 0);
触发器脚本如下:

drop trigger if exists trig_insert_Demo1_Tab;
delimiter |
create trigger trig_insert_Demo1_Tab after insert on Demo_Tab
for each row
begin
update Tab_Version_Tab set TrigVersion=UNIX_TIMESTAMP() where Tab_Name = 'Demo1_Tab';
end;
|
delimiter ;


同样可以建立update,delete的触发器。郁闷的是MySQL的触发器只支持for each row,效率会较低。

在实际应用中,触发器脚本是用LUA脚本生成的。

local file_in = "d:\\sync_tables.sql"
local file_out = "d:\\sync_trigs.sql"
local tbl_prop = {}

local fp = io.open(file_in, "r")
if fp then
while true do
s1 = fp:read("*l")
if not s1 then break end

_,_,s2 = string.find(s1, "\"([%w%_]+)\"")

if s2 then
tbl_prop[s2] = 1
end
end
end

local sql_prep = [[
drop trigger if exists trig_$OP_$TAB;
delimiter |
create trigger trig_$OP_$TAB after $OP on $TAB
for each row
begin
update Tab_Version_Tab set TrigVersion=UNIX_TIMESTAMP() where Tab_Name = '$TAB';
end;
|
delimiter ;
]]

local tbl_rep = {"insert", "update", "delete"}

local fp_out = io.open(file_out, "w")
if fp_out then
fp_out:write("use xopensdb\n")
for k,v in pairs(tbl_prop) do
fp_out:write("-- triggers of " .. k .. "\n")
for k1,v1 in pairs(tbl_rep) do
local sql_out = sql_prep
sql_out = string.gsub( sql_out, "$TAB", k);
sql_out = string.gsub( sql_out, "$OP", v1);
fp_out:write(sql_out)
fp_out:write("\n")
end
fp_out:write("\n")
end
end

二、 维护表记录一致

从数据库定时访问Tab_Version_Tab,检查是否发生变化,如果发生变化,则将主数据库的数据表按条件导入到从数据库的临时表中,然后比较临时表和本地表的记录是否相同:

1. 比较两者记录个数是否相同

2. 用natural join取出的记录个数和本地表记录是否相同

SELECT COUNT(*) FROM table_local NATURAL JOIN table_tmp;

如果不同,则清空本地表,从临时表插入。

MySQL无DBLINK,否则访问远端数据库会简单些。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  MySQL