CoreSync多版本数据库同步

1.简介

CoreSync是一个用于数据库间双向数据同步的.NET库。它支持SQLite、SQL Server和PostgreSQL,使您能够保持多个数据库实例的同步——无论它们是在同一台机器上,还是通过HTTP进行通信。github地址:https://github.com/davidortinau/CoreSync

核心功能

任何受支持的数据库组合之间均可实现双向同步(例如,SQLite ↔ SQL Server、PostgreSQL ↔ SQLite 等)
自动变更跟踪——通过基于版本的锚点检测插入、更新和删除操作
冲突解决 — 内置策略(跳过或强制写入),可针对每个项目进行自定义
过滤同步 — 使用参数化查询同步数据子集
HTTP传输 — 通过网络与ASP.NET Core服务器端点同步,并使用具有Polly重试功能和MessagePack二进制格式的弹性HTTP客户端
多种提供程序:SQLite、SQL Server(自定义变更跟踪)、SQL Server CT(原生变更跟踪)、PostgreSQL

运行机制

CoreSync采用基于版本的变更跟踪方法:
每个数据库都会获得一个唯一的Store ID (GUID)
当你调用ApplyProvisionAsync()时,CoreSync会创建内部跟踪表来监控插入、更新和删除操作
SyncAgent负责协调同步过程:它从一个提供者那里获取更改,并将其应用到另一个提供者,反之亦然
每一方都会保存另一存储的最后已知版本,因此下一次同步只会传输已更改的内容

image

 

2.项目接入

 1.nuget搜索并安装

image

2.从github下载源码,编译后引入项目

CoreSync支持.NET Standard 2.0(与.NET Framework 4.6.1+和.NET Core 2.0+兼容),我当时项目使用的.NET4.6.1会安装不上,升到4.7.2就能正常安装和使用了

3.基础示例(双向数据同步)

1.建立追踪表

        static async Task ApplyProvision()
        {
            try
            {
                var configA = new SqlSyncConfigurationBuilder("Data Source=172.16.3.45,1433; Initial Catalog=SyncDataTestA; Connection Timeout=8000; User ID=sa; Password=123!#%A; TrustServerCertificate=true; Encrypt=true;")
                .Table("Sys_User")
                .Table("Sys_Role")
                .Table("Sys_UserRole")
                .Build();

                var configB = new SqlSyncConfigurationBuilder("Data Source=172.16.3.180,1433; Initial Catalog=SyncDataTestB; Connection Timeout=8000; User ID=sa; Password=123!#%A; TrustServerCertificate=true; Encrypt=true;")
                    .Table("Sys_User")
                    .Table("Sys_Role")
                    .Table("Sys_UserRole")
                    .Build();
                var providerA = new SqlSyncProvider(configA);
                var providerB = new SqlSyncProvider(configB);//// 初始化追踪表
                await providerA.ApplyProvisionAsync();
                await providerB.ApplyProvisionAsync();

                Console.WriteLine($"初始化同步环境完成");
            }
            catch (Exception ex)
            {
                throw;
            }

        }

这步操作不用每次都执行,项目初始化时执行一次,分析源码就能发现这步操作就是在两个数据库中添加相关的表来记录相关的变更,同时也会在指定同步的表上建立触发器,效果如下所示

imageimage

 框架创建的表不要手动删除,不然新增或修改数据时会导致触发器逻辑执行失败,影响正常数据的插入或修改

 2.数据同步

static async Task RunAsync()
        {
            try
            {
                Console.WriteLine($"B<--->A同步开始");

                var configA = new SqlSyncConfigurationBuilder("Data Source=172.16.3.45,1433; Initial Catalog=SyncDataTestA; Connection Timeout=8000; User ID=sa; Password=123!#%A; TrustServerCertificate=true; Encrypt=true;")
                .Table("Sys_User")
                .Table("Sys_Role")
                .Table("Sys_UserRole")
                .Build();

                var configB = new SqlSyncConfigurationBuilder("Data Source=172.16.3.180,1433; Initial Catalog=SyncDataTestB; Connection Timeout=8000; User ID=sa; Password=123!#%A; TrustServerCertificate=true; Encrypt=true;")
                    .Table("Sys_User")
                    .Table("Sys_Role")
                    .Table("Sys_UserRole")
                    .Build();

                var providerA = new SqlSyncProvider(configA);
                var providerB = new SqlSyncProvider(configB);

                // 第一次同步(建立基线)
                var syncAgentBA = new SyncAgent(providerA, providerB);
                await syncAgentBA.SynchronizeAsync(conflictResolutionOnLocalStore: ConflictResolution.ForceWrite);
                Console.WriteLine($"B<--->A同步完成");
            }
            catch (Exception ex)
            {
                throw;
            }

        }

