MY-SQL

 

Tomcat 에서 jndi 등으로

MySQL Connection 세팅을 하고 쓰다보면

 

가끔. java.io.EOFException: Can not read response from server.

Expected to read 4 bytes, read 0 bytes before connection was unexpectedly lost.

이런류의 에러를 뱉을때가 있다.

 

원인을 찾아보니 MySQL Connection Error 인데,

어느 정도 사용을 하는 어플리케이션이라면 이런 문제는 발생하지 않을것이다.

MySQL 은 기본적으로 컨넥션을 통해서 8시간 동안 request가 오지 않는다면, 

강제적으로 컨넥션을 닫아버린다.

 

( 이는 물론 MySQL 의 설정을 변경함으로써 값을 바꿀 수는 있다. 하지만, 좋은 방법이라고 생각되지는 않는다. )

해결방법은 의외로 간단했다.

 

 

 

<GlobalNamingResources>

    <Resource name="커넥션이름" 

              auth="Container" 

              type="javax.sql.DataSource"

              maxActive="1000"

              maxIdle="30"

              maxWait="180"

              logAbandoned="true"

              removeAbandoned="true"

              removeAbandonedTimeout="60"

              <!-- validationQuery:유효 검사용 쿼리

                  ( 1개 이상의 row를 반환하는 쿼리를 넣어주면 된다. ) -->

           validationQuery="select 1"

              <!-- testWhileIdle:컨넥션이 놀고 있을때 -_-; 

                  validationQuery 를 이용해서 유효성 검사를 할지 여부. -->

           testWhileIdle="true"

              <!-- timeBetweenEvictionRunsMillis:

                  해당 밀리초마다 validationQuery 를 이용하여 유효성 검사 진행 -->

           timeBetweenEvictionRunsMillis="7200000"

              username="DB접속ID"

              password="DB접속비밀번호"

              driverClassName="com.mysql.jdbc.Driver"

              url="jdbc:mysql://DBurl/DBname"/>

  </GlobalNamingResources>

 

 

 

Error Log

2013. 7. 30 오후 6:18:56 org.apache.catalina.core.StandardWrapperValve invoke

심각: Servlet.service() for servlet [dispatcher] in context with path [/test] threw exception [Request processing failed; nested exception is org.springframework.transaction.CannotCreateTransactionException: Could not open JDBC Connection for transaction; nested exception is com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure

 

The last packet successfully received from the server was 34,961 milliseconds ago.  

The last packet sent successfully to the server was 1 milliseconds ago.] with root cause

java.io.EOFException: Can not read response from server. 

Expected to read 4 bytes, read 0 bytes before connection was unexpectedly lost.

at com.mysql.jdbc.MysqlIO.readFully(MysqlIO.java:3052)

at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:3503)

at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:3492)

at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4043)

at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2503)

at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2664)

at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2809)

at com.mysql.jdbc.ConnectionImpl.setAutoCommit(ConnectionImpl.java:5333)

at org.apache.tomcat.dbcp.dbcp.DelegatingConnection.setAutoCommit(DelegatingConnection.java:371)

at org.apache.tomcat.dbcp.dbcp.PoolingDataSource$PoolGuardConnectionWrapper.setAutoCommit(PoolingDataSource.java:328)

at org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin(DataSourceTransactionManager.java:223)

at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:371)

at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:335)

at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:105)

at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)

at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:89)

at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)

at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)

at com.sun.proxy.$Proxy23.sendLearnPush(Unknown Source)

at com.unus.englishcall.common.controller.CommonController.sendLearnPush(CommonController.java:199)

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.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:176)

at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:426)

at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:414)

at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:790)

at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719)

at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:644)

at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:560)

at javax.servlet.http.HttpServlet.service(HttpServlet.java:647)

at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)

at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)

at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)

at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)

at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)

at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)

at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)

at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)

at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:947)

at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)

at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)

at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1009)

at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)

at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)

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)

 

 

	<environments default="development">
        <environment id="development">
            <transactionManager type="JDBC" />

<dataSource type="DBCP">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://ec2-54-180-93-87.ap-northeast-2.compute.amazonaws.com:3306/111?autoReconnect=true" />
<property name="username" value="1111" />
<property name="password" value="111" />
<property name="defaultAutoCommit" value="true" />
<property name="maximumActiveConnections" value="5" />
<property name="maximumIdleConnections" value="3" />
<property name="maximumWait" value="60000" />
<!-- validationQuery:유효 검사용 쿼리( 1개 이상의 row를 반환하는 쿼리를 넣어주면 된다. ) -->
<property name="validationQuery" value="select 1"/>
<!-- testWhileIdle:컨넥션이 놀고 있을때 -_-; validationQuery 를 이용해서 유효성 검사를 할지 여부. -->
<property name="testWhileIdle" value="true"/>
<!-- timeBetweenEvictionRunsMillis:해당 밀리초마다 validationQuery 를 이용하여 유효성 검사 진행 -->
<property name="timeBetweenEvictionRunsMillis" value="7200000"/>
</dataSource>
      
        </environment>
    </environments>
    

 

 

 

 

 

 

Warning... too many connections..."

라고 하는 메시지와 함께 종료되는 경우가 발생합니다.

이 문제의 root cause는 MYSQL의 환경변수에 설정되어있는 "max_connections" 값을 초과하는 쿼리가 발생하는 것입니다.

 

"mysqladmin -u root -p variables" 를 실행해보면 MYSQL의 전체 환경변수의 값을 확인 할 수 있는데 그 가운데 다음 3가지의 값을 조절함으로서 해당 에러를 응급조치 할 수 있습니다.

 

- max_connections  : MYSQL에 접속할 수 있는 최대 연결 수

- table_open_cache : MYSQL의 캐쉬 크기

- wait_timeout     : MYSQL의 쿼리가 지속되는 시간

 

이 방법으로 "too many connections" 문제가 해결되었다면 부팅시마다 MYSQL을 시작하면서 매번 자동 적용 되도록 /etc/rc.d/rc.local 파일에 아래와 같이 설정해두는 것도 좋은 방법이 됩니다.

 

예시)

/usr/local/mysql/bin/mysqlid_safe -O max_connections=1000 -O table_open_cache=512 -O wait_timeout=57600 &

 

 

 

 

 

 

about author

PHRASE

Level 60  라이트

악으로 시작한 것은 악에 의해 강화된다. -셰익스피어

댓글 ( 9)

댓글 남기기

작성