Too many connection 문제 해결

 

wha
이번해 초부터 시작된 too many connection 문제가 하루에 한번씩 mysql 을 뻗게 만들었다.
되는대로... 아무것도 모른채로 만든 운영툴이 그 원인... 쿼리도 10초 이상 걸리는 것도 존재했고..인덱스도 제대로 안걸려있고..
그래서 슬로우 쿼리를 잡고 인덱스도 제대로 걸어서...그런 쿼리문제를 없앰으로서 커넥션 문제는 없어질 줄 알았다.
그런데 여전히 하루에 한번씩...서버를 내렸다 올리는 걸 반복해야 했으니.... 그래서 다음과 같은 삽질 겸.. 재설정 시작..
이젠 그만 잡혀달라고~~~~! ㅠㅠ

Too many connections?
모든 연결 가능한 connections 이 다른 clients 들에 의해 쓰이고 있다는 의미.. 결국 이 이후의 커넥션 연결은 실패하게 되고 max_connect_errors 동안 커넥션에 실패하게 되면 이 이후의 모든 커넥션이 블러킹이 된다.


해결방법 1.

슬로우 쿼리의 제거, connection 을 지속시키는 불필요한 것들을 제거한다.
connection 연결 시간을 최대한 줄인다. jdbc 설정에서는 데이터베이스 커넥션풀을 만들고 관리할 수 있다. 이때 이미 있는 커넥션을 재생하여 재 사용하는 것이 새 커넥션을 가져오는 것보다 효율적인데 웹 애플리케이션서 이들 커넥션을 닫지 못하게 되면 다시 재사용할 수가 없게 된다. 이를 해결할 수 있는 방법이 Jakarta-Commns DBCP 이다. 여기서는 버려진 커넥션을 추적해서 복구하도록 설정할 수 있는데 이 설정은 DBCP DataSoure 설정으로 할 수 있다.

또한 mysql_connect() 함수를 사용하면 해당 스크립트의 종료와 함께 자동으로 연결이 종료된다고 하지만 실제로 살펴보면 커넥션은 그대로 살아있다. ( " ./mysqladmin -u -p processlist "  명령어로 확인) 이것은 mysql 의시작옵션 중 wait_timeout 과 연관된다. 이 값만큼 서버에 그대로 연결을 유지한 채 남아있는 것이다.

- datasource 설정
    // db connection 을 재 사용하겠다고 선언 (default는 false 이다)
    admin.datasource.master.jdbc.removeAbandoned=true
    //버려진 connection 으로 간주하는 시간은 1분으로 설정
    admin.datasource.master.jdbc.removeAbandonedTimeout = 60
    // 재사용하는 커넥션에 대한 로그를 남기겠다고 선언(defaul는 false 이다)
    admin.datasource.master.jdbc.logAbandoned = true

- wait-timeout 설정
  #mysql server 설정
   port =3306
   socket = /tmp/mysql.sock
   .......기타 설정들
   ....... 
   wait_timeout = 50
   #wait_timeout 을 50으로 줄임

=> 슬로우 쿼리를 제거하는게 우선적으로 행해져야 한다. 커넥션을 지속시키는 가장 큰 원인이므로 슬로우 쿼리를 해결하면 커넥션 수를 감소시킬 수 있다. 또한 DB 서버의 접속이 많은 경우 wait_timeout 을 최대한 적게(10~20 정도..) 설정하여 불필요한 연결을 빨리 정리하는 것이 좋다. 하지만 Connection Miss Rate(%) 가 1% 이상이라면(아래 튜닝 부분에서 설명) 좀 더 길게 잡을 필요가 있다.


해결방법 2.

max_connection 수를 증가 시켜 connection 개수를 확보한다.
이 때 커넥션풀을 사용하고 있다면 java 설정에서 jdbc 의 connection-pool 의 최대 도 같이 증가시켜야 한다.


- mysql 서버의 my.cnf 에  max-connection 개수 설정
  #mysql server 설정
   port =3306
   socket = /tmp/mysql.sock
   .......기타 설정들
   ....... 
   max_connections = 200 
   #커넥션을 200으로 올림

- jdbc pool-max 설정
   //최소 connection pool 개수
   admin.datasource.master.jdbc.pool-min=3 아래 문제 발생! 참고하세요 .
   //최대 connection pool 개수
   admin.datasource.master.jdbc.pool-max=100  //max_connections 와 비례해서 증감시켜야 한다.

