Spring Boot 多数据源切换核心是构建可路由、可切换、事务可控的运行时机制,推荐使用 dynamic-datasource-spring-boot-starter;需配置主从数据源、通过@DS注解按方法粒度切换,避免跨库事务,支持动态新增数据源。

Spring Boot 配置多数据源切换,核心不是“配多个 DataSource Bean”,而是建立一套可路由、可切换、事务可控的运行时机制。直接硬写两个 DataSource 并用 @Qualifier 注入,短期能跑通,但很快会在事务、分页、MyBatis 映射、连接池管理上出问题。
用 dynamic-datasource-spring-boot-starter 快速落地
这是当前 Spring Boot 生态中最成熟、侵入性最低的方案,官方支持主流连接池(HikariCP、Druid)、MyBatis/MyBatis-Plus、JPA,且天然兼容事务。
- 添加依赖(Maven):
<dependency><br> <groupId>com.baomidou</groupId><br> <artifactId>dynamic-datasource-spring-boot-starter</artifactId><br> <version>4.4.0</version><br></dependency>
- 在
application.yml中声明多个数据源,明确指定主数据源:spring:<br> datasource:<br> dynamic:<br> primary: master<br> datasource:<br> master:<br> url: jdbc:mysql://localhost:3306/main<br> username: root<br> password: 123456<br> driver-class-name: com.mysql.cj.jdbc.Driver<br> slave_1:<br> url: jdbc:mysql://localhost:3306/replica<br> username: repl<br> password: repl123<br> driver-class-name: com.mysql.cj.jdbc.Driver
- 无需额外配置事务管理器或 SqlSessionFactory —— starter 自动完成适配
按方法粒度切换数据源(注解驱动)
业务代码里不需要感知底层是哪个库,只需在需要切换的方法上加注解即可,完全无侵入。
- 读操作走从库:
@DS("slave_1")<br>public List<Order> listOrders() { ... } - 写操作强制走主库:
@DS("master")<br>@Transactional<br>public void createOrder(Order order) { ... } - 支持嵌套切换(比如 Service 方法 A 切到 slave_1,内部调用的方法 B 再切回 master),靠 ThreadLocal + Deque 实现安全嵌套
跨库事务必须谨慎处理
Spring 原生 @Transactional 只绑定单个 DataSourceTransactionManager,无法跨库生效。这不是配置问题,而是分布式事务范畴。
- 如果一个方法里同时操作
master和slave_1,不要指望单个@Transactional能回滚两边 —— 它只会管理当前线程绑定的那个数据源 - 真实需求中,应尽量避免“同事务内跨库写”;若必须,需引入 Seata、XA 或业务层补偿机制
- 读写分离场景下,
@DS("slave_1")的方法本身就不该带@Transactional(除非只读事务有特殊要求)
动态新增数据源(运行时不重启)
适用于租户隔离、数据中台等场景,可通过 API 在服务运行中注册新数据源。
- 调用
DynamicDataSourceContextHolder.addDataSource("tenant_001", dataSource)即可注入 - 后续用
@DS("tenant_001")就能立即使用,连接池、健康检查、销毁逻辑均由 starter 管理 - 注意:动态添加的数据源不会自动写入配置中心,如需持久化,需自行对接 Nacos/Apollo


















