달력

072018  이전 다음

  • 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
  •  
  •  
  •  
  •  
[MySQL] mysqld_multi 사용법

- 작성자 : 김칠봉 <san2(at)linuxchannel.net>
- 작성일 : 2002.02.09(오타수정, 보완)
         : 2003.01.29
- 분 류  : mysql
- 수 준  : 초중급이상
- 내 용  : 하나의 서버에서 여러개의 mysqld 데몬을 띄우는 방법
- 키워드 : mysql, mysqld, mysqld_multi, safe_mysqld, mysqld_safe

*주1)
이 문서에 대한 최신 내용은 아래 URL에서 확인할 수 있습니다.

http://www.linuxchannel.net/docs/mysqld_multi.txt

*주2)
이 문서의 내용은 같은 하나의 MySQL 서버에서 여러개의 mysqld 데몬을
띄우는 방법에 대해서 설명합니다.
mysql 설치나 실제 실무에서 다루는 고차원적이고 상세한 기술적인
부분은 다루지 않습니다.

*주3)
`mysqld_multi` 프로그램은 MySQL 3.23.29 이상 버전용입니다.

reference :
- http://www.mysql.com/doc/en/mysqld_multi.html
- http://www.mysql.com/doc/en/Multiple_servers.html

---------------------------------------------------------
목차
1. mysqld multi 란?
2. 서로 다른 여러개의 mysqld를 띄우는 방법(기본)
3. mysqld_multi 을 이용하여 여러개의 mysqld 띄우는 방법
4. MySQL 3.23.x와 MySQL 4.0.x 을 동시에 구동하는 방법
5. 공유한 하나의 DB에 랜덤하게 접속하는 방법
6. 후기
---------------------------------------------------------

1. mysqld multi 란?

