ef core 本身不内置读写分离支持,但可通过多上下文、dbcontext工厂或拦截器实现:写操作走主库,读操作走从库;需规避复制延迟、跨库事务、连接复用等陷阱,关键在识别强一致性场景。

EF Core 本身不内置读写分离支持,但可以通过多上下文、自定义 DbContext 工厂或拦截器等方式灵活实现。核心思路是:写操作走主库(Master),读操作走从库(Slave),并由应用层或基础设施层控制路由逻辑。
使用多个 DbContext 类区分读写
最直接的方式是定义两个 DbContext 子类,分别配置主库和从库连接字符串:
- WriteDbContext:只用于增删改(SaveChanges/SaveChangesAsync)和必要强一致性查询
- ReadDbContext:只用于查询(ToList/FirstOrDefault 等),连接从库
在 DI 容器中注册时,可分别注入不同生命周期(如 Scoped)并确保事务边界清晰。注意:不能在同一个事务中混用两个上下文,否则会破坏一致性。
通过 DbContextFactory + 路由策略动态切换
借助 IDbContextFactory
- 写操作(Insert/Update/Delete)→ 返回主库上下文实例
- 读操作(以 AsNoTracking() 或只读标记为特征)→ 返回从库上下文实例
- 可结合 AsyncLocal
或 CallContext 标记当前是否处于写上下文作用域
这种方式更轻量,避免硬编码两个上下文类,适合中大型项目统一管控数据源路由。
利用 EF Core 7+ 的 ExecuteSqlInterception 拦截 SQL 类型
EF Core 7 引入了更完善的拦截机制,可通过实现 ICommandInterceptor 分析 SqlCommand 的 CommandText:
- 检测是否为 SELECT 语句(且非 FOR UPDATE、非子查询含写意图)→ 自动路由到从库连接
- 其他命令(INSERT/UPDATE/DELETE/EXEC)→ 强制使用主库连接
- 需配合连接池管理,防止跨库连接复用导致异常
该方式对业务代码透明,但调试和排查较复杂,建议搭配日志输出实际路由结果用于验证。
注意事项与常见陷阱
读写分离不是“一配就灵”,必须考虑实际场景约束:
- 从库存在复制延迟,刚写入的数据可能立即查不到 → 敏感查询(如登录后跳转页)应强制走主库
- 事务内所有操作必须在同一数据库,跨库事务不可行 → 避免在 TransactionScope 中调用读从库的 DbContext
- 连接字符串、超时、重试策略需按主/从特性差异化配置(例如从库可设更长 CommandTimeout)
- 健康检查应分别探测主从库连通性,避免单点故障导致全站只读或只写失败
基本上就这些。关键不在“怎么切”,而在于“什么时候不该切”——合理识别强一致性需求,比技术实现更重要。