=> 문제: 하루에 보통 사용하는 connection 수는 기본 4~50 이었다. 그런데 이 연결이 어느 한 순간 150~180 이렇게 치솟게 된다. 이때 에러가 발생하는 것... 기본적으로 connection 수가 많다면 max connection 을 증가 시키는 것이 맞지만 어느 순간 치솟는 커넥션이라면 max를 증가한다고 해결되지는 않는다.



해결방법 3.

connection 에 대한 튜닝을 한다.
 

1. status

  • Aborted_clients - 클라이언트 프로그램이 비 정상적으로 종료된 수
  • Aborted_connects - MySQL 서버에 접속이 실패된 수
  • Max_used_connections - 최대로 동시에 접속한 수
  • Threads_cached - Thread Cache의 Thread 수
  • Threads_connected - 현재 연결된 Thread 수
  • Threads_created - 접속을 위해 생성된 Thread 수
  • Threads_running - Sleeping 되어 있지 않은 Thread 수

2. system variables

  • wait_timeout - 종료전까지 요청이 없이 기다리는 시간 ( TCP/IP 연결, Shell 상의 접속이 아닌 경우 )
  • thread_cache_size - thread 재 사용을 위한 Thread Cache 수로써, Cache 에 있는 Thread 수보다 접속이 많으면 새롭게 Thread를 생성한다.
  • max_connections - 최대 동시 접속 가능 수
<현재 내 mysql 정보>

 mysql> show variables like '%max_connection%';
+-----------------+-------+
| Variable_name   | Value |
+-----------------+-------+
| max_connections | 200   |
+-----------------+-------+
1 row in set (0.00 sec)

mysql> show status like '%connect%';
+----------------------+-------+
| Variable_name        | Value |
+----------------------+-------+
| Aborted_connects     | 8     |
| Connections          | 10558 |
| Max_used_connections | 32    |
| Threads_connected    | 12    |
+----------------------+-------+
4 rows in set (0.01 sec)

mysql> show status like '%clients%';
+-----------------+-------+
| Variable_name   | Value |
+-----------------+-------+
| Aborted_clients | 680   |
+-----------------+-------+
1 row in set (0.01 sec)

mysql> show status like '%thread%';
+------------------------+-------+
| Variable_name          | Value |
+------------------------+-------+
| Delayed_insert_threads | 0     |
| Slow_launch_threads    | 0     |
| Threads_cached         | 4     |
| Threads_connected      | 14    |
| Threads_created        | 246   |
| Threads_running        | 1     |
+------------------------+-------+
6 rows in set (0.02 sec)


<계산식>
Cache Miss Rate(%) =  (Threads_created / Connections) * 100
Connection Miss Rate(%) = (Aborted_connects / Connections) * 100
Connection Usage(%) = (Threads_connected / max_connections) * 100

(나의 경우는 Cache Miss Rate(%) = 2.3%, Connection Miss Rate(%) = 0.08%, Connection Usage(%) = 7% 이다.
peak time 때 계산해보는 것이 중요...)

- > 설명

경축! 아무것도 안하여 에스천사게임즈가 새로운 모습으로 재오픈 하였습니다.
어린이용이며, 설치가 필요없는 브라우저 게임입니다.
https://s1004games.com

  • Connection Usage(%)가 100% 라면 max_connections 수를 증가시켜 주십시요. Connection 수가 부족할 경우 Too many connection 문제가 발생합니다.
  • DB 서버의 접속이 많은 경우는 wait_timeout 을 최대한 적게 (10~20 정도를 추천) 설정하여 불필요한 연결을 빨리 정리하는 것이 좋습니다. 그러나 Connection Miss Rate(%) 가 1% 이상이 된다면 wait_timeout 을 좀 더 길게 잡는 것이 좋습니다.
  • Cache Miss Rate(%) 가 높다면 thread_cache_size를 기본값인 8 보다 높게 설정하는 것이 좋습니다. 일반적으로 threads_connected 가 Peak-time 시 보다 약간 낮은 수치로 설정하는 것이 좋습니다.
  • MySQL 서버는 외부로 부터 접속 요청을 받을 경우 인증을 위해 IP 주소를 호스트네임으로 바꾸는 과정을 수행하여 접속시에 불필요한 부하가 발생하게 됩니다. skip-name-resolve를 설정하시고 접속시에 IP 기반으로 접속을 하게 되면 hostname lookup 과정을 생략하게 되어 좀 더 빠르게 접속을 하실 수 있습니다.

    =============================================================================
    문제 해결!!