`mysqld_multi'라는 PERL 스크립트(3.23.29 이상)를 이용하여
같은 서버에서 여러개의 독자적인 mysqld를 운영하는 방법을 말합니다.

정확히 말해서, mysql 포트나 소켓을 서로 달리하여 여러개의 mysqld
프로세스를 띄워 운영하는 방법을 말합니다.

httpd에서 80, 8080 포트로 운영하는 것이나 또는 sendmail에서
daemonport를 서로 달리하여 운영하는 방법과 비슷한 원리입니다.


2. 서로 다른 여러개의 mysqld를 띄우는 방법(기본)

<주의>
이 절의 내용은 여러개의 mysqld 데몬을 띄우는 기본 사항에 대해서
다룹니다. 실제로 이렇게 운영할 수도 있지만 약간 불편하기 때문에
권장방법은 아닙니다.
</주의>

따로 mysql을 추가로 컴파일할 필요는 없습니다. 기존의 safe_mysqld
스크립트를 이용하면 됩니다.

이때 중요한 점은 반드시 최소한 pid-file, socket 위치를 서로 다르게
지정해야 합니다.

*반드시 다르게 설정해야할 옵션)

--pid-file=
--socket=
--port= or --skip-network

나머지 옵션은 mysql을 컴파일할때 기본값으로 사용하는 값을 따르거나
my.cnf 파일의 [mysqld] 섹션에 설정한 옵션을 따릅니다.

<팁> 외부 MySQL client에서 접속을 원천 봉쇄하려면?
mysql.host 테이블과 상관없이 아예 mysql 포트를 열지않도록
--skip-network 옵션을 주고 mysqld를 시작하면 됩니다.
(`netstat -atnp`로 확인).
</팁>

이하 설명은 외부 mysql client에서 접속해 오는 경우가 아닌 내부 client
에서 접속하는 경우로 가정하겠습니다.

만약 외부 mysql client(대부분 웹서버)에서 접속해야만 하는 경우라면
--skip-network 대신 --port=# 옵션으로 바꾸어야 합니다.


[첫번째 mysqld 구동]

shell> safe_mysqld &
or
shell> safe_mysqld --defaults-file=/root/.my.cnf &

[두번째 추가적인 mysqld 구동]

shell> safe_mysqld \
  --pid-file=/usr/local/mysql/var/`hostname`.pid2 \
  --socket=/tmp/mysql.sock2 \
  --skip-network & /*** or --port=3307 ***/
or
shell> safe_mysqld \
  --defaults-file=/root/.my.cnf \
  --pid-file=/usr/local/mysql/var/`hostname`.pid2 \
  --socket=/tmp/mysql.sock2 \
  --skip-network & /*** or --port=3307 ***/

두번째 mysqld에서 사용되는 나머지 옵션은 첫번째 mysqld의 기본 옵션을
그대로 따릅니다. 즉 basedir, datadir 와 같은 옵션을 따로 지정하지
않았기 때문에 어떤 값을 사용하는지를 알아보려면 다음과 같이 확인해
봅니다.

[기본적으로 사용되는 값 알아보기]

shell> /usr/local/mysql/libexec/mysqld --help
...
basedir:     /usr/local/mysql/
datadir:     /usr/local/mysql/var/
tmpdir:      /tmp/
language:    /usr/local/mysql/share/mysql/english/
pid file:    /usr/local/mysql/var/home.pid
TCP port:    3306
Unix socket: /tmp/mysql.sock
...
Possible variables for option --set-variable (-O) are:
back_log              current value: 50
binlog_cache_size     current value: 32768
connect_timeout       current value: 5
...


[두번째 mysqld에 접속해 보기]

현재 두번째 mysqld의 datadir 옵션이 없기 때문에 첫번째 mysqld의 datadir
와 같습니다. 즉 하나의 datadir를 공유한 셈이 됩니다.

*프로세스 확인)
shell> ps -ef --cols 400 | grep mysqld

*소켓 확인)
shell> ls /tmp/mysql.sock*
/tmp/mysql.sock  /tmp/mysql.sock2

*접속해 보기)
shell> mysql -u username -p -S /tmp/mysql.sock2 db_name

'-S'(또는 --socket) 옵션으로 두번째 mysqld의 소켓 위치를 입력해 주면
됩니다.


[두번째 mysqld 종료하기]

이와 같이 두번째, 세번째 mysqld를 구동하는 방법은 매번 옵션을 적어줘야
하는 불편함이 있습니다(또한 관리도 썩 매끄럽지 못하고).

일단 두번째 mysqld 구동에 성공하고 접속 테스트까지 끝냈다면 이제는
필요없으니 두번째 mysqld를 종료해 봅시다.

종료도 간단합니다. 단지 소켓 위치만 추가 옵션을 주면 됩니다.

shell> mysqladmin -u root -p -S /tmp/mysql.sock2 shutdown


3. mysqld_multi 을 이용하여 여러개의 mysqld 띄우는 방법

mysqld_multi 프로그램은 PERL로 짜여져 있으며, PREFIX/bin/mysqld_multi에
위치합니다. (MySQL 3.23.29 버전부터 추가되었군요.)

mysql.server 또는 safe_mysqld 스크립트는 기본적으로 /etc/my.cnf 또는
~/.my.cnf 또는 PREFIX/var/my.cnf 설정 파일에서 [mysqld] 섹션의 옵션 내용
을 읽어들여 mysqld 를 구동합니다.

<주의>
MySQL 4.0.x 버전은 safe_mysqld가 아니라 mysqld_safe으로 스크립트 이름이
변경되었습니다.
</주의>

이하 mysql 설정파일(my.cnf)은 /root/.my.cnf으로 통일합니다.

반면 mysqld_multi 스크립트는 [mysqld_multi], [mysqld1], [mysqld2], ...,
[mysqld] 의 섹션을 참고합니다.

정리하면,

  `safe_mysqld'  <-- [mysqld] <-- defaults options

  `mysqld_multi' <-- [mysqld_multi]
                       |-- [mysqld1] <-- ([mysqld]) <-- defaults options
                       |-- [mysqld2] <-- ([mysqld]) <-- defaults options
                       |-- [mysqld3] <-- ([mysqld]) <-- defaults options
                       `-- [mysqld#] <-- ([mysqld]) <-- defaults options

이와 같은 위계로 각 섹션을 참고하여 mysqld를 구동합니다.
(괄호안의 섹션은 그 섹션이 있다면 참고한다는 옵션입니다.)

mysqld_multi 를 사용하기 위해서 /root/.my.cnf 파일에 다음과 같이
추가해야 합니다(없다면 파일 생성).

shell> /usr/local/mysql/bin/mysqld_multi --example

하면 그 예제가 출력됩니다.

-- /root/.my.cnf 또는 /etc/my.cnf (수정전) ----------
[client]
password	= 안 갈쳐조오..
host		= localhost

[mysql]
ignore-spaces

[mysqld]
default-character-set = euc_kr
safe-show-database
skip-name-resolve
#port		= 3306
skip-network
log
#log-update
user		= mysql
set-variable 	= key_buffer=256M
set-variable 	= thread_cache_size=8
set-variable 	= table_cache=256

[myisamchk]
set-variable 	= key_buffer=100M
set-variable 	= sort_buffer=100M
set-variable 	= read_buffer=3M
set-variable 	= write_buffer=3M
#set-variable 	= sort_key_blocks=20
#set-variable 	= decode_bits=10

[mysqladmin]
#set-variable 	= connect_timeout=100
#set-variable 	= shutdown_timeout=1

[mysqldump]
user		= root
-----------------------------------------------------

-- /root/.my.cnf 또는 /etc/my.cnf (수정후) ----------
[client]
(생략)...

[mysql]
(생략)...

[mysqld]
default-character-set = euc_kr
skip-name-resolve
skip-network	## only localhost access
language	= /usr/local/mysql/share/mysql/english
(생략)...

[mysqld_multi]
mysqld		= /usr/local/mysql/bin/safe_mysqld
mysqladmin	= /usr/local/mysql/bin/mysqladmin
#user		= root

[mysqld1]
socket		= /tmp/mysql.sock1
#port		= 3307
pid-file	= /usr/local/mysql/var/mysqld1.pid
datadir		= /usr/local/mysql/var
log		= /usr/local/mysql/var/mysqld1.log
user		= mysql

[mysqld2]
socket		= /tmp/mysql.sock2
#port		= 3308
pid-file	= /usr/local/mysql/var2/mysqld2.pid
datadir		= /usr/local/mysql/var2
log		= /usr/local/mysql/var2/mysqld2.log
user		= mysql

[myisamchk]
(생략)...

[mysqladmin]
(생략)...

[mysqldump]
(생략)...
-----------------------------------------------------

앞의 설정에서 [mysqld1]은 datadir이 기존의 [mysqld] 섹션과 동일하므로
하나의 datadir을 공유하겠다는 의미입니다.

[mysqld2]의 datadir은 서로 다르므로 아주 독자적인 데이터베이스를 운영
하겠다는 의미입니다.

예) [mysqld2]용 datadir 만들기
shell> mkdir /usr/local/mysql/var2
shell> /usr/local/mysql/bin/mysql_install_db \
  --datadir=/usr/local/mysql/var2
