일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- Android
- xe
- WebView
- C# IO
- dovecot
- PHP
- curl
- 자동 생성
- javascript
- 안드로이드 gcm
- 안드로이드
- not working
- 안드로이드 푸시
- UML
- roundcube
- 설치
- C#
- chart.js
- 자바스크립트
- 우분투
- 폼메일
- php 시큐어코딩
- android 효과음
- 안드로이드 푸쉬
- Mail Server
- html5
- FCM
- php 취약점
- mysql
- soundpool
- Today
- Total
그러냐
MySQL 동시접속자 수(동접자수) 변경하기 - max_connection, wait_timeout 본문
출처 : https://m.blog.naver.com/fromyongsik/40158255209
Max connections 에러가 발생하면 페이지에 Too many connection가 나옵니다. 이는mysql에서 동시 연결 가능한 클라이언트 수를 넘었기 때문이다.
MySQL서버는 동시에 연결될 수 있는 클라이언트의 수가 기본으로 100명이다. 동시 접속자수를 변경하려면 my.cnf을 수정하고 MySQL서버를 재 시작하면 된다.
이런 에러의 원인으로는 다음과 같습니다.
1) mysql_connect()함수로 DB connect를 했다면 해당스크립트가 종료됨과 동시에 mysql_close()함수를 호출하지 않아도 자동으로 연결이 종료된다.
하지만, mysql_pconnect()함수는 해당스크립트가 종료된 후 mysql_close()함수가 호출되었더라도 연결이 끊어지지 않은 채로 계속 연결을 유지하고 있어서 금방 커넥션을 다 채울 수도 있다.
2) MySQL 의 메뉴얼을 보면 mysql_connect()함수를 사용하면 해당스크립트의 종료와 함께 연결이 종료된다고 되어 있지만 ./mysqladmin -u -p processlist라는 명령어를 통해서 살펴보면 그대로 살아 있음을 알 수 있다.
mysqladmin -u -p variables의 결과로서 볼 수 있는 여러 가지 시작 옵션들 중 wait_timeout의 값만큼 서버에 그대로 연결을 유지한 채로 남아 있는 것이다.
따라서, 이것이 too many connections의 직접적인 이유인 것이다.
그러므로 아래의 값을 조절하여 Max connections 에러를 막을 수 있다.
• max_connections - 최대 동시 접속 가능 수 기본값=100
• wait_timeout - 종료전까지 요청이 없이 기다리는 시간
[콘솔에서 커넥션수 알아내기]
$ mysqladmin -u root -p variables | grep max_connection
| max_connections | 100
[mysql에서 커넥션수 알아내기]
이제는, 클라이언트의 동시 접속자를 늘리는 명령이다. 먼저 mysql을 종료하고 아래와 같이 서버를 재가동한다.
#mysqld_safe --language=korean --datadir=/data --user=mysql --default-character-set=euc_kr -O max_connections=256 -O table_cache=128 -O wait_timeout=60 &
#mysqld_safe -O max_connections=256 -O table_cache=128 -O wait_timeout=60 &
MySQL 설정 파일(my.cnf or 윈도우의 경우는 my.ini) 에 직접 추가 한 다음 재실행을 하셔도 적용이 됩니다.
[mysqld]
max_connections = 500
wait_timeout = 60
MySQL에서 실행하는 방법
mysql> set global max_connections=500;
mysql> set wait_timeout=60;
이렇게 한 후 다시 확인한다.
[콘솔에서]
$ mysqladmin -u root -p variables | grep max_connection
$ mysqladmin -u root -p variables | grep wait_timeout
[mysql에서]
mysql> show variables like '%max_connection%';
mysql> show variables like 'wait_timeout';
[출처] MySQL max connections 설정|작성자 오라클
출처 - http://blog.naver.com/PostView.nhn?blogId=wiznux&logNo=60151893217
다음은 참고내용이다. 출처 - http://netholic.tistory.com/116
이번해 초부터 시작된 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 개수 //최대 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> 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 때 계산해보는 것이 중요...)
- > 설명
=============================================================================
문제 해결!!</li>
내 경우는 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 을 그때 그때 끊어주면서 접근하니까 아래 방법이 일단 더 낫다고 본다..
'mysql' 카테고리의 다른 글
HeidiSQL sql 쿼리 자동 생성 (0) | 2022.03.28 |
---|---|
MySQL 기본적인 모니터링 방법과 Connection과 Memory 튜닝 방법 (0) | 2021.12.13 |
ERROR 2006 (HY000): MySQL server has gone away Resolved 덤프 용량 에러 (0) | 2021.12.02 |
mysql 수동 설치시 에러 mysql_install_db 실행시 bash err등 (0) | 2021.08.02 |
MySQL 특정 DB 덤프 및 복구 (0) | 2021.07.28 |