내 경우는 wait_timeout 과 Cache Miss Rate 에 문제가 있었다.
원래 wait_timeout 이 28800 으로 설정되어 있었고 Threads_cashed 가 0 으로 되어있었기에 thread_created 가 connection 수만큼 증가하였던 것..
이렇게 설정 후 mysql을 재시작 하게 한 지금은 connection 이 치솟는 현상은 없는 듯하다.
아직은...조금 더 지켜봐야겠지만 예전에 비해 연결 정도가 안정적인것 같다. 이것으로 더이상 500 Too many connection 이란 글자를 안 봤으면 한다.. ㅠㅠ 시달린다 정말....
======================================================

!!! 해결 한 줄 알았던 문제 또 발생!!

이번엔...oraqle 이다...어휴 이건 DB 설정 못 건들이는데....
자꾸 요청이 올 때 마다 치솟는 connection 수.. 외부서 배치로 2만개의 쿼리가 날라오는 것 땜에 리스너가 맛이 갈 정도였다..

DB 설정과 jdbc 설정이 안 맞는게 이상하여 테스트를 해보았다.
jdbc 설정 고치기..
커넥션 풀 의 속성 은 아래와 같다.

 

 

속성 설명
maxActive 커넥션 풀이 제공할 최대 커넥션 개수
whenExhaustedAction 커넥션 풀에서 가져올 수 있는 커넥션이 없을 때 어떻게 동작할지를 지정한다. 1일 경우 maxWait 속성에서 지정한 시간만큼 커넥션을 구할 때 까지 기다리며, 0일 경우 에러를 발생시킨다. 2일 경우에는 일시적으로 커넥션을 생성해서 사용한다.
maxWait whenExhaustedAction 속성의 값이 1일 때 사용되는 대기 시간. 단위는 1/1000초이며, 0 보다 작을 경우 무한히 대기한다.
maxIdle 사용되지 않고 풀에 저장될 수 있는 최대 커넥션 개수. 음수일 경우 제한이 없다.
minIdle 사용되지 않고 풀에 저장될 수 있는 최소 커넥션 개수.
testOnBorrow true일 경우 커넥션 풀에서 커넥션을 가져올 때 커넥션이 유효한지의 여부를 검사한다.
testOnReturn true일 경우 커넥션 풀에 커넥션을 반환할 때 커넥션이 유효한지의 여부를 검사한다.
timeBetweenEvctionRunsMillis 사용되지 않은 커넥션을 추출하는 쓰레드의 실행 주기를 지정한다. 양수가 아닐 경우 실행되지 않는다. 단위는 1/1000 초이다.
numTestsPerEvictionRun 사용되지 않는 커넥션을 몇 개 검사할지 지정한다.
minEvictableIdleTimeMillis 사용되지 않는 커넥션을 추출할 때 이 속성에서 지정한 시간 이상 비활성화 상태인 커넥션만 추출한다. 양수가 아닌 경우 비활성화된 시간으로는 풀에서 제거되지 않는다. 시간 단위는 1/1000초이다.
testWhileIdle true일 경우 비활성화 커넥션을 추출할 때 커넥션이 유효한지의 여부를 검사해서 유효하지 않은 커넥션은 풀에서 제거한다.

이 중..minIdle 은 사용되지 않고 풀에 저장될 수 있는 최소 커넥션이란다..그래 최소니까 최소한으로 끊지 않고 연결해두면 나중에 커넥션 요청 시 다시 맺지 않고 있는 걸 쓸테니 효율적이겠지...라고 생각했다만!! 이게 커넥션을 줄어들지 않게 만든 원인이 되고 있었다. 왜그럴까 의구심은 증폭.. 혹시 pool 자체가 하나가 아니고 여러개가 생성이 되나 하는 의심을 하게 된다.
각 pool 마다 최소 커넥션을 유지하다보니 커넥션이 줄지 않는 게 아닐까... 근데 그럼 이게 있는 의미가 없잖아...ㅠㅠ