shell> chown mysql.mysql -R /usr/local/mysql/var2

이와 같이 기본 mysql 데이터베이스를 만들어 주면 됩니다.

MySQL 영문 매뉴얼에 의하면 [mysqld_multi] 섹션에 multi_admin 유저를
다음과 같이 기존의 MySQL에 추가하여 관리하도록 하는 예제가 있습니다.

shell> mysql -u root -S /tmp/mysql.sock -proot_password -e \
  "GRANT SHUTDOWN ON *.* TO multi_admin@localhost \
  IDENTIFIED BY 'multipass'"

그러나 반드시 이와 같이 multi_admin 유저를 추가할 필요는 없고
기존의 root 유저를 이용하면 그만입니다.

<참고>
[mysqld1] 섹션에서 user는 해당 mysqld의 프로세스 유저를
의미합니다. /etc/passwd 파일에 존재한 다른 유저로도 설정가능합니다.
만약 하나의 유저에 대한 어떤 제한(ulimt)이 있다면 mysql 유저 대신
다른 유저를 /etc/passwd 파일에 추가하고 해당 유저를 사용하면 됩니다.
</참고>

그럼 두번째 [mysqld1], 세번째 [mysqld2] mysqld를 구동해 봅시다.

shell> /usr/local/mysql/bin/mysqld_multi --help
...
Usage: mysqld_multi [OPTIONS] {start|stop|report} [GNR,GNR,GNR...]
or     mysqld_multi [OPTIONS] {start|stop|report} [GNR-GNR,GNR,GNR-GNR,...]
..

GNR은 'Group NumbeR'를 의미하며 [mysqld#]에서 # 부분을 말합니다.
즉 정수 단위로 1부터 가능하며 GNR 옵션이 없다면 모든 GNR을 기본값으로
사용합니다.

*mysqld 구동하기)
shell> /usr/local/mysql/bin/mysqld_multi start
or
shell> /usr/local/mysql/bin/mysqld_multi start 1,2

*구동확인)
shell> /usr/local/mysql/bin/mysqld_multi report
Reporting MySQL servers
MySQL server from group: mysqld1 is running
MySQL server from group: mysqld2 is running

