글쓴이 : 권순선
MySQL이나 PgSQL을 아파치/PHP와 연동하여 사용할 때 db와 연결이 잘 되지 않는 경우가 종종 발생하며 사용자가 많지 않은데도 접속 에러가 뜨는 경우가 많이 있습니다.
이는 db 서버와 웹서버, 그리고 PHP의 설정 파라미터를 조정해 줌으로서 쉽게 해결할 수 있습니다. 점검해볼 항목은 다음과 같습니다.
PgSQL의 경우 /etc/postgresql/postgresql.conf 에 보면
max_connections = 64
와 같은 부분이 있습니다. 이는 PgSQL이 동시에 받아들일 수 있는 최대 접속 수입니다.
아파치 웹서버 설정 파일인 httpd.conf에는
MaxClients 90
과 같은 부분이 있습니다. 이는 아파치 웹서버가 동시에 처리할 수 있는 클라이언트의 숫자입니다.
PgSQL을 예로 들자면, php.ini에 다음과 같은 내용이 있습니다.
pgsql.allow_persistent = On
pgsql.max_persistent = 2 #max persistant links per process
pgsql.max_links = 16 # max pers/non-pers links per process
여기서 웹서버(PHP)가 PgSQL에 정의된 숫자보다 더 많은 접속을 시도할 경우 접속을 하지 못하고 에러가 발생하게 됩니다.
그러므로 MaxClients * pgsql.max_persistent < max_connections 가 되도록 설정값을 조정해 주어야 합니다.
지금 적힌 대로 시스템이 설정되어 있다면 90 * 2 > 64 이므로 위의 식을 만족하지 못하기 때문에 금방 db 커넥션 관련 에러가 발생하게 됩니다.
웹서버가 좀더 많은 사용자를 커버할 수 있도록 튜닝을 하더라도 위의 공식을 염두에 두고 튜닝을 해야 사용자가 얼마 없는 상황에서 db 접속을 하지 못하는 현상을 방지할 수 있습니다.
만약 위의 경우에서 웹서버와 db서버가 분리된 상태라면 각각의 MaxClients * pgsql.max_persistent 값을 더한 것이 db서버측의 max_connections를 넘지 않도록 튜닝해야 합니다.
MySQL의 경우 wait_timeout값을 매우 짧게 설정함으로서 idle 프로세스를 최대한 줄이는 방법도 있습니다만 db서버와 웹서버의 관계를 잘 고려하여 튜닝을 한다면 같은 하드웨어 사양으로도 좀더 효율적인 튜닝이 가능할 것입니다.
저도 이문제 때문에 한참을 고민하다가 postgresql 메일링 리스트에서 힌트를 얻었습니다. 위의 글은 PgSQL기준이지만 MySQL에서도 기본은 같으므로 따로 설명을 하지는 않겠습니다.
도움이 되었기를 바랍니다....
☞☞
Too many connections 에러가 발생할때
많은 분들이 max_connections 숫자를 늘리라고 하시는군요.
하지만 max_connections 을 100 에서 200으로 늘리는 만큼
MySQL 이 사용하는 메모리는 200M 이상 늘어나게 됩니다.
join_buffer, record_buffer, sort_buffer 등이 영향을 미치기 때문이죠.
(물론 실제 결과는 약간 차이가 있는 것 같습니다만...)
만약 MySQL이 물리적 메모리보다 많은 메모리를 사용하게 된다면
디스크 swap을 쓰게 되고, 결과적으로 퍼포먼스는 더 떨어지게 됩니다.
제 생각인데요.
대개의 경우 Too many connections 에러가 발생하는 원인은
동시접속이 과다하게 일어나기 때문이라기보다
MySQL 연결이 제대로 관리되지 않고 있기 때문입니다.
속도를 향상시키느라 mysql_pconnect 같은 함수를 쓰는데,
(하나의 DB계정을 사용하는 단독 서버의 경우는 문제가 안되겠지만)
호스팅을 하거나 여러 DB 계정으로 접속을 하는 경우에는
httpd 데몬이 이미 붙들고 있는 mysql 연결이 있으니까
기존 연결을 끊지 않고 자꾸 새로운 DB 연결을 생성하는 것이 아닌가 싶습니다.
제 경우는 우선 key_buffer 와 wait_timeout 시간을 줄였습니다.
(잘 모르지만, key buffer가 자꾸 커지는 문제가 있다고 하더군요.)
또 PHP에서 mysql_pconnect 대신 mysql_connect 를 사용하는 것으로 바꿔봤습니다.
(속도가 조금 떨어진다고 하나 별 문제는 안되니까요.)
이런 조치가 제대로 먹힐지는 내일이 되어봐야 알겠군요.
이 부분에 대해서 고수님들의 조언을 부탁드립니다.
(아, 그리고 back_log, thread_cache. thread_concurrency 등에 대해 설명한 자료가 있는 분은 좀 알려주시면 감사하겠습니다.)
쓰고 보니, 질문인지 팁인지 이상하게 되어버렸네요.
그럼, 진짜 팁... ^^;;
(다들 아시리라고 생각했는데, 아무런 언급이 없어서 늦게나마 씁니다.)
ADODB 같은 라이브러리를 보면
나름대로 DB 쿼리를 파일로 캐시한다든가 하는 등의 방법을 사용하고 있습니다만,
PHP에서도 자바처럼 DB connecion pool 같은 걸 쓸 수 있습니다.
SQLB (http://sqlb.sourceforge.net/) 또는
SQL_relay (http://www.firstworks.com/sqlrelay.html) 를 이용해보시기 바랍니다.
프비에는 sqlreplay 및 php-sqlrelay 포트도 있군요.
PHP에서 mysql_xxxx()함수 대신 accelsqlb() 또는 sqlrcon_xxxx() 함수를 사용하면 됩니다.
도움이 되셨기를...
MySQL이나 PgSQL을 아파치/PHP와 연동하여 사용할 때 db와 연결이 잘 되지 않는 경우가 종종 발생하며 사용자가 많지 않은데도 접속 에러가 뜨는 경우가 많이 있습니다.
이는 db 서버와 웹서버, 그리고 PHP의 설정 파라미터를 조정해 줌으로서 쉽게 해결할 수 있습니다. 점검해볼 항목은 다음과 같습니다.
PgSQL의 경우 /etc/postgresql/postgresql.conf 에 보면
max_connections = 64
와 같은 부분이 있습니다. 이는 PgSQL이 동시에 받아들일 수 있는 최대 접속 수입니다.
아파치 웹서버 설정 파일인 httpd.conf에는
MaxClients 90
과 같은 부분이 있습니다. 이는 아파치 웹서버가 동시에 처리할 수 있는 클라이언트의 숫자입니다.
PgSQL을 예로 들자면, php.ini에 다음과 같은 내용이 있습니다.
pgsql.allow_persistent = On
pgsql.max_persistent = 2 #max persistant links per process
pgsql.max_links = 16 # max pers/non-pers links per process
여기서 웹서버(PHP)가 PgSQL에 정의된 숫자보다 더 많은 접속을 시도할 경우 접속을 하지 못하고 에러가 발생하게 됩니다.
그러므로 MaxClients * pgsql.max_persistent < max_connections 가 되도록 설정값을 조정해 주어야 합니다.
지금 적힌 대로 시스템이 설정되어 있다면 90 * 2 > 64 이므로 위의 식을 만족하지 못하기 때문에 금방 db 커넥션 관련 에러가 발생하게 됩니다.
웹서버가 좀더 많은 사용자를 커버할 수 있도록 튜닝을 하더라도 위의 공식을 염두에 두고 튜닝을 해야 사용자가 얼마 없는 상황에서 db 접속을 하지 못하는 현상을 방지할 수 있습니다.
만약 위의 경우에서 웹서버와 db서버가 분리된 상태라면 각각의 MaxClients * pgsql.max_persistent 값을 더한 것이 db서버측의 max_connections를 넘지 않도록 튜닝해야 합니다.
MySQL의 경우 wait_timeout값을 매우 짧게 설정함으로서 idle 프로세스를 최대한 줄이는 방법도 있습니다만 db서버와 웹서버의 관계를 잘 고려하여 튜닝을 한다면 같은 하드웨어 사양으로도 좀더 효율적인 튜닝이 가능할 것입니다.
저도 이문제 때문에 한참을 고민하다가 postgresql 메일링 리스트에서 힌트를 얻었습니다. 위의 글은 PgSQL기준이지만 MySQL에서도 기본은 같으므로 따로 설명을 하지는 않겠습니다.
도움이 되었기를 바랍니다....
☞☞
Too many connections 에러가 발생할때
많은 분들이 max_connections 숫자를 늘리라고 하시는군요.
하지만 max_connections 을 100 에서 200으로 늘리는 만큼
MySQL 이 사용하는 메모리는 200M 이상 늘어나게 됩니다.
join_buffer, record_buffer, sort_buffer 등이 영향을 미치기 때문이죠.
(물론 실제 결과는 약간 차이가 있는 것 같습니다만...)
만약 MySQL이 물리적 메모리보다 많은 메모리를 사용하게 된다면
디스크 swap을 쓰게 되고, 결과적으로 퍼포먼스는 더 떨어지게 됩니다.
제 생각인데요.
대개의 경우 Too many connections 에러가 발생하는 원인은
동시접속이 과다하게 일어나기 때문이라기보다
MySQL 연결이 제대로 관리되지 않고 있기 때문입니다.
속도를 향상시키느라 mysql_pconnect 같은 함수를 쓰는데,
(하나의 DB계정을 사용하는 단독 서버의 경우는 문제가 안되겠지만)
호스팅을 하거나 여러 DB 계정으로 접속을 하는 경우에는
httpd 데몬이 이미 붙들고 있는 mysql 연결이 있으니까
기존 연결을 끊지 않고 자꾸 새로운 DB 연결을 생성하는 것이 아닌가 싶습니다.
제 경우는 우선 key_buffer 와 wait_timeout 시간을 줄였습니다.
(잘 모르지만, key buffer가 자꾸 커지는 문제가 있다고 하더군요.)
또 PHP에서 mysql_pconnect 대신 mysql_connect 를 사용하는 것으로 바꿔봤습니다.
(속도가 조금 떨어진다고 하나 별 문제는 안되니까요.)
이런 조치가 제대로 먹힐지는 내일이 되어봐야 알겠군요.
이 부분에 대해서 고수님들의 조언을 부탁드립니다.
(아, 그리고 back_log, thread_cache. thread_concurrency 등에 대해 설명한 자료가 있는 분은 좀 알려주시면 감사하겠습니다.)
쓰고 보니, 질문인지 팁인지 이상하게 되어버렸네요.
그럼, 진짜 팁... ^^;;
(다들 아시리라고 생각했는데, 아무런 언급이 없어서 늦게나마 씁니다.)
ADODB 같은 라이브러리를 보면
나름대로 DB 쿼리를 파일로 캐시한다든가 하는 등의 방법을 사용하고 있습니다만,
PHP에서도 자바처럼 DB connecion pool 같은 걸 쓸 수 있습니다.
SQLB (http://sqlb.sourceforge.net/) 또는
SQL_relay (http://www.firstworks.com/sqlrelay.html) 를 이용해보시기 바랍니다.
프비에는 sqlreplay 및 php-sqlrelay 포트도 있군요.
PHP에서 mysql_xxxx()함수 대신 accelsqlb() 또는 sqlrcon_xxxx() 함수를 사용하면 됩니다.
도움이 되셨기를...
댓글