Spring Boot多数据源配置实战:MySQL与PostgreSQL整合 1. 多数据源配置的必要性与应用场景在企业级应用开发中多数据源配置已经成为刚需。我经历过不少项目需要同时连接MySQL和PostgreSQL的场景比如历史数据迁移、跨数据库报表生成、异构数据库同步等。有些老系统使用MySQL存储业务数据而新模块可能采用PostgreSQL的特性如GIS支持、JSONB类型这就需要在同一个应用中操作两种数据库。去年我参与的一个电商项目就遇到这种情况订单中心用MySQL保证事务一致性商品搜索用PostgreSQL实现全文检索。通过多数据源配置我们成功在一个Spring Boot应用中实现了两种数据库的无缝操作。下面就把这套经过实战检验的方案分享给大家。2. 环境准备与基础配置2.1 依赖引入关键点首先在pom.xml中添加必要依赖。除了常规的spring-boot-starter-jdbc需要特别注意这两个核心依赖!-- MySQL连接驱动 -- dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId version8.0.28/version /dependency !-- PostgreSQL连接驱动 -- dependency groupIdorg.postgresql/groupId artifactIdpostgresql/artifactId version42.3.3/version /dependency重要提示驱动版本要与数据库服务器版本匹配。我曾遇到过PostgreSQL 14使用旧版驱动导致SSL连接失败的问题建议保持驱动版本与数据库大版本一致。2.2 配置文件的多数据源定义在application.yml中配置双数据源时建议采用明确的命名空间隔离spring: datasource: mysql: url: jdbc:mysql://localhost:3306/ruoyi?useSSLfalseserverTimezoneUTC username: root password: mysql123 driver-class-name: com.mysql.cj.jdbc.Driver postgresql: url: jdbc:postgresql://localhost:5432/ruoyi_pg username: postgres password: postgres123 driver-class-name: org.postgresql.Driver这种层级结构比用datasource.primary/secondary更直观后续在代码中引用时也更容易区分。3. 多数据源的核心实现逻辑3.1 数据源配置类编写创建两个独立的配置类分别管理各自的数据源。以下是MySQL配置类的关键代码Configuration MapperScan(basePackages com.ruoyi.mysql.mapper, sqlSessionTemplateRef mysqlSqlSessionTemplate) public class MysqlDataSourceConfig { Bean(name mysqlDataSource) ConfigurationProperties(prefix spring.datasource.mysql) public DataSource mysqlDataSource() { return DataSourceBuilder.create().build(); } Bean(name mysqlTransactionManager) public DataSourceTransactionManager mysqlTransactionManager( Qualifier(mysqlDataSource) DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } }PostgreSQL配置类结构类似主要区别在于basePackages指向不同的mapper包路径Bean名称使用pg前缀事务管理器独立配置3.2 动态数据源路由实现当需要在一个事务中操作多个数据库时需要自定义AbstractRoutingDataSourcepublic class DynamicDataSource extends AbstractRoutingDataSource { Override protected Object determineCurrentLookupKey() { return DataSourceContextHolder.getDataSourceType(); } }配套的上下文持有器public class DataSourceContextHolder { private static final ThreadLocalString contextHolder new ThreadLocal(); public static void setDataSourceType(String dsType) { contextHolder.set(dsType); } public static String getDataSourceType() { return contextHolder.get(); } public static void clearDataSourceType() { contextHolder.remove(); } }实战经验ThreadLocal一定要记得清除我在生产环境遇到过内存泄漏就是因为某个异常分支没有执行clear操作。4. 事务管理的特殊处理4.1 分布式事务的妥协方案真正的分布式事务如XA协议性能损耗大在大多数场景下我们可以采用最终一致性的折中方案。比如// 在MySQL操作的方法上 Transactional(transactionManager mysqlTransactionManager) public void updateOrder(Order order) { //... DataSourceContextHolder.setDataSourceType(postgresql); try { productMapper.updateStock(order.getProductId()); } finally { DataSourceContextHolder.clearDataSourceType(); } }这种写法虽然不能保证强一致性但通过合理的重试机制和补偿逻辑在大多数业务场景下已经足够。4.2 事务传播的坑点记录在多数据源环境下事务传播行为需要特别注意不要跨数据源使用REQUIRES_NEWPROPAGATION_NESTED只对支持保存点的数据源有效建议在方法入口处就明确设置数据源避免中途切换5. 实际应用中的优化技巧5.1 连接池参数调优不同数据库的连接池配置应该区别对待spring: datasource: mysql: hikari: maximum-pool-size: 20 connection-timeout: 30000 postgresql: hikari: maximum-pool-size: 15 connection-timeout: 40000PostgreSQL通常需要更小的连接池因为它的连接创建成本更高。我在压力测试中发现PG连接数超过15后性能反而下降。5.2 监控与健康检查建议为每个数据源单独配置健康检查Bean public HealthIndicator mysqlHealth() { return new DataSourceHealthIndicator(mysqlDataSource()); } Bean public HealthIndicator pgHealth() { return new DataSourceHealthIndicator(postgresqlDataSource()); }这样在/actuator/health端点可以看到每个数据源的状态便于快速定位问题。6. 常见问题排查手册6.1 连接失败类问题症状启动时报Failed to obtain JDBC Connection排查步骤检查URL中的IP、端口、数据库名验证用户名密码特别是PostgreSQL的密码可能包含特殊字符查看数据库服务器的连接限制测试telnet端口连通性6.2 事务不生效问题症状跨数据源操作没有回滚解决方案确认每个数据源有独立的事务管理器检查Transactional注解指定了正确的事务管理器避免在private方法上使用Transactional6.3 性能问题症状查询响应慢特别是跨库关联查询优化建议尽量减少同一次请求中的跨库操作对频繁访问的跨库数据建立本地缓存考虑使用数据库链接如PostgreSQL的FDW替代应用层关联7. 扩展思考何时需要多数据源虽然技术可以实现多数据源但架构上还是要慎重考虑。根据我的经验以下场景适合采用多数据源方案渐进式迁移从MySQL逐步迁移到PostgreSQL的过渡期特殊功能需求如需要PostgreSQL的GIS、全文检索等特性报表分离OLTP和OLAP使用不同数据库引擎而不建议的情况包括简单的数据分片应该用ShardingSphere等中间件没有实际业务价值的技术炫技团队缺乏多数据库运维能力时这套方案在若依框架中经过充分验证实际上可以推广到任何Spring Boot项目。关键是要理解每个配置背后的原理而不是简单复制粘贴。我在GitHub上准备了一个可运行的示例项目包含文中所有配置的完整实现需要的朋友可以私信获取。