执行上边的代码,就能将对应的表进行双向数据同步了,最终的效果就是将A库的数据同步到B库,B库的数据同步到A库实现数据的双向同步,其中可以通过ConflictResolution.ForceWrite参数进行强制覆盖也可以通过ConflictResolution.Skip忽略冲突

 3.移除追踪表

 static async Task RemoveProvision()
        {
            try
            {
                var configA = new SqlSyncConfigurationBuilder("Data Source=172.16.3.45,1433; Initial Catalog=SyncDataTestA; Connection Timeout=8000; User ID=sa; Password=123!#%A; TrustServerCertificate=true; Encrypt=true;")
                .Table("Sys_User")
                .Table("Sys_Role")
                .Table("Sys_UserRole")
                .Build();

                var configB = new SqlSyncConfigurationBuilder("Data Source=172.16.3.180,1433; Initial Catalog=SyncDataTestB; Connection Timeout=8000; User ID=sa; Password=123!#%A; TrustServerCertificate=true; Encrypt=true;")
                    .Table("Sys_User")
                    .Table("Sys_Role")
                    .Table("Sys_UserRole")
                    .Build();

         
var providerA = new SqlSyncProvider(configA); var providerB = new SqlSyncProvider(configB);

          await providerA.RemoveProvisionAsync(); await providerB.RemoveProvisionAsync(); Console.WriteLine($"卸载同步环境完成"); } catch (Exception ex) { throw; } }

执行上边的方法就会移除追踪相关的表和对应表上的触发器

4.进阶示例(单向数据同步)

github文档上提供的示例是双向同步的,那能否进行单项同步及支持特殊策略呢,通过分析源码,可以发现是可以这么操作的,具体示例如下

 
static async Task RunAsyncBToA()
        {
            try
            {
                Console.WriteLine($"B--->A同步开始");

                var configA = new SqlSyncConfigurationBuilder("Data Source=172.16.3.45,1433; Initial Catalog=SyncDataTestA; Connection Timeout=8000; User ID=sa; Password=123!#%A; TrustServerCertificate=true; Encrypt=true;")
                .Table("Sys_User", SyncDirection.DownloadOnly)
                .Table("Sys_Role", SyncDirection.DownloadOnly)
                .Table("Sys_UserRole", SyncDirection.DownloadOnly)
                .Build();

                var configB = new SqlSyncConfigurationBuilder("Data Source=172.16.3.180,1433; Initial Catalog=SyncDataTestB; Connection Timeout=8000; User ID=sa; Password=123!#%A; TrustServerCertificate=true; Encrypt=true;")
                    .Table("Sys_User")
                    .Table("Sys_Role")
                    .Table("Sys_UserRole")
                    .Build();

                var providerA = new SqlSyncProvider(configA,ProviderMode.Local);
                var providerB = new SqlSyncProvider(configB,ProviderMode.Remote);

                // 第一次同步(建立基线)
                var syncAgentBA = new SyncAgent(providerA, providerB);
                await syncAgentBA.SynchronizeAsync(conflictResolutionOnLocalStore: ConflictResolution.ForceWrite);
                Console.WriteLine($"B--->A同步完成");
            }
            catch (Exception ex)
            {
                throw;
            }

        }

实现单项同步有两个关键点,SqlSyncProvider(configA,ProviderMode.Local); 定义provider为Local或Remote,Table("Sys_User", SyncDirection.DownloadOnly)同时在绑定Table上DownloadOnly,这样这张表只会下载更新的内容,自身的变更不进行上传,这样就实现了数据的单项同步

 
 
posted @ 2026-08-14 11:02  hello-*-world  阅读(2)  评论(0)    收藏  举报