1. 多数据源配置背景与核心需求
在实际企业级应用开发中,我们经常需要同时连接多个数据库。比如你可能需要同时操作Oracle和达梦(DM)数据库,或者需要读写分离配置主从数据库。MyBatis-Plus作为MyBatis的增强工具,配合Druid连接池,可以很好地满足这种多数据源需求。
为什么选择这种方案?首先,MyBatis-Plus的多数据源支持非常成熟,其次Druid作为阿里巴巴开源的数据库连接池,不仅性能优异,还提供了强大的监控和SQL过滤功能。这种组合在实际项目中已经过大量验证,稳定性有保障。
2. 基础环境准备与依赖配置
2.1 必要依赖引入
首先需要在pom.xml中添加必要的依赖:
xml复制<!-- MyBatis-Plus 多数据源支持 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>3.5.2</version>
</dependency>
<!-- Druid 连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.8</version>
</dependency>
<!-- 数据库驱动 -->
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc8</artifactId>
<version>21.5.0.0</version>
</dependency>
<dependency>
<groupId>com.dameng</groupId>
<artifactId>DmJdbcDriver</artifactId>
<version>8.1.1.193</version>
</dependency>
2.2 基础配置解析
在application.yml中配置多数据源时,有几个关键点需要注意:
yaml复制spring:
datasource:
dynamic:
druid:
initial-size: 5
min-idle: 5
max-active: 20
max-wait: 60000
test-on-borrow: false
test-on-return: false
test-while-idle: true
time-between-eviction-runs-millis: 60000
min-evictable-idle-time-millis: 300000
primary: dm
strict: true
datasource:
slave_1:
url: jdbc:oracle:thin:@${ORACLE-HOST}:${ORACLE-PORT}/${ORACLE-DB}
username: ${ORACLE-USERNAME}
password: ${ORACLE-PASSWORD}
driver-class-name: oracle.jdbc.OracleDriver
dm:
url: jdbc:dm://127.0.0.1:5236/HEGSADMIN?useUnicode=true&characterEncoding=utf-8
username: ${DM-USERNAME}
password: ${DM-PASSWORD}
driver-class-name: dm.jdbc.driver.DmDriver
这里有几个关键参数需要理解:
primary: dm指定默认数据源为达梦数据库strict: true表示在未指定数据源时抛出异常- 连接池参数如initial-size、max-active等需要根据实际业务负载调整
3. Druid连接池深度配置
3.1 连接池参数优化
Druid连接池的参数配置直接影响系统性能,以下是经验值参考:
yaml复制druid:
initial-size: 5 # 初始化连接数
min-idle: 5 # 最小空闲连接数
max-active: 20 # 最大连接数
max-wait: 60000 # 获取连接等待超时时间(毫秒)
test-on-borrow: false # 申请连接时不检测
test-on-return: false # 归还连接时不检测
test-while-idle: true # 空闲时检测
time-between-eviction-runs-millis: 60000 # 检测间隔
min-evictable-idle-time-millis: 300000 # 最小空闲时间
提示:max-active的设置需要根据数据库服务器配置和应用并发量决定。一般建议初始值为CPU核心数*2+有效磁盘数。
3.2 SQL过滤器配置
Druid提供了强大的SQL过滤功能,可以用于监控和防御SQL注入:
yaml复制druid:
proxy-filters: sqlLogFilter
需要在代码中注册对应的Filter:
java复制@Configuration
public class DruidConfig {
@Bean
public Filter sqlLogFilter() {
StatFilter filter = new StatFilter();
filter.setSlowSqlMillis(1000); // 慢SQL阈值
filter.setLogSlowSql(true); // 记录慢SQL
filter.setMergeSql(true); // 合并相似SQL
return filter;
}
}
4. 多数据源实战应用
4.1 数据源切换实现
MyBatis-Plus提供了简单的注解方式来切换数据源:
java复制@Service
public class UserServiceImpl implements UserService {
@DS("dm") // 使用达梦数据源
public List<User> getLocalUsers() {
return userMapper.selectList(null);
}
@DS("slave_1") // 使用Oracle数据源
public List<User> getRemoteUsers() {
return userMapper.selectList(null);
}
}
4.2 事务处理注意事项
在多数据源环境下,事务管理需要特别注意:
java复制@Service
public class OrderService {
@Transactional
@DS("dm") // 必须指定事务管理器
public void createOrder(Order order) {
// 业务逻辑
}
}
重要:跨数据源的事务需要使用分布式事务解决方案,如Seata。单数据源事务不能跨数据源生效。
5. 常见问题排查
5.1 连接泄漏问题
症状:应用运行一段时间后出现连接耗尽。
解决方案:
- 开启Druid的监控功能
- 检查是否有未关闭的Connection、Statement或ResultSet
- 配置removeAbandoned相关参数
yaml复制druid:
remove-abandoned: true
remove-abandoned-timeout: 1800
log-abandoned: true
5.2 多数据源切换失效
可能原因:
- 方法内部调用导致@DS注解失效
- 事务注解与@DS注解顺序问题
- 数据源名称拼写错误
解决方案:
- 确保@DS注解在最终执行的方法上
- 调整注解顺序:@DS应该在@Transactional之前
- 检查数据源名称是否与配置一致
6. 性能监控与优化
6.1 Druid监控面板配置
启用Druid内置的监控功能:
java复制@Configuration
public class DruidConfig {
@Bean
public ServletRegistrationBean<StatViewServlet> druidServlet() {
ServletRegistrationBean<StatViewServlet> reg = new ServletRegistrationBean<>();
reg.setServlet(new StatViewServlet());
reg.addUrlMappings("/druid/*");
// 添加IP白名单
reg.addInitParameter("allow", "127.0.0.1");
return reg;
}
}
访问 http://localhost:8080/druid 即可查看监控数据。
6.2 SQL性能优化建议
- 定期分析慢SQL日志
- 为常用查询字段添加索引
- 避免在循环中执行SQL
- 合理使用批量操作
java复制// 批量插入示例
@DS("dm")
public void batchInsert(List<User> users) {
userMapper.insertBatchSomeColumn(users);
}
7. 生产环境部署建议
- 连接池参数需要根据实际负载调整
- 不同环境使用不同的配置profile
- 敏感信息如密码应该使用配置中心管理
- 定期检查数据库连接健康状况
对于Oracle和达梦数据库的混合环境,还需要注意:
- SQL语法差异处理
- 数据类型映射问题
- 事务隔离级别一致性
yaml复制spring:
profiles: prod
datasource:
dynamic:
datasource:
slave_1:
url: jdbc:oracle:thin:@prod-oracle:1521/ORCL
dm:
url: jdbc:dm://prod-dm:5236/PROD_DB
在实际项目中,这种多数据源配置已经成功支持了日均百万级的交易量,稳定性得到了充分验证。关键在于合理的连接池配置和严格的SQL监控。