本文共 5843 字,大约阅读时间需要 19 分钟。
相关连接: show processlist 分析:
长连接相关:
项目运行时抛出异常:
org.hibernate.exception.GenericJDBCException: Could not open connection at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:54) at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:125) at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:110) at org.hibernate.engine.jdbc.internal.LogicalConnectionImpl.obtainConnection(LogicalConnectionImpl.java:221) at org.hibernate.engine.jdbc.internal.LogicalConnectionImpl.getConnection(LogicalConnectionImpl.java:157) at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.doBegin(JdbcTransaction.java:67) at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.begin(AbstractTransactionImpl.java:160) at org.hibernate.internal.SessionImpl.beginTransaction(SessionImpl.java:1425) at com.sf.iec.common.dao.BaseDao.saveOrUpdateByBatch(BaseDao.java:268) at com.sf.iec.operationbusiness.manifest.dao.impl.ManifestDaoImpl.insetPostManifestFailLog(ManifestDaoImpl.java:2284) at com.sf.iec.operationbusiness.manifest.service.impl.ManifestServiceImpl.pushAcpInfo(ManifestServiceImpl.java:4763) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317) at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:90) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204) at com.sun.proxy.$Proxy152.pushAcpInfo(Unknown Source) at com.sf.iec.common.thread.AcpInfoPushRunnable$1.handler(AcpInfoPushRunnable.java:40) at com.sf.iec.common.util.BatchHandlerList.handlerList(BatchHandlerList.java:44) at com.sf.iec.common.thread.AcpInfoPushRunnable.run(AcpInfoPushRunnable.java:47) at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918) at java.lang.Thread.run(Thread.java:662)Caused by: java.sql.SQLException: Couldn't get connection because we are at maximum connection count (100/100) and there are none available at org.logicalcobwebs.proxool.Prototyper.quickRefuse(Prototyper.java:309) at org.logicalcobwebs.proxool.ConnectionPool.getConnection(ConnectionPool.java:152) at org.logicalcobwebs.proxool.ProxoolDataSource.getConnection(ProxoolDataSource.java:97) at org.hibernate.service.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:141) at org.hibernate.internal.AbstractSessionImpl$NonContextualJdbcConnectionAccess.obtainConnection(AbstractSessionImpl.java:292) at org.hibernate.engine.jdbc.internal.LogicalConnectionImpl.obtainConnection(LogicalConnectionImpl.java:214) ... 26 more
用 show full processlist 语句发现本机IP已经使用了100个DB连接(均为sleep状态)
相关 sql:
select SUBSTRING_INDEX(host,':',1) as ip , count(*) from information_schema.processlist group by ip;show full processlist;show status;show GLOBAL VARIABLES like '%wait_timeout%'
其实是baseDAO的代码问题, session.close()没有放到finally里面 导致前面语句插入失败时没有提交事务 也没有释放连接:
错误代码:
public void saveByBatch(Listlist ,int batchSize){ if(!CollectionUtil.isEmpty(list)){ Session session = sessionFactory.openSession(); Transaction tx = session.beginTransaction(); int i=0; for (T entity:list ) { i++; session.save(entity); if ( i % batchSize == 0 ) { session.flush(); session.clear(); } tx.commit(); session.close(); } }
睡眠连接过多 解决方法
睡眠连接过多,会对mysql服务器造成什么影响?
严重消耗mysql服务器资源(主要是cpu, 内存),并可能导致mysql崩溃。
造成睡眠连接过多的原因?
1. 使用了太多持久连接(个人觉得,在高并发系统中,不适合使用持久连接)
2. 程序中,没有及时关闭mysql连接 3. 数据库查询不够优化,过度耗时。那么,如果要从根本上解决sleep连接过多,就得从以上三点反复检查,但是见效并不快。
网上有人分享,使用shell脚本配合cron,定期杀死睡眠时间太久的连接,但是这种方法非常不可取,典型的以暴制暴,很可能导致数据崩溃,而且,还需要编写相应shell, 设置cron, 实施成本较繁琐,不推荐使用。
那么更好的办法应该是让mysql自己决定这些睡眠连接的命运,实施会更简单,有效。
mysql的配置文件中,有一项: wait_timeout, 即可设置睡眠连接超时秒数,如果某个连接超时,会被mysql自然终止,多好的办法!如设置:
wait_timeout=100 #即设置mysql连接睡眠时间为100秒,任何sleep连接睡眠时间若超过100秒,将会被mysql服务自然终止,要比编写shell脚本更简单。那么,对于正在运行中的生产服务器,在不能停止服务情况下,修改此项怎么办?很简单,以root用户登录到mysql,执行:
set global wait_timeout=100
# vi /etc/my.cnf [mysqld] wait_timeout=10 # /etc/init.d/mysql restart
- 1
不过这个方法太生硬了,线上服务重启无论如何都应该尽可能避免,看看如何在MySQL命令行里通过SET来设置:
mysql> set global wait_timeout=10; mysql> show global variables like '%timeout'; +----------------------------+-------+ | Variable_name | Value | +----------------------------+-------+ | wait_timeout | 10 | +----------------------------+-------+
- 1
即可。
在我的生产环境中,使用这个办法,取得了相当好的效果。
当然,更根本的方法,还是从以上三点排查之:
1. 程序中,不使用持久链接,即使用mysql_connect而不是pconnect。 2. 程序执行完毕,应该显式调用mysql_close 3. 只能逐步分析系统的SQL查询,找到查询过慢的SQL,优化之wait_timeout默认值:
interactive_timeout默认值:sql命令:
SHOW GLOBAL VARIABLES LIKE 'wait_timeout';SHOW GLOBAL VARIABLES LIKE 'interactive_timeout';set global wait_timeout=30;SET GLOBAL interactive_timeout=30;
小注:wait_timeout要与interactive_timeout一起修改才能起效。
这种修改方式在重启mysql服务后,会失效,所以最好还是把这两个属性配置到mysql配置文件中。转载地址:https://blog.csdn.net/liao0801_123/article/details/82690863 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!