利用Sqlserver的CDC功能实现2张表的同步更新

摘要:
Sqlserver使用CDC函数实时同步两个表的数据。第一个应用程序环境仅在SQL Server 2008(包括)之后的企业版、开发版和评估版中可用。在打开CDC函数之前,请记住打开sqlserver2的代理服务器。关于CDC函数,CDC函数主要捕获SQL server指定表的添加、删除和修改。由于任何操作都会写入日志,CDC捕获来自日志文件。

Sqlserver利用CDC功能实时同步两张表数据
一  适用环境
仅在SQLServer2008(含)以后的企业版、开发版和评估版中可用。

在开启CDC功能前,记得要把sqlserver的代理服务器打开。、

二 CDC功能大概介绍
CDC(change data capture)功能主要捕获SQLServer指定表的增删改操作,由于任何操作都会写日志(哪怕truncate),所以CDC的捕获来源于日志文件。日志文件会把更改应用到数据文件中,同时也会标记符合要求的数据标记为需要添加跟踪的项。然后通过一些配套函数,最后写入到数据仓库中。大概流程如图:

三 具体同步步骤以及截图
1准备工作
现在假设有2个数据库和2张表,db1是我们的目标数据库,里面有一张目标表t_cdc_ta,对目标表的所有增删改查操作,我们想要同步到结果库monitor里的结果表t_cdc_ta里。

首先创建这样2张表

create database db1;

create databasemonitor;

然后创建表结构,如下


CREATETABLE [t_cdc_ta]
(
[id] [int] IDENTITY(1,1) PRIMARY KEY NOT NULL,
[name] [varchar](20) NULL,
[addr] [varchar](20) NULL,
[ttime] [datetime] NULL
)

2对数据库开启CDC功能
开启cdc功能

USEdb1
GO
EXEC sys.sp_cdc_enable_db
-验证

--检查是否开启成功

SELECT  is_cdc_enabled ,

        CASE WHEN is_cdc_enabled = 0 THEN 'CDC功能禁用'

             ELSE 'CDC功能启用'

        END 描述

FROM    sys.databases

WHERE   NAME = 'db1'
--0 :未开启cdc 1:开启cdc

然后可以发现数据库db1里的一些变化

db1的安全性里的用户添加了cdc,架构也添加了cdc

在sqlserver代理里,我们也会发现,增加了目标库的capture和cleanup,一个负责捕获变化,一个负责清除变化。

3对某张表具体开启cdc功能
USE db1;

GO

EXECsys.sp_cdc_enable_table      

       @source_schema ='dbo'       

         ,@source_name='t_cdc_ta'       

         ,@role_name=null      

         ,@capture_instance=NULL        

         ,@supports_net_changes=1       

         ,@index_name=null       

         ,@captured_column_list=null      

          ,@filegroup_name=default      

         ,@allow_partition_switch=1

这里补充说明下,source_schema是表的拥有者,source_schema是表名。

role_name可以写null,但是如果设置了比如设置成cdc_Admin,那么可以在角色一栏自动创建的

具体语句

USE db1;

GO

EXECUTEsys.sp_cdc_enable_table

    @source_schema = 'dbo'

  , @source_name = 't_cdc_ta'

  , @role_name = 'cdc_Admin'--可以自动创建

  , @capture_instance=DEFAULT

GO

执行完后,我们会发现,在db1的系统表里会生成这样一张表

这张表就是针对目标表的增删改操作会生成相关的监听数据,写进这张表里,下面我们来事例下

4测试cdc功能,看看日志表情况(记录目标表的变化情况)
对目标表进行相关的增删改操作

use db1;

insert intodbo.t_cdc_ta(id,name,addr,ttime) values

(1,'zjm','addr1','2017-10-1909:56:15.000'),

(2,'zjm2','addr2','2017-10-1909:56:15.000'),

(3,'zjm3','addr3','2017-10-1909:56:15.000'),

(4,'zjm4','addr4','2017-10-1909:56:15.000')

update dbo.t_cdc_taset name='xxq' where id=1

delete fromdbo.t_cdc_ta where id=3

此时我们看下日志表的具体情况

  select * from [db1].[cdc].[dbo_t_cdc_ta_CT]

右边边框是目标表里的数据,对于[__$operation]列,相当于对于增删改打了个标签,1代表删除,2代表插入,3代表update的旧数据,4代表update的新数据。

5如何针对日志表对结果表同步
先针对结果表写一个存储过程,实现对结果表的增删改操作

Use monitor

CREATE  PROC [dbo].[p_merge]

@oper INT,

@id INT,

@name VARCHAR(20),

@addr VARCHAR(20),

@ttime DATETIME

AS

-- 删除

   IF @oper=1

   BEGIN

     DELETE FROM  dbo.t_cdc_ta

     WHERE id=@id

   END

   ELSE IF @oper=2  --  新增

    BEGIN

      INSERT INTO  dbo.t_scdc_ta(id,NAME,addr,ttime)

      VALUES(@id,@name,@addr,@ttime)

   END

   ELSE IF @oper=4   -- 更新

   BEGIN

    UPDATE dbo.t_cdc_ta

      SET NAME=@name,addr=@addr,ttime=@ttime

      WHERE id=@id   

   END

  

GO

此时,就可以看到写好的存储过程了

在写一个游标的代码,一条一条遍历日志表的数据,嵌套刚才存储过程

use db1

 declare @oper INT

 declare @id INT

 declare @name VARCHAR(20)

 declare @addr VARCHAR(20)

 declare @ttime DATETIME

--定义一个游标

