开发者社区 问答 正文

基于模式的多租户:不时获取“ java.sql.SQLException:未选择数据库”

我的代码是用Java编写的,并且使用Spring JDBC模板访问MySQL数据库。

我的系统是一个多租户,每个租户在MySQL中都有自己的专用架构(例如“ tenant_1”,“ tenant_2”等)。

这是初始化数据库连接的方式:

在引导过程中,我创建了一个暴露DataSourceTransactionManager的bean ,该bean 由配置有MySQL数据库的连接字符串(未指定架构)的DataSource初始化。

由于我的系统是多租户,因此对于每个请求,我都必须选择给定租户的架构。因此,典型查询如下所示:

1、“使用tenant_xxx” 2、.... 问题:

我不时地(1至数千次处决)

java.sql.SQLException:未选择数据库。

我仔细检查了我的代码-实际上,我总是在执行查询之前选择架构。

有任何想法吗?

Spring-最新版本(5.x) Java-11 MySQL(5.7),在本地MySQL和AWS Aurora上均已复制

展开
收起
垚tutu 2019-11-28 18:14:31 1003 分享 版权
阿里云 AI 助理回答

遇到“未选择数据库”的异常,尽管您确认每次执行查询前都正确地选择了架构,这可能与几个因素相关。以下是一些排查和解决的建议:

  1. 事务管理器配置:确保您的DataSourceTransactionManager在处理多租户时能够正确维护每个租户的连接状态。Spring框架默认的事务管理可能不会针对每次请求自动切换数据源或模式。考虑使用更精细的事务管理策略,比如为每个租户创建一个独立的数据源(虽然这会增加资源消耗),或者实现自定义的AbstractRoutingDataSource来动态路由到正确的租户数据库。

  2. 连接池配置:检查您的连接池配置(如HikariCP、Tomcat JDBC Pool等),确保连接被正确回收和重用时,不会丢失租户上下文。某些情况下,连接池可能会复用之前操作过的连接,而没有重新设置当前租户的架构。可以尝试调整连接池的参数,如设置适当的测试查询来验证连接的有效性,并在获取连接后强制执行一次租户架构的选择。

  3. 并发问题:如果您的应用在高并发环境下运行,可能存在多个线程同时访问共享连接的情况,导致租户上下文混淆。确保对数据库访问逻辑进行适当的同步控制,或者利用Spring的事务同步机制来避免此类问题。

  4. 日志审查:详细记录每次数据库操作前后的行为,包括选择架构的操作和异常堆栈信息。这有助于定位是哪个具体操作导致的问题,以及是否真的每次查询前都成功设置了架构。

  5. MySQL服务器配置与版本兼容性:虽然可能性较小,但有时数据库服务器的配置或特定版本的MySQL/Aurora可能对多租户架构有特殊要求或限制。检查是否有相关的已知问题或更新补丁。

  6. 代码审查:再次全面审查涉及数据库交互的所有代码路径,特别是那些可能绕过常规租户架构选择逻辑的角落情况或异常处理逻辑。

  7. 使用AOP(面向切面编程):考虑使用Spring AOP来拦截所有数据库操作,在执行前动态添加“USE tenant_xxx”语句,这样可以减少遗漏的可能性,并使代码更加整洁。

如果以上方法都不能解决问题,可能需要通过更详细的日志记录、单元测试和压力测试来进一步诊断问题所在。

有帮助
无帮助
AI 助理回答生成答案可能存在不准确,仅供参考
0 条回答
写回答
取消 提交回答