【问题标题】:Spring Boot Rest + ClearDB mySQL "exceeded 'max_user_connections'" errorSpring Boot Rest + ClearDB mySQL“超过'max_user_connections'”错误
【发布时间】:2020-04-30 11:49:07
【问题描述】:

我每隔一段时间就会随机收到此错误:“java.sql.SQLSyntaxErrorException: User '{key}' has exceeded the 'max_user_connections' resource (current value: 10)”。

我已经尝试在谷歌上搜索帮助,但我只能找到:

  1. “增加最大连接数限制”(在免费的 clearDB 中无法做到)
  2. “调整 maxActive 数量”或“释放旧连接”(我在 Spring Boot 中都找不到如何操作)

我的代码如下所示:

// application.properties
# Connect to heroku ClearDB MySql database
spring.datasource.url=jdbc:mysql://{heroku_url}?reconnect=true
spring.datasource.username={user}
spring.datasource.password={password}

# Hibernate ddl auto (create, create-drop, update)
spring.jpa.hibernate.ddl-auto=update

#MySQL DIALECT
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
spring.jpa.open-in-view=false
server.port=8080
@Configuration
public class DatabaseConfig {
    @Value("${spring.datasource.url}")
    private String dbUrl;

    @Bean
    public DataSource dataSource() {
        HikariConfig config = new HikariConfig();
        config.setJdbcUrl(dbUrl);

        return new HikariDataSource(config);
    }
}

编辑 1:我尽我所能遵循 PauMAVA 的说明,我想出了这段代码,但由于某种原因失败了:

@Configuration
public class DatabaseConfig {
    @Value("${spring.datasource.url}")
    private String dbUrl;

    public static DataSource ds;

    @Bean
    public DataSource dataSource() {
        HikariConfig config = new HikariConfig();
        config.setJdbcUrl(dbUrl);

        DataSource ds = new HikariDataSource(config);
        DatabaseConfig.ds = ds;

        return ds;
    }
}
// Main class
public static void main(String[] args) {
    SpringApplication.run(BloggerApplication.class, args);

    Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
        public void run() {
            DataSource ds = DatabaseConfig.ds;
            if (ds != null) {
                try {
                    ds.getConnection().close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }, "Shutdown-thread"));
}

【问题讨论】:

  • 尝试使用HikariConfig 中的setMaximumPoolSize(5) 降低最大池大小。 Hikari 的默认最大池大小为 10,这也是 ClearDB 的最大限制。还要避免长时间运行的查询。
  • @RyanGuamos 似乎有效,我现在已经重新启动后端超过 10 次并且每次都获取数据并且完全没有错误。我只是希望有某种方法可以测试它现在是否确实已修复,在我对 HikariConfig 进行每次更改后,它始终可以正常工作一段时间。
  • 您也可以考虑增加HikariConfig 的连接超时时间,默认为 30 秒,因此如果连接已经达到最大池大小,查询可能会等待超过 30 秒
  • @RyanGuamos 如果我增加连接超时有一个问题,我一直在默认时间收到此警告:"WARN 7364 - Possibly consider using a shorter maxLifetime value" 所以我不得不将其更改为:config.setMaxLifetime(30000);,或者是连接超时与 maxLifetime 不同?
  • maxLifetime 不同于connectionTimeout 你可以参考他们的官方文档https://github.com/brettwooldridge/HikariCP#configuration-knobs-baby

标签: java mysql spring-boot spring-data-jpa cleardb


【解决方案1】:

每当您在代码中创建连接对象时,建议在 finally 块中关闭该对象。这样连接数就不会耗尽。

希望这会有所帮助!

【讨论】:

  • 但我不知道我在哪里打开连接。我不会在任何地方调用“数据源”方法,我只使用普通的 RestController 方法,例如:@RequestMapping(value = "/blogposts", method= RequestMethod.GET) public Iterable fetchBlogposts() { return blogDatabase.找到所有(); }
【解决方案2】:

您应该在应用程序终止时关闭 DataSource,以便没有未使用的连接保持打开状态。

public void close(DataSource ds) {
    if(ds != null) {
        ds.close();
    }
}

但仅在程序终止时执行此操作,如 here 所述。

要稍后使用数据源(关闭时),您可以将 DataSource 注册为类中的字段:

private DataSource ds;

@Bean
public DataSource dataSource() {
    HikariConfig config = new HikariConfig();
    config.setJdbcUrl(dbUrl);
    DataSource ds = new HikariDataSource(config);
    this.ds = ds;
    return ds;
}

如果您要拥有多个数据源,您可以采用基于列表的方法:

private List<DataSource> activeDataSources = new ArrayList<>();

public DataSource dataSource() {
    HikariConfig config = new HikariConfig();
    config.setJdbcUrl(dbUrl);
    DataSource ds = new HikariDataSource(config);
    this.activeDataSources.add(ds);
    return ds;
}

public void closeAllDataSources() {
    for(DataSource ds: this.activeDataSources) {
        if(ds != null) {
            ds.close();
        }
    }
    this.activeDataSources = new ArrayList<>();
}

要在程序关闭时执行函数,请参阅this

【讨论】:

  • 我是否需要在我的项目中包含一个执行器模块以在后端终止时调用该 close 方法,或者有更好的方法吗?以及如何访问该 DataSource 以便将其作为参数提供?
  • 我已经添加了您需要的信息。希望它有所帮助:)
  • 我觉得自己很愚蠢,但我似乎无法弄清楚您希望我如何实现这一点。我没有从我的代码中的任何地方访问 DataSource(据我所知),但我编辑了我的问题以向您展示我是如何理解您的指令的。我觉得我错过了这方面的一些关键方面。
  • 你不需要显式关闭连接,因为在Spring boot中,如果你添加了spring数据依赖,它会自动配置一个事务管理。它通过在类级别或方法级别定义@Transactional,在事务完成后自动关闭连接。
  • @Crossoni 只是 spring-boot-starter-data-jpa。当您使用 spring 数据中可用的任何存储库接口时,它们的默认实现具有 @Transactional 注释,因此需要将其添加到应用程序的任何层中,除非您需要覆盖它或在服务层中进行一些事务管理。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-26
  • 1970-01-01
  • 2020-12-21
  • 2016-09-13
  • 2019-07-26
相关资源
最近更新 更多