*두번째 mysqld에 접속하기
shell> mysql [OPTIONS] -S /tmp/mysql.sock1 db_name

*세번째 mysqld에 접속하기
shell> mysql [OPTIONS] -S /tmp/mysql.sock2 db_name

*두번째 mysqld 종료하기)
shell> /usr/local/mysql/bin/mysqld_multi stop 1

*두번째, 세번째 mysqld 종료하기)
shell> /usr/local/mysql/bin/mysqld_multi stop 1,2

*모든 mysqld multi 종료하기)
shell> /usr/local/mysql/bin/mysqld_multi stop
or
shell> /usr/local/mysql/bin/mysqld_multi stop 1,2

mysqld_multi는 safe_mysqld와 별개입니다. 어떤 옵션을 주고 구동하느냐에
따라서 두개가 서로 연계를 갖을 수 있지만 정확히 말하면 두개의 독립된 별개의
mysqld 입니다.

즉,

shell> safe_mysqld &
shell> mysqld_multi start
shell> mysqladmin shutdown
shell> mysqld_multi stop

이와 같이 별도로 각각 구별하여 시작/종료할 수 있습니다.

만약 이와 같이 각각 서로 구별하여 운영하고 싶지 않다면
기존의 safe_mysql의 [mysqld] 섹션을 mysqld_multi 용의 [mysqld1]으로
수정하여 기본 mysqld로 운영할 수 있습니다.

<참고> 부팅시 자동 시작하기(/etc/rc.d/rc.local)
/usr/local/mysql/bin/mysqld_multi \
  --defaults-file=/root/.my.cnf start
</참고>


4. MySQL 3.23.x와 MySQL 4.0.x 을 동시에 구동하는 방법

지금까지의 내용을 이해했다면 두개의 서로 다른 MySQL 버전을 구동하는
방법은 아주 쉽습니다.

  MySQL 3.23.x : /usr/local/mysql
  MySQL 4.0.x  : /usr/local/mysql4

에 각각 설치했다는 가정입니다.

<주의>
MySQL 4.0.x 버전은 safe_mysqld가 아니라 mysqld_safe으로 스크립트 이름이
변경되었습니다.
</주의>

-- /root/.my.cnf 또는 /etc/my.cnf ----------------
[client]
(생략)...

[mysql]
(생략)...

[mysqld]
(생략)...

[mysqld_multi]
mysqld		= /usr/local/mysql4/bin/mysqld_safe ## <-- 주의
mysqladmin	= /usr/local/mysql4/bin/mysqladmin
#user		= root

[mysqld1]
socket		= /tmp/mysql4.sock1
#port		= 3307
skip-name-resolve
skip-network	## only localhost access
default-character-set = euc_kr
pid-file	= /usr/local/mysql4/var/mysqld1.pid
datadir		= /usr/local/mysql4/var
language	= /usr/local/mysql4/share/mysql/english
log		= /usr/local/mysql4/var/mysqld1.log
user		= mysql

[myisamchk]
(생략)...

[mysqladmin]
(생략)...

[mysqldump]
(생략)...
-----------------------------------------------------

*MySQL 3.23.x 구동
shell> safe_mysqld &

*MySQL 4.0.x 구동
shell> mysqld_multi start

필자가 이 방법을 소개한 이유는 MySQL 4.0.x 버전으로 업그레이드할 경우
관리자가 조용하게(?) 테스트해 보아, 이상이 없다면 아무도 모르게(?)
조용하게 업그레이드할 수 있다는 점입니다.

물론 다음의 URL을 먼저 알아두어야 합니다.

  - http://www.mysql.com/doc/en/Upgrading-from-3.23.html


5. 공유한 하나의 DB에 랜덤하게 접속하는 방법

이 방법의 서로 다른 여러개의 mysqld 데몬의 datadir을 모두 동일하게
설정하여 운영하는 방법입니다.

여러개의 mysqld 데몬을 띄어야 하므로 시스템에 충분한 메모리가 있어야
합니다(512M 이상).

*권장 하는 경우)
1. 시스템 부하가 극도로 높지 않는 경우.
2. 하나(socket)의 mysqld로 시스템을 운영하기에는 자원이 남는 경우
3. 하나의 mysqld로 서비스가 포화 상태인 경우
4. 기타 테스트로 전보다 낫은 성능을 낼 경우


