【问题标题】:Schema-based multitenancy: getting "java.sql.SQLException: No database selected" from time to time基于模式的多租户:不时出现“java.sql.SQLException:未选择数据库”
【发布时间】:2020-03-23 22:15:48
【问题描述】:

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

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

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

在引导期间,我创建了一个暴露 DataSourceTransactionManager 的 bean,它由配置了 MySQL 数据库连接字符串的 DataSource 初始化(不指定架构)。

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

  1. “使用租户_xxx”
  2. ....

问题:

不时(1 到数千次处决),我得到了

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

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

有什么想法吗?

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

更新:添加更多信息

  • 我使用 Spring Boot,默认使用 HikariCP
  • 我注意到代码中随机位置的问题,所以很可能它不是 我的代码中特定位置的错误

更新 2:

  • 连接器/J 版本 8.0

【问题讨论】:

    标签: java mysql spring spring-jdbc


    【解决方案1】:

    有很多事情可能会出错,我将尝试提供一般性想法,希望其中一些有用。

    所以,给定信息:

    1. 一般的想法。尝试记录 sql 请求,以便在发生错误时查看它是否始终是相同的请求/请求类型(导致代码的某些特定区域出现错误的东西)。

    2. 检查您的连接池。您没有指定实际的池,但从问题中可以清楚地看出它不是“自我教育”项目或其他什么,所以您可能有一个。 有时他们在尝试处理多租户环境时会遇到错误。

    3. 如果适用,请检查在查询中添加架构名称的方法,可能是驱动程序中存在错误或其他问题(不太可能)。我的意思是,而不是

    USE XYZ
    select * from foo
    

    你可以使用

    select from xyz.foo
    

    【讨论】:

    • 嗨,马克,我编辑了问题以提供更多信息。基本上我们使用 HikariCP,肯定他们在多租户环境中可能存在错误(我会尝试询问他们)。此外,我们看到这个问题发生在多个地方,所以很可能它不是我们代码中的错误(至少不是在查询级别)תודה
    • 酷。在这种情况下,还有一个更普遍的想法。是否有机会将 Hikari CP 切换到其他池以检查问题是否仍然存在?更改应该是透明的(配置属性+依赖)...
    • 关于使用“完全限定”表名(例如 schema.table):这不是一种可扩展的方法,因为 Connector/J 将每个 SQL 解析和缓存为“预编译”语句。此缓存是一个字典,其中键是原始 SQL 语句(字符串)。因此,使用完全限定的表名会将所有使用的 SQL 语句重复缓存为多个模式。
    • 顺便说一句,您能否发布一个小代码 sn-p,显示您如何准确地使用 jdbc 模板,也许您只是以通常有效但有时会失败的错误方式进行操作...
    • 我想到了在一个连接上执行“use”语句但随后在另一个连接上执行实际语句以防出错的情况。通常这不会发生,因为从池中选择了相同的连接,但有时(多线程高负载谁知道)池为实际的 sql 语句提供不同的连接......查看一些实际代码可能有助于提供解决方案或建议如何检查
    【解决方案2】:

    如果您有连接池的配置资料,请提供。

    听起来连接池是在USE 和随后的DDL/DML 语句之间切换连接。

    另外,有没有办法将数据库分配给池条目,反之亦然?

    【讨论】:

    • 这也是我们目前的工作原理。我们在代码中进行重构,很快我们就会看到。关于池配置 - 没有 - 我们只是使用默认的 Spring Boot 配置
    • 另一个想法...如果您(或 Spring)未能检查错误,可能会有一个 USE 语句,而不是设置数据库,而是充当自动执行的“ping”重新连接。自动重新连接不是一个好主意,因为它会弄乱事务。
    猜你喜欢
    • 2020-02-02
    • 1970-01-01
    • 2014-12-17
    • 1970-01-01
    • 2020-06-26
    • 1970-01-01
    • 1970-01-01
    • 2014-01-16
    • 2012-12-14
    相关资源
    最近更新 更多