C# 通过windows服务同步MySQL和MSSQL数据库

C# 通过windows服务同步MySQL和MSSQL数据库,c#,mysql,sql,sql-server,windows-services,C#,Mysql,Sql,Sql Server,Windows Services,我必须同步两个数据库的两个表,其中一个是MSSQL,另一个是MySQL。我必须通过Windows服务来完成这项工作。我目前已经创建了一个Windows服务,我目前添加到该服务中的是:从MySQL数据库获取数据,并将其插入数据适配器,我计划使用插入式事务将数据移动到MSSQL数据库。您能否告诉我解决此问题的最佳方法,以及我现在所做的是否正确,我第一次这样做。如果您将mySql数据库添加为链接服务器(sp_addlinkedserver),那么我认为您可以在MS SQL数据库的存储过程中执行以下操作

我必须同步两个数据库的两个表,其中一个是MSSQL,另一个是MySQL。我必须通过Windows服务来完成这项工作。我目前已经创建了一个Windows服务,我目前添加到该服务中的是:从MySQL数据库获取数据,并将其插入数据适配器,我计划使用插入式事务将数据移动到MSSQL数据库。您能否告诉我解决此问题的最佳方法,以及我现在所做的是否正确,我第一次这样做。

如果您将mySql数据库添加为链接服务器(sp_addlinkedserver),那么我认为您可以在MS SQL数据库的存储过程中执行以下操作:

 insert table1(col1) 
 select col1 
 from openquery('MySqlLinkedDb','select col1 from mySqlDb.dbo.table2')

也许有两种方法可以解决这个问题。您并没有提到表的数量和大小,以及所需的同步频率,所以我的答案可能不是100%相关。无论如何,我的建议是:

  • 每个表都应该有额外的列-SyncDate(TIMESTAMP),默认为空
  • 在Windows服务中实现的同步逻辑通过执行如下查询定期检查每个表是否有一些数据要同步(出于性能原因,请使用纯IDataReader):

    从SyncDate为空的TEST_表中选择*

  • 如果上述语句返回数据,则:

    • 收集要插入的行包(例如500行)
    • 在目标数据库上开始事务,并为收集的包执行insert语句(将列SyncDate的值设置为DateTime.Now)
    • 当insert完成时,在源数据库中执行如下语句:
    更新TEST_TABLE SET SyncDate=@DateTime.Now where ID_PRIMARY_KEY IN(来自包的标识)

    • 提交事务
    • 收集另一个包并重复算法,直到DataReader提供数据
  • 上述算法应应用于两个数据库

  • 可能您的数据库有外键,所以您必须记住从属表应该按照有效的顺序同步
  • 只要有可能,您都可以从多线程中获益

  • 如果您必须通过Windows服务执行此操作,我很好奇您是如何从MySQL接收数据的?启动对服务的调用的是什么?传递的数据是什么形式?您是在进行更改还是在刷新数据

    例如,如果您收到一个DataTable或其他类型的IEnumerable,并且它是一个完整的刷新,那么您可以使用SqlBulkCopy.WriteToServer()。这将是最快和最有效的


    Tom

    对于这类工作,SQL Server集成服务是一条出路

    SSI用于提取、转换和加载数据。(ETL过程)

    通过数据的每个转换步骤(从MySQL到MSSQL)设计工作流

    然后创建一个作业并配置它的计划,它将由SQL Server执行


    无需从头开始开发难以维护的内容。

    如果您已经准备好将MySQL数据移动到SQL。我建议您将它们放在一个单独的表中,并发出Merge命令来合并数据。请确保标记回已更新的数据,以便现在可以将其取回并推送到MySQL:

    MERGE TableFromMySQL AS TARGET USING TableFromSQL AS SOURCE
        ON (TARGET.PrimaryKey = SOURCE.PrimaryKey)
             WHEN Matched AND (TARGET.Field1 <> SOURCE.Field1
                OR TARGET.Field2 <> SOURCE.Field2
                OR .. put more field comparison here that you want to sync
             THEN
                UPDATE
                SET TARGET.Field1 = SOURCE.Field1,
                    TARGET.Field2 = SOURCE.Field2,
                    //flag the target field as updated
                    TARGET.IsUpdated = 1,
                    TARGET.LastUpdatedOn = GETDATE()
                WHEN Not Matched 
                THEN
        INSERT(PrimaryKey, Field1, Field2, IsUpdated, LastUpdatedOn)
        VALUES(SOURCE.PrimaryKey, SOURCE.Field1, SOURCE.Field2, 1, GETDATE());
    
    使用TableFromSQL作为源将TableFromMySQL合并为目标
    打开(TARGET.PrimaryKey=SOURCE.PrimaryKey)
    匹配和时(TARGET.Field1 SOURCE.Field1
    或TARGET.Field2 SOURCE.Field2
    或者..在此处放置更多要同步的字段比较
    然后
    更新
    设置TARGET.Field1=SOURCE.Field1,
    TARGET.Field2=SOURCE.Field2,
    //将目标字段标记为已更新
    TARGET.IsUpdated=1,
    TARGET.lastUpdateOn=GETDATE()
    当不匹配时
    然后
    插入(PrimaryKey、字段1、字段2、IsUpdate、LastUpdateOn)
    值(SOURCE.PrimaryKey、SOURCE.Field1、SOURCE.Field2、1、GETDATE());
    

    现在,您可以使用IsUpdated=1查询MySQL表,并将所有值推送到MySQL数据库。我希望这会有所帮助。

    如果您不通过C#添加链接服务器,您可以通过Sql server Management Studio添加链接服务器。请检查:。链接服务器名称等同于上面的MySqlLinkedDb。添加后,您可以查看服务列表rs通过select*从sys.servers链接。我正在寻找一个使用Microsoft Sync Framework的解决方案。也许你对它有一些经验?你是否尝试过使用SSI将MySQL等异构数据库同步到MSSQL?这可能会完成你的工作。不过有一点。两个数据库中的表应该在代码中进行比较否则将插入我们不需要的重复记录。也许你可以解释一下这一部分?冗余有时并没有那么糟糕,但当然它取决于业务模型,通常最好避免它。为此,我看不到任何其他方法,除了通过执行查询和where子句havin来比较记录g表中的所有列听起来并不完美。更聪明的方法是添加列RecordHash,该列RecordHash包含插入期间根据除SyncDate和主键Id之外的所有其他列的值生成的唯一标识符。在插入数据之前,具有这种结构的目标表您必须执行查询,该查询检查哪一个数据这些都是新的。