V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
aizya
V2EX  ›  Java

Java 操作 MySQL 的时候,为什么瞬间会产生大量的 sleep 的连接。

  •  
  •   aizya · 2021-01-21 22:04:09 +08:00 · 3947 次点击
    这是一个创建于 1161 天前的主题,其中的信息可能已经有所发展或是发生改变。

    持久化用的 Hibernate,连接池用的 Hikari,连接池大小设置为 800 。场景是使用 csv 批量导入上万条记录,每条记录不是简单的保存到数据库,可能会涉及到多次数据库查询或者更新操作。

    在这种前提之下,当我将这些动作都放到一个事务中去处理的时候,后台会报如下的错误:

    Caused by: java.sql.SQLTransientConnectionException: HikariPool-3 - Connection is not available, request timed out after 20001ms.
    21:37:18,591 ERROR [stderr] (default task-3) 	at com.zaxxer.hikari.pool.HikariPool.createTimeoutException(HikariPool.java:695)
    21:37:18,591 ERROR [stderr] (default task-3) 	at com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:197)
    21:37:18,591 ERROR [stderr] (default task-3) 	at com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:162)
    21:37:18,591 ERROR [stderr] (default task-3) 	at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:100)
    21:37:18,592 ERROR [stderr] (default task-3) 	at org.hibernate.hikaricp.internal.HikariCPConnectionProvider.getConnection(HikariCPConnectionProvider.java:77)
    21:37:18,592 ERROR [stderr] (default task-3) 	at org.hibernate.engine.jdbc.connections.spi.AbstractMultiTenantConnectionProvider.getConnection(AbstractMultiTenantConnectionProvider.java:36)
    
    

    使用 show processlist 观察 mysql 连接的时候,某个瞬间会产生大量的 sleep 连接。

    现在我的疑问是,sleep 连接是怎么才会产生的? 如果我仅仅只是在循环中执行一万次数据库查询操作,MySQL 连接没有什么波动,而当我在使用事务执行某个耗时任务时(这个任务中会执行查询数据库的操作),就会产生大量的 sleep 连接?

    谁能帮忙解释一下?

    20 条回复    2021-01-22 13:20:50 +08:00
    gjkv86
        1
    gjkv86  
       2021-01-21 22:15:14 +08:00 via iPhone
    800 个连接太多了 什么数据库禁得起这么造啊
    kosmosr
        2
    kosmosr  
       2021-01-21 22:35:51 +08:00 via Android
    连接池原理,预申请,避免频繁新建销毁连接;而且连接池大小不是越大越好
    CEBBCAT
        3
    CEBBCAT  
       2021-01-21 22:52:28 +08:00 via Android
    @gjkv86 800 个很多吗?刚入行的小菜鸡,前两天看到同事在讨论,我们有的 MySQL 实例链接数上限就是 800
    ElmerZhang
        4
    ElmerZhang  
       2021-01-21 23:06:57 +08:00
    @CEBBCAT 一般 SQL 优化的比较好的,连接池设置 10 个就够用了。
    我经手过的某系统,单机峰值 QPS 1500,也只使用了不到 10 个连接。
    neoblackcap
        5
    neoblackcap  
       2021-01-21 23:09:44 +08:00
    如果是在循环中跑事务,那么显然会出现大量 sleep 。毕竟一个连接只能同时处理一个事务啊。你如果快速地提交,显然连接池的连接不够用,那么就会触发大量连接。
    你要不将事务的作用域扩大一些?比如分批次导入,一次用一个事务导入 100 条这样?
    zoharSoul
        6
    zoharSoul  
       2021-01-22 00:29:00 +08:00
    Hikari 建议的连接池大小是 10 还是 15 来着
    xcstream
        7
    xcstream  
       2021-01-22 02:27:57 +08:00
    连接池大小设置为 800 噗
    k9982874
        8
    k9982874  
       2021-01-22 07:26:03 +08:00 via iPhone
    楼主: 连接池 800,启动!
    mysql: ???我死给你看!
    iceneet
        9
    iceneet  
       2021-01-22 08:30:55 +08:00
    ???连接池 800 数据库没挂很厉害了!
    yanzhiling2001
        10
    yanzhiling2001  
       2021-01-22 09:03:10 +08:00
    楼上描述的很准确了,连接池 10-15 就够用的,800mysql 没挂都是他性能好
    cloudhuang
        11
    cloudhuang  
       2021-01-22 09:03:37 +08:00
    设置线程池,其实一般来说,就设置成 2N | 2N + 1 就可以了,数据库连接池也一样
    jorneyr
        12
    jorneyr  
       2021-01-22 09:09:19 +08:00
    看看数据库允许的最大并发连接数是多少。

    此外,800 虽然多,但也不算多,我们数据库连接一般会允许最大 2000 。
    supuwoerc
        13
    supuwoerc  
       2021-01-22 09:47:33 +08:00
    @CEBBCAT 震惊
    mmdsun
        14
    mmdsun  
       2021-01-22 09:54:29 +08:00 via Android
    MySQL 连接数
    和 Java 数据库连接池不是一个概念吧。


    你把链接池改小一下,存活周期改小。

    另外 hibernate jpa 这类批量导数据需要关闭
    spring.jpa.open-in-view false

    不然 session 保存时间太长一直不结束。
    passerbytiny
        15
    passerbytiny  
       2021-01-22 10:08:30 +08:00 via Android
    上万条记录……每条记录……可能会涉及到多次……查询或者更新……将这些动作都放到一个事务……

    你该不会是在循环外面套事务吧,那样的事务太大,压根处理不了。
    WuwuGin
        16
    WuwuGin  
       2021-01-22 10:45:31 +08:00
    Connection is not available, request timed out after 20001ms.
    我怀疑是 mysql 挂了,或者某个表挂了,看看是不是会有死锁产生?
    aizya
        17
    aizya  
    OP
       2021-01-22 11:09:52 +08:00
    @WuwuGin 谢谢,查了没有死锁。 应该是我在处理的时候,把耗时的逻辑放在事务里面去处理了。 但是又不知道该怎么把里面的逻辑拆分出来。
    keepeye
        18
    keepeye  
       2021-01-22 11:12:17 +08:00
    800 有点多,但纯连接应该没事吧,又没跑 sql
    ytll21
        19
    ytll21  
       2021-01-22 11:40:25 +08:00
    你们的数据库就给你这一个系统用吗?你这一个系统就用掉了 800 个。。。还给不给其它系统用呀。。。
    CODEWEA
        20
    CODEWEA  
       2021-01-22 13:20:50 +08:00
    800 个客户端 你们那个机器行吗?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3499 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 11:06 · PVG 19:06 · LAX 04:06 · JFK 07:06
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.