헤고..일단 minIdle을 0으로 과감히 세팅해버렸다..무식하지만...일단 효율보다 DB가 죽어나게 생겼다...
- jdbc pool-max 설정을 아래와 같이 바꿔보자
   //최소 connection pool 개수
   admin.datasource.master.jdbc.pool-min=0   // 커넥션 풀 에 남아있지 않게 바꿈..
   admin.datasource.master.jdbc.pool-max=20  //max_connections 와 비례해서 증감시켜야 한다.


참고! 위에서 말한 DB 설정 해결방법은 DB 에서 강제로 커넥션을 끊어주는 것에 반하여 아래는 DB 접속하는 측에서 connection 을 그때 그때 끊어주면서 접근하니까 아래 방법이 일단 더 낫다고 본다..

 

[출처] http://egloos.zum.com/kwaknu/v/5212895

 

 

 

본 웹사이트는 광고를 포함하고 있습니다.
광고 클릭에서 발생하는 수익금은 모두 웹사이트 서버의 유지 및 관리, 그리고 기술 콘텐츠 향상을 위해 쓰여집니다.
번호 제목 글쓴이 날짜 조회 수
공지 오라클 기본 샘플 데이터베이스 졸리운_곰 2014.01.02 25085
공지 [SQL컨셉] 서적 "SQL컨셉"의 샘플 데이타 베이스 SAMPLE DATABASE of ORACLE 가을의 곰을... 2013.02.10 24564
공지 [G_SQL] Sample Database 가을의 곰을... 2012.05.20 25943
525 데이터 사이언스 학습 안내 졸리운_곰 2018.11.11 165
524 MySQL 중복 데이터 찾아서 삭제하기 졸리운_곰 2018.10.29 141
523 MySQL에서 중복되는 행을 하나만 남기도 모두 삭제하는 방법 졸리운_곰 2018.10.29 94
522 데이터베이스 진단의 핵심기법 file 졸리운_곰 2018.09.11 145
521 kor-char-rnn-tensorflow 한글텍스트 RNN 학습 텐서플로우 file 졸리운_곰 2018.09.06 196
520 Prophet: Automatic Forecasting Procedure 자동 예측 프로시져 프로그램 /데이터분석 / 데이터 과학 file 졸리운_곰 2018.09.04 162
519 7 ways to convince MySQL to use the right index 졸리운_곰 2018.08.30 88
518 MYSQL에서 원치않는 TABLE LOCK이 걸렸을 경우 해제 방법입니다. 졸리운_곰 2018.08.29 118
517 제목 : [mysql] 현재날짜에서 이전달 구하기 file 졸리운_곰 2018.08.28 450
516 [mysql-함수]날짜 관련 함수 모음 졸리운_곰 2018.08.24 219
515 [질문]디비안에 있는 이번달에 입력된 자료만 뽑아 보고 싶거든요 졸리운_곰 2018.08.24 170
514 MYSQL 이번달 검색 쿼리 (말일,첫일 구하기) 졸리운_곰 2018.08.24 1333
513 MySQL 현재시간을 기준으로 (+, -) 시간 조회하기 - SUBDATE 졸리운_곰 2018.08.17 167
512 How to INSERT If Row Does Not Exist (UPSERT) in MySQL 졸리운_곰 2018.08.16 138
511 Learn R in 15 Minutes file 졸리운_곰 2018.08.14 198
510 torch lua install on ubuntu 16.04 LTS [machine learning] 졸리운_곰 2018.08.13 190
509 How to kill MySQL connections 졸리운_곰 2018.08.02 181
508 MYSQL의 "too many connections" 에러 해결법 졸리운_곰 2018.08.02 52
» [mysql] Too many connection 문제 해결 졸리운_곰 2018.08.02 93
506 [mysql] too many connections 에러 이유와 해결방안 file 졸리운_곰 2018.08.02 62
대표 김성준 주소 : 경기 용인 분당수지 U타워 등록번호 : 142-07-27414
통신판매업 신고 : 제2012-용인수지-0185호 출판업 신고 : 수지구청 제 123호 개인정보보호최고책임자 : 김성준 sjkim70@stechstar.com
대표전화 : 010-4589-2193 [fax] 02-6280-1294 COPYRIGHT(C) stechstar.com ALL RIGHTS RESERVED