<주의>
필자가 테스트해 본 바로는 시스템 부하(CPU 사용량 95%이상)가 심한
경우, 좋은 대안이 될 수 없습니다(큰 효과가 없음).
(여러개의 mysqld 데몬을 띄우지 않아도 얼마든지 높은 퍼포먼스를
낼 수 있습니다)
다만, 이 방법은 여러가지 더 많은 테스트를 해보아, 전보다 좀더 낫은
성능을 낼 경우에만 사용하도록 하세요.
</주의>

-- /root/.my.cnf 또는 /etc/my.cnf ----------------
[client]
(생략)...

[mysql]
(생략)...

[mysqld]
default-character-set = euc_kr
skip-name-resolve
skip-network	## only localhost access
datadir		= /usr/local/mysql/var
language	= /usr/local/mysql/share/mysql/english
user		= mysql
(생략)...

[mysqld_multi]
mysqld		= /usr/local/mysql/bin/safe_mysqld
mysqladmin	= /usr/local/mysql/bin/mysqladmin
#user		= root

[mysqld1]
socket		= /tmp/mysql.sock1
#port		= 3307
pid-file	= /usr/local/mysql/var/mysqld1.pid
log		= /usr/local/mysql/var/mysqld1.log

[mysqld2]
socket		= /tmp/mysql.sock2
#port		= 3308
pid-file	= /usr/local/mysql/var/mysqld2.pid
log		= /usr/local/mysql/var/mysqld2.log

[mysqld3]
socket		= /tmp/mysql.sock3
#port		= 3309
pid-file	= /usr/local/mysql/var/mysqld3.pid
log		= /usr/local/mysql/var/mysqld3.log

[myisamchk]
(생략)...

[mysqladmin]
(생략)...

[mysqldump]
(생략)...
-----------------------------------------------------

앞의 설정을 요약하면 각 그룹 [mysqld#]는 datadir 옵션이 없으므로
[mysqld] 섹션의 datadir를 그대로 따릅니다.
즉 모두 같은 하나의 datadir을 공유하는 결과가 됩니다.

또한 log 옵션을 생략하면 기본 [mysqld] 섹션의 log 옵션을 따릅니다.
앞의 예제는 접속 확인을 알아보기 위해서 각각 다른 log 파일에 기록
하도록 했을 뿐입니다.

만약 하나의 유저로 모두 구동하고 싶지 않다면 각 [mysqld#] 섹션에
해당 user 옵션을 설정해 주면 됩니다.
(하나의 유저당 파일 제한수가 적을 경우)

shell> mysqld_multi start

이렇게 명령어를 내리면 추가로 3개의 각각 독립된 mysqld가 구동되며,
모두 동일한 하나의 datadir를 공유합니다.

만약 1, 2번 mysqld만 시작하도록 하고 싶다면

shell> mysqld_multi start 1,2

이렇게 추가 옵션을 주면 됩니다.

shell> mysqld_multi report

앞의 명령어로 3개 모두 구동하는지 확인해 보도록 하세요.

이제는 랜덤하게 1, 2, 3번에 접속하도록 socket 파일만 랜덤하게 선택해
주면 됩니다.

만약 PHP로 접근한다면(검색에만 적용),

----------------------------------------------------
<?php
##
## 검색모드에만 적용
if('검색모드인경우') {
  $sock = '/tmp/mysql.sock' . rand(1,3);
  ini_set('mysql.default_socket',$sock);
}

(생략: 나머지는 기존과 동일)

?>
----------------------------------------------------

이렇게 접속하는 기본 socket 파일 위치를 랜덤하게 만들어 주면 됩니다.

만약 각각 datadir이 서로 다르고 독자적으로 모두 별개의 MySQL 서비스를
한다면, 관리자 측면에서 다음과 같이 설정할 수 있습니다.

-- httpd.conf --------------------------------------
...
<VirtualHost xxxx>
  ...
  php_value mysql.default_socket "/tmp/mysql.sock1"
</VirtualHost>

<VirtualHost xxxx>
  ...
  php_value mysql.default_socket "/tmp/mysql.sock2"
</VirtualHost>

<VirtualHost xxxx>
  ...
  php_value mysql.default_socket "/tmp/mysql.sock3"
</VirtualHost>
----------------------------------------------------

or

-- DOCUMENT_ROOT/.htaccess -------------------------
...
php_value mysql.default_socket "/tmp/mysql.sock2"
----------------------------------------------------


6. 후기

(생략)


EOF
Posted by Tornado tornado