declare user_curcursor for select __$operation,id ,name,addr,ttime fromdb1.cdc.dbo_t_cdc_ta_CT 

--打开游标

open user_cur

while@@fetch_status=0

begin

--读取游标

    fetch next from user_cur into @oper,@id,@name,@addr,@ttime

       use monitor

       set identity_insert  t_cdc_ta on

       exec dbo.p_merge @oper,@id,@name,@addr,@ttime

  

end

close user_cur

deallocate user_cur

上面的同步脚本写好之后,下面给一个企业级同步的方案

比如我想5分钟执行一次同步数据

当第一次开启捕获,相关的存储过程写好之后,

可以写一个脚本,专门进行同步,然后同步完后删除日志表的数据。

把这样的脚本放进sqlserver自带的作业计划里,设置执行间隔为5分钟。

同步脚本只需要在以上游标代码基础上再加上一段删除日志表数据即可,具体如下:

--写一个游标,进行最终的同步操作

use db1

 declare @oper INT

 declare @id INT

 declare @name VARCHAR(20)

 declare @addr VARCHAR(20)

 declare @ttime DATETIME

--定义一个游标

declare user_curcursor for select __$operation,id ,name,addr,ttime fromdb1.cdc.dbo_t_cdc_ta_CT 

--打开游标

open user_cur

while@@fetch_status=0

begin

--读取游标

    fetch next from user_cur into @oper,@id,@name,@addr,@ttime

       use monitor

       set identity_insert  t_cdc_ta on

       exec dbo.p_merge @oper,@id,@name,@addr,@ttime

  

end

close user_cur

deallocate user_cur

--删除日志表数据

use db1

delete from cdc.dbo_t_cdc_ta_CT

相关截图如下

Sqlserver代理里作业一栏右击新建作业,然后设置相关的一些内容。

在步骤一栏新建,然后打开sql脚本文件,会自动加载进去sql语句。

然后点击计划,新建一个计划,设置相关的时间间隔,执行频率情况。比如设置5分钟,那么就会自动5分钟执行一次脚本,先同步数据,再删除表数据。

备注补充:

一可能遇到的问题

1因为我设置sqlserver自带的那个cleanup功能时间频次啥的,5分钟让清空日志表数据一次,可是执行了好几遍,日志表始终无法清空数据,所以才在同步数据脚本里在每次执行好同步后跟一句清空日志表数据的sql语句,

实现人为的cleanup。

2因为在执行同步脚本时也是需要执行时间的,在这个过程中,目标表的捕获还在开启中,万一我同步的时候,目标表还在不断增删改,最后那个清空日志表的sql会不会把没有同步的数据记录也删除了,这里存在一个纰漏地方,暂时没想到更好的解决方法。

如果你有更好的想法解决这个问题,可以评论给我帮助。

二 CDC的一些存储过程和函数链接,链接页面里往下翻有相关内容。

免责声明:文章转载自《利用Sqlserver的CDC功能实现2张表的同步更新》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Oracle比较时间大小Axure无法签出,团队配合时无法导入项目下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Flink 如何实时分析 Iceberg 数据湖的 CDC 数据

简介: 数据湖的架构中,CDC 数据实时读写的方案和原理 本文由李劲松、胡争分享,社区志愿者杨伟海、李培殿整理。主要介绍在数据湖的架构中,CDC 数据实时读写的方案和原理。文章主要分为 4 个部分内容: 常见的 CDC 分析方案 为何选择 Flink + Iceberg 如何实时写入读取 未来规划 一、常见的 CDC 分析方案 我们先看一下今天的 to...

USB中CDC-ECM的了解和配置

USB中典型类及子类: 类别 解释 子类 典型应用 IC芯片 备注 UVC 视频类 免驱USB摄像头 CDC 通讯类 RNDIS ECM(p24) 免驱USB网卡 RTL8152B EEM ......         曾经接触过UVC。今天接触了CDC-ECM原理上是一样的,定义一套标准协议主从机都...

(转)USB中CDC-ECM的了解和配置

USB中典型类及子类: 类别 解释 子类 典型应用 IC芯片 备注 UVC 视频类 免驱USB摄像头 CDC 通讯类 RNDIS ECM(p24) 免驱USB网卡 RTL8152B EEM ......         以前接触过UVC,今天接触了CDC-ECM原理上是一样的,定义一套标准协议主从机都遵...

一个专门下载全球气象站数据的网站(包括中国700多个站)

我只是搬运工。。。 1.我也下载了,好像不能超过500M每次,100个站。下了也不会看。有没有高手能介绍下专门下载某个省的所有气象站气温资料的方法,从而计算出每个站每月的平均气温。。格式为txt。2 http://www.esrl.noaa.gov/psd/data/gridded/reanalysis/网站可以下载气象数据,.nc格式,同样不会用,不会打...

白乔原创:VC之美化界面篇

本文专题讨论VC中的界面美化,适用于具有中等VC水平的读者。读者最好具有以下VC基础: 1.大致了解MFC框架的基本运作原理; 2.熟悉Windows消息机制,熟悉MFC的消息映射和反射机制; 3.熟悉OOP理论和技术; 本文根据笔者多年的开发经验,并结合简单的例子一一展开,希望对读者有所帮助。 1. 美化界面之开题篇 相信使用过《金山毒霸》、...

CDC和HDC的区别与转换

CDC和HDC的区别与转换 - 陳さん様 - 博客园 http://www.cnblogs.com/cwbo-win/articles/3393891.html 1 CDC和HDC的区别与转换 2 3 4 一、区别与联系 5 HDC是句柄;CDC是MFC封装的Windows 设备相关的一个类;CClientDC是CDC的衍生类,产生...