源本科技 | 码上会

多数据源支持

2026/04/03
2
0

引言

在分布式、微服务、读写分离等场景中,单一数据源已无法满足企业级开发需求。MyBatis-Plus 官方提供了两套完善的多数据源 / 动态数据源解决方案,分别适配开源社区企业级商用场景,可轻松实现一主多从、多库切换、动态数据源管理等功能。


核心概念

  • 多数据源:项目中同时配置多个固定数据源,手动指定使用某一个。

  • 动态数据源:支持运行时动态添加、删除、切换数据源,无需重启服务。

  • 数据源分组:将多个从库归为一组,实现负载均衡或故障转移。

  • 读写分离:写操作走主库,读操作走从库,提升数据库性能。


dynamic-datasource

dynamic-datasource-spring-boot-starter 是 MyBatis-Plus 生态下最流行、零门槛、生产级的开源多数据源组件,支持 Spring Boot 2/3,无侵入、高兼容、易扩展。

核心特性

  • 数据源分组:支持主从、读写分离、多租户、一主多从、多主多从

  • 敏感配置加密:支持数据库账号密码 ENC() 加密,防止配置泄露

  • 独立初始化:每个数据源可独立执行 SQL 初始化表结构

  • 注解驱动@DS 极简切换,支持类 / 方法 / 接口多级注解

  • 连接池兼容:原生支持 HikariCP、Druid、DBCP2 等

  • 框架兼容:完美适配 MyBatis-Plus、MyBatis、JdbcTemplate、JPA

  • 动态增减:运行时动态添加 / 移除数据源,无需重启

  • 分布式事务:集成 Seata 实现分布式事务

  • 高约定配置:自动识别下划线分组,简化配置

核心约定

  1. 默认主数据源名称:master,可修改

  2. 数据源名称以下划线 _ 区分分组,如 slave_1slave_2 属于 slave

  3. 注解优先级:方法上 > 类上 > 全局默认

  4. 严格模式 strict:关闭时,找不到指定数据源自动使用主库

使用步骤

引入依赖

Spring Boot 3

<dependency>
 <groupId>com.baomidou</groupId>
 <artifactId>dynamic-datasource-spring-boot3-starter</artifactId>
 <version>${version}</version>
</dependency>

YAML 配置

一主两从示例

spring:
  datasource:
    dynamic:
      primary: master  # 默认主数据源
      strict: false    # 关闭严格模式,找不到数据源则走默认
      datasource:
        # 主库(写入)
        master:
          url: jdbc:mysql://127.0.0.1:3306/db_master?useSSL=false
          username: root
          password: root
          driver-class-name: com.mysql.cj.jdbc.Driver
        # 从库 1
        slave_1:
          url: jdbc:mysql://127.0.0.1:3307/db_slave?useSSL=false
          username: root
          password: root
          driver-class-name: com.mysql.cj.jdbc.Driver
        # 从库 2(加密配置示例)
        slave_2:
          url: ENC(xxx)
          username: ENC(xxx)
          password: ENC(xxx)
          driver-class-name: com.mysql.cj.jdbc.Driver

3切换数据源

  • 不加注解:默认使用主库 master

  • 类上注解:整个类使用指定数据源

  • 方法上注解:覆盖类上注解

@Service
@DS("slave") // 类级别:默认使用 slave 组
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    // 查询走从库
    @Override
    public List<User> list() {
        return userMapper.selectList(null);
    }

    // 方法级别:强制指定 slave_1
    @Override
    @DS("slave_1")
    public User getById(Long id) {
        return userMapper.selectById(id);
    }

    // 无注解:默认 master(写入操作)
    @Override
    public boolean save(User user) {
        return userMapper.insert(user) > 0;
    }
}

适用场景

  • 读写分离

  • 多业务库切换

  • 微服务多租户

  • 主从架构

  • 测试库 / 正式库切换