FreeSql icon indicating copy to clipboard operation
FreeSql copied to clipboard

是否支持主从使用不同类型的数据库库

Open DrZhong opened this issue 3 years ago • 5 comments

Feature 特性

主从使用不同类型的数据库

简要描述原因

在做单机程序的时候,主数据库存储在本地的sqllite里,从数据库存在在服务器的sqlserver上

使用场景

在做单机程序的时候,我们允许用户在离线(无网络)的情况下进行数据存储在本地,但是检测到用户联网的时候。我们希望把数据同步存储一份在服务器的 sqlserver上,为了简化安装,我们会单本地采用sqllite存储,远程使用sqlserver存储。

DrZhong avatar Jul 01 '22 06:07 DrZhong

master slave 模式并不是ORM实现的,FreeSql只是写主,读从。中间的同步状态,是各自数据库特性自行实现。 比如MySql,参考 如下内容 1.master 写入binlog ,slave 启动 I/O thread连接到Master数据,判断变化的binlog 2.Slave I/O线程获取到的二进制日志会保存到自己的Relay log 3.Slave 有一个SQL线程会定时检查Relay log是否发生变化,若是变化就更新

https://zhuanlan.zhihu.com/p/335142300 image

Sql Server 有一个Always on ,具体自行查询资料

luoyunchong avatar Jul 01 '22 07:07 luoyunchong

主库 sqlserver 从库 sqlite

目前因为是在最后执行SQL的时候才选择目标,若此时生成的 SQL 是 sqlserver 语法,是不能在 sqlite 上执行的。

假如支持该模式,应该在生成 SQL 之前就选择可用的目标,再针对性的做 SQL 转化翻译工作。

2881099 avatar Jul 01 '22 07:07 2881099

master slave 模式并不是ORM实现的,FreeSql只是写主,读从。中间的同步状态,是各自数据库特性自行实现。 比如MySql,参考 如下内容 1.master 写入binlog ,slave 启动 I/O thread连接到Master数据,判断变化的binlog 2.Slave I/O线程获取到的二进制日志会保存到自己的Relay log 3.Slave 有一个SQL线程会定时检查Relay log是否发生变化,若是变化就更新

https://zhuanlan.zhihu.com/p/335142300 image

Sql Server 有一个Always on ,具体自行查询资料

所以freesql仅仅是实现是数据库自带的主从,并没有实现一套自己的主从存储是吧?

DrZhong avatar Jul 01 '22 07:07 DrZhong

其实 IFreeSql 定义够简单了,实现你想要的也不难。

class MasterSlaveFreeSql : BaseDbProvider, IFreeSql
{
    IFreeSql _master;
    IFreeSql[] _slaves;
    public MasterSlaveFreeSql(IFreeSql master, IFreeSql[] _slaves)
    {
        _master = master;
        _slaves = _slaves;

        this.InternalCommonUtils = GetMaster().InternalCommonUtils;
        this.InternalCommonExpression = GetMaster().InternalCommonExpression;

        this.Ado = GetMaster().Ado;
        this.Aop = GetMaster().Aop;

        this.DbFirst = GetMaster().DbFirst;
        this.CodeFirst = GetMaster().CodeFirst;
    }
    ~MasterSlaveFreeSql() => this.Dispose();
    int _disposeCounter;
    public override void Dispose()
    {
        if (Interlocked.Increment(ref _disposeCounter) != 1) return;
        foreach (var slave in _slaves)
        {
            try
            {
                (slave.Ado as AdoProvider)?.Dispose();
            }
            catch { }
        }
        (_master?.Ado as AdoProvider)?.Dispose();
    }

    BaseDbProvider GetMaster()
    {
        return _master as BaseDbProvider;
    }
    BaseDbProvider GetSlave()
    {
        return _slaves.Where(a => a.Ado.MasterPool.IsAvailable).First() as BaseDbProvider;
    }

    public override ISelect<T1> CreateSelectProvider<T1>(object dywhere) => GetSlave().CreateSelectProvider<T1>(dywhere);
    public override IInsert<T1> CreateInsertProvider<T1>() => GetMaster().CreateInsertProvider<T1>();
    public override IUpdate<T1> CreateUpdateProvider<T1>(object dywhere) => GetMaster().CreateUpdateProvider<T1>(dywhere);
    public override IDelete<T1> CreateDeleteProvider<T1>(object dywhere) => GetMaster().CreateDeleteProvider<T1>(dywhere);
    public override IInsertOrUpdate<T1> CreateInsertOrUpdateProvider<T1>() => GetMaster().CreateInsertOrUpdateProvider<T1>();
}

2881099 avatar Jul 01 '22 07:07 2881099

对,ORM 并不关注具体数据是如何同步的。

luoyunchong avatar Jul 01 '22 09:07 luoyunchong