MyBatis-Plus多数据源配置实战与优化
发布时间:2026/9/14 18:11:23 作者:尧图编辑部 阅读量:1,286

1. 多数据源配置的核心价值与应用场景在真实的企业级应用开发中单数据源往往难以满足复杂的业务需求。我经历过多个需要同时对接Oracle财务库和MySQL业务库的项目也处理过读写分离场景下的数据一致性问题。MyBatis-Plus的多数据源方案之所以备受青睐关键在于它解决了以下痛点混合业务系统整合当需要同时访问遗留系统的SQL Server和新业务的PostgreSQL时读写分离架构主库写从库读的场景下如何避免手动切换数据源分库分表扩展水平拆分的数据库实例需要统一管理多租户SaaS系统每个租户独立数据库实例的情况特别注意多数据源与分布式事务是两个不同维度的问题。本文方案适用于非跨库事务或能接受最终一致性的场景如需强一致性需结合Seata等方案2. 技术选型与方案对比2.1 主流多数据源实现方式在Spring生态中实现多数据源主要有三种技术路线方案优点缺点适用场景AbstractRoutingDataSource轻量级Spring原生支持需自行处理事务管理简单读写分离MyBatis-Plus多数据源开箱即用功能完善学习曲线略高企业级复杂场景JPAHibernateORM层统一性能损耗较大全JPA技术栈2.2 MyBatis-Plus方案核心优势动态数据源切换通过DS注解实现方法级别的数据源路由连接池智能管理集成HikariCP、Druid等主流连接池事务边界控制提供DSTransactional注解处理跨库事务敏感信息加密支持数据库密码ENC()加密存储3. 完整实现步骤详解3.1 环境准备与依赖配置!-- pom.xml关键依赖 -- dependency groupIdcom.baomidou/groupId artifactIddynamic-datasource-spring-boot-starter/artifactId version3.5.2/version /dependency dependency groupIdcom.alibaba/groupId artifactIddruid-spring-boot-starter/artifactId version1.2.8/version /dependency3.2 多数据源配置模板# application.yml标准配置 spring: datasource: dynamic: primary: master # 设置默认数据源 strict: false # 是否严格匹配数据源 datasource: master: url: jdbc:mysql://127.0.0.1:3306/master?useSSLfalse username: root password: ENC(密文) # 使用jasypt加密 driver-class-name: com.mysql.cj.jdbc.Driver type: com.alibaba.druid.pool.DruidDataSource slave_1: url: jdbc:mysql://127.0.0.1:3306/slave1?useSSLfalse username: slave_user password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver3.3 核心功能实现3.3.1 基础数据源切换Service public class OrderServiceImpl implements OrderService { DS(master) // 默认数据源可不写 public void createOrder(Order order) { // 主库写操作 } DS(slave_1) public Order getOrderById(Long id) { // 从库读操作 } }3.3.2 动态数据源进阶用法// 基于参数动态切换 public class DataSourceSelector { public static String determineDataSource(String tenantId) { return tenant_ tenantId; } } DS(#header.tenant) GetMapping(/data) public ListObject getData(RequestHeader String tenant) { // 根据header自动路由 }4. 生产环境注意事项4.1 连接池配置优化master: initial-size: 5 max-active: 20 min-idle: 5 max-wait: 60000 validation-query: SELECT 1 FROM DUAL test-while-idle: true关键参数建议每个数据源的max-active总和不应超过数据库最大连接数不同业务场景应设置不同的连接池隔离级别4.2 事务管理要点本地事务在方法内切换数据源时需添加Transactional(propagation Propagation.NOT_SUPPORTED)跨库事务使用DSTransactional注解基于XA协议DSTransactional public void crossDatabaseOperation() { // 操作master数据源 masterMapper.update(...); // 操作slave数据源 slaveMapper.insert(...); }5. 性能调优实战技巧5.1 监控指标采集Bean public ServletRegistrationBeanStatViewServlet druidServlet() { ServletRegistrationBeanStatViewServlet reg new ServletRegistrationBean(); reg.setServlet(new StatViewServlet()); reg.addUrlMappings(/druid/*); return reg; }5.2 常见问题排查问题1出现Could not open JDBC Connection异常检查项数据库连接数是否耗尽网络策略是否开通密码加密情况下是否配置了jasypt解密器问题2DS注解不生效排查路径确保方法是被Spring代理的非private/final方法检查是否在同一个类中自调用确认依赖版本无冲突6. 扩展应用场景6.1 多租户实现方案public class TenantDataSourceSelector { public static String currentTenant() { return TenantContext.getCurrentTenant(); } } DS(#tenantDataSourceSelector.currentTenant()) public class TenantService { // 业务方法 }6.2 读写分离自动路由Aspect Component public class ReadOnlyAspect { Around(annotation(readOnly)) public Object around(ProceedingJoinPoint pjp, ReadOnly readOnly) throws Throwable { DynamicDataSourceContextHolder.push(slave); try { return pjp.proceed(); } finally { DynamicDataSourceContextHolder.poll(); } } }在实际项目落地时建议先在小规模非核心业务验证稳定性。我曾在一个电商项目中通过这套方案将订单查询性能提升了3倍同时保证了写操作的可靠性。关键是要做好连接池监控和故障转移方案当某个数据源不可用时能自动降级。