MySQL Replication

2007/02/04 15:55
MySQL Replication

아 드디어 내 홈에서 DB 에 관한 부분을 다루게 되었다. 하지만 DB 에 관한 설치 및 튜닝에 대
해서는 논하지는 않는다. 왜냐면 필자는  DB쪽에 지식이 별로 없기 때문이다. 만약 설치 및 튜
닝쪽에 관심이 있다면 http://database.sarang.net 으로 문의하기 바란다. 필자에게 질문을 하
더라도 답변 듣기 힘들테니까..

잡설은 그만두고 그럼 여기서는 우선 MySQL 의 3.23부터 지원이 되는 Replication 기능에 대해
서 논하고자 한다. Load Ballance 등의 장비나 또는 software 적인 방법을 통해 서버를 여러대
운영하다 보면 동기화 문제가 발생하게 된다. Replication 기능은 바로 이것처럼 DB server 를
여러대로 구동을 할때 각 DB서버의 동기화를 지원하기위한 기능으로 사용을 할 수가 있다. 즉,
입력 서버와 출력 서버를 분리해서 운영을 할 수가 있는 것이다.

일단 설정을 논하기 전에 주의 할 것은 MySQL 의 Replication 기능은 3.23버젼 부터 지원을 하
며 현재 MySQL 의 Replication 기능은 테스트 버젼 정도라고 인식을 하고 도입여부를 결정해야
한다는 점이다.





Replication 에서는 Master 와 Slave 라는 말을 사용하게 된다. Master 라는 말은 즉 능동적인
작업을 수행하는 측을 의미한다.  즉 실제로 업데이트가 발생하고, 동기화를 할 서버의 기준이
되는 서버를 의미한다.

일단, Replication 기능을 사용하기 위해서는 Replication 의 기능을 수행 할 유저가 필요하며
이 유저는 모든 DB 에 대해서 file 의 권한을 가지고 있어야 한다.

GRANT file ON *.* TO $repjob_user@'$slave_host_addr' IDENTIFIED BY '$passwd'

명령을 이용하여 file 에 대해서만 모든 DB 에 권한을 가지는 유저를 추가하도록 한다. 여기서
$repjob_user 는 중복되지 않는 유일한 아무 이름의 유저로 지정하면 되며,  $salve_host.addr
은 SLAVE server 로 만들 서버의 주소를 적어 줘야 한다. 그래야 SLAVE 에서 위에서 지정한 유
저로 MASTER server 에 접속이 가능하기 때문이다. 마지막의 $passwd 는 접속할 패스워드를 지
정하는 것이다.

다음 my.cnf 에 아래와 같이 Replication 기능을 위한 MASTER 설정을 한다.

Hanterm - cat /etc/my.cnf

 [root@bbuwoo /etc]$ cat my.cnf

  [mysqld]
  ....
  ....
  log-bin
  binlog-do-db    = test
  binlog-do-db    = test1
  server-id       = 1

 [root@bbuwoo /etc]$

log-bin 은 Replication 을 위한 binary log 를 남기게 한다.  server-id 는 Replication 기능
을 사용하는 서버중 유일값을 가져야 한다. server-id 는 1 에서 2^32-1 까지 지정할 수 있다.

binlog-do-db 는 Replication 을 사용할 database 를 지정한다. binlog-do-db = test,test1 과
같이는 사용이 안된다. 이유는 모르겠지만 하나에 하나씩 적어 줘야 한다. 만약 모든 database
를 동기화 하려한다면 binlog-do-db 를 설정을 안하면 된다. 만약 mysql DB 만 Replication 기
능을 사용하고 싶지 않다면 binlog-ignore-db 를 사용하면 된다.

my.cnf 에서 사용할 수 있는 MASTER 에 관한 옵션은 다음과 같다

log-bin=filename

Replication 기능에 필요한 binary log 를 남기게 한다.  filename 을 지정하지 않을 경우에는
mysql 의 lib directory 에 $host-bin.001 과 같이 남게 된다.  RPM으로 설치했을 경우에는 보
통 /var/lib/rpm 에 남게되며, prefix 를 지정하지 않은 채 소스 컴파일을 했을 경우에는 보통
/usr/local/mysql/lib/ 에 남게 된다.

log-bin-index=filename

binary file 의 index 파일을 생성한다. 지정하지 않으면 $host-bin.index 로 남게 된다. 지정
하나 하지 않으나 별 상관은 없다.

sql-bin-update-same

If set, setting SQL_LOG_BIN to a value will automatically set SQL_LOG_UPDATE to the same
value and vice versa. 

binlog-do-db=database_name

MASTER 의 여러 DB 중 Replication 기능으로 동기화를 할 Database를 선택한다. 이것이 지정이
되어 있으면 지정되지 않은 Database 들은 동기화에서 빠진다.

binlog-ignore-db=database_name

MASTER 의 여러 DB 중 Replication 기능으로 동기화를 하지 않을  Database 를 선택한다. 이것
이 지정이 되어 있으면 지정되지 않은 Database 들만 동기화를 한다. 만약 binlog-do-db 가 설
정이 되어 있을 경우 에는 binlog-do-db 를 먼저 적용하고나서 binlog-ignore-db 를 적용한다.

좀 더 자세한것을 알고 싶다면 http://www.mysql.com/doc/R/e/Replication_Options.html 를 참
고 하도록 한다.




SLAVE 측의 설정에서는 별다른 유저 추가가 필요 없으며 MASTER 측의 추가한 유저 정보를 이용
하여 my.cnf 에서 SLAVE 설정만 해 주는 것으로 설정이 끝난다.

Hanterm - cat /etc/my.cnf

 [root@bbuwoo /etc]$ cat my.cnf

  [mysqld]
  ....
  ....
  server-id       = 2
  master-host     = mater_ipaddres
  master-user     = $repjob_user
  master-password = $passwd
  replicate-do-db = test
  master-port     = 3306

 [root@bbuwoo /etc]$

server-id 는 역시 유일값 이어야 한다. MASTER 에서 1 을 사용했으니 SLAVE 에서는 2 를 사용
한다.

master-host 는 MASTER server 의 ip address 를 지정해 준다. master-user 는 Replication 작
업을 할 유저를 지정한다. 위의 MASTER 에서 등록해 준 유저를 적도록 한다.

master-passwd 는 Replication 작업을 할 유저의 패스워드를 지정한다.

master-port 는 MASTER server 가 사용하는 포트를 지정한다. 기본값으로 3306 이다.

만약 MASTER server 의 특정 DB만 Replication 기능을 사용하고 싶다면 replicate-do-db 를 이
용한다.  하지만 이 기능은 MASTER 에서 binlog-ignore-db 로 제한을 하고 있다면 적용이 되지
않는다. 즉 SLAVE level 에서는 MASTER 가 허락 하는 database 중에서 선택을 할 수 있을 뿐이
다. SLAVE 에서 사용할 수 있는 옵션들은

http://www.mysql.com/doc/R/e/Replication_Options.html

를 참고 하도록 한다.

위의 작업을 간단히 설명을 하자면 MASTER 에서는 Replication 을 위한 유저에게 file 에 대해
서는 모든 권한을 준 상태로 추가 했으며, test, test1 database 에 대해서 Replication 을 하
도록 설정을 한 것이다.  SLAVE 에서는 replicate-do-db 가 설정이 되어 있으므로 test1 DB 만
동기화를 하게 설정한 것이다.




MASTER 와 SLAVE 의 설정을 마쳤으면 Replication 기능을 사용하기 전에 두대간의 동기화 작업
을 먼저 해 놓아야 한다. 먼저 동기화 할 database 를 SLAVE 로 옮긴다. (만약 MASTER 에서 아
무것도 없는 상태에서 시작한다면 이 작업은 필요없다. MASTER에서 운영중인 것을 Replication
기능을 이용하여 동기화 하기 위해 필요한 작업이다.)  위에서는 test1 DB 만 동기화를 하도록
설정을 했으니 MASTER 의 test1 DB를 압축해서 SLAVE 로 옮긴다 (mysql 의 경우에는 data file
만 옮겨도 그냥 적용을 할 수 있다.)

master) cd /var/lib/mysql
master) tar cvfpz test1.tgz test1
master) chmod 777 test1.tgz

slave) cd /var/lib/mysql
slave) ncftp -u user master_server
slave) (Afer login) cd /var/lib/mysql
slave) get test1.tgz
slave) delete test1.tgz (ftp 상의 파일을 삭제)
slave) quit (ftp logout)
slave) tar xvfpz test1.tgz
slave) chown -R mysql.mysql test1




여기 까지의 작업이 완료 되었다면 이제 MASTER 와 SLAVE 의 mysql 을 구동하고 다음을 확인한
다. 여기서의 결과값은 3.23.42 를 기준으로 한다. 버젼 마다 결과값이 다른 형태로 나올 수가
있다.


MASTER Server
Hanterm - mysql -e "show process"

 [root@bbuwoo /etc]$ /etc/rc.d/init.d/mysql restart

  Shutting down MySQL:                                       [  OK  ]
  Starting MySQL:                                            [  OK  ]

 [root@bbuwoo /etc]$ mysql -uroot -p -e "show processlist"

  +----+-------+--------+------+-------------+------+
  | Id | User  | Host   | db   | Command     | Time |
  +----+-------+--------+------+-------------+------+
  |  7 | $user | $slave | NULL | Binlog Dump | 2865 |
  +----+-------+--------+------+-------------+------+
  +---------------------------------------------+------+ 
  | State                                       | Info | 
  +---------------------------------------------+------+ 
  | Slave connection: waiting for binlog update | NULL | 
  +---------------------------------------------+------+ 

 [root@bbuwoo /etc]$ mysql -uroot -p -e "show master status"

  +---------------+----------+------------------+------------------+
  | File          | Position | Binlog_do_db     | Binlog_ignore_db |
  +---------------+----------+------------------+------------------+
  | $host-bin.001 | 729      | test,test1       |                  |
  +---------------+----------+------------------+------------------+

 [root@bbuwoo /etc]$

SLAVE Server
Hanterm - mysql -e "show process"

 [root@bbuwoo /etc]$ /etc/rc.d/init.d/mysql restart

  Shutting down MySQL:                                       [  OK  ]
  Starting MySQL:                                            [  OK  ]

 [root@bbuwoo /etc]$ mysql -uroot -p -e "show processlist"

  +----+-------------+------+------+---------+------+-----------------------+------+
  | Id | User        | Host | db   | Command | Time | State                 | Info |
  +----+-------------+------+------+---------+------+-----------------------+------+
  |  1 | system user | none | NULL | Connect | 2847 | Reading master update | NULL |
  +----+-------------+------+------+---------+------+-----------------------+------+

 [root@bbuwoo /etc]$ mysql -uroot -p -e "show slave status"

  +-------------+-------------+-------------+---------------+---------------+-----+
  | Master_Host | Master_User | Master_Port | Connect_retry | Log_File      | Pos |
  +-------------+-------------+-------------+---------------+---------------+-----+
  | $master_ip  | $rejob_user | 3306        | 60            | $host-bin.001 | 729 |
  +-------------+-------------+-------------+---------------+---------------+-----+
  +---------------+-----------------+---------------------+------------+
  | Slave_Running | Replicate_do_db | Replicate_ignore_db | Last_errno |
  +---------------+-----------------+---------------------+------------+
  | Yes           | test            |                     | 0          |
  +---------------+-----------------+---------------------+------------+
  +------------+--------------+
  | Last_error | Skip_counter |
  +------------+--------------+
  |            | 0            |
  +------------+--------------+

 [root@bbuwoo /etc]$

와 같이 나와 있음을 확인하면 된다.




Replication 이 잘 되다가 갑자기 slave 에서 master 가 반영이 되어 있지 않을 경우 slave 의
error log 를 보도록 한다. error log 를 보고 문제점을 fix 한 다음

shell> mysqladmin -uroot -p slave-start

명령을 실행하면 반영되지 않았던 master 의 자료가 하나씩 반영되는 것을 볼 수 있을 것이다.

또 한가지 주의할 점은 replication 을 구현할때 master 에서 

mysql> create database DB명;

명령은 slave 에 반영이 되지를 않는다. 그러므로 slave 의 설정에

replicate-do-db = DB명

을 명확하게 밝혀 놓아야지 에러가 발생하는 것을 막을 수 있다. 그럼 Master 에서 DB 를 추가
할 때는 귀찮더라도 slave 에서 수동으로 create database 를 한 다음 추가된 db 를 my.cnf 에
서 replicate-do-db 를 설정한 다음 slave 를 재시작 하는 것을 권장한다.

database 추가가 반영이 되지 않는 것은 필자가 그 방법을 찾지 못한 것인지 아니면 원래 구현
이 안되어 있는 것인지를 모르겠다. 혹시 아는 사람이 있으면 필자에게 포스팅을 해 주면 감사
하겠다.




  mysql> show processlist;

  +----+-------------+------+------+---------+------+-----------------------+------+
  | Id | User        | Host | db   | Command | Time | State                 | Info |
  +----+-------------+------+------+---------+------+-----------------------+------+
  |  1 | system user | none | NULL | Connect | 2847 | Waiting to reconnect  | NULL |
  |    |             |      |      |         |      | after a failed read   |      |
  +----+-------------+------+------+---------+------+-----------------------+------+
  2 rows in set (0.00 sec)

  mysql> show slave status;
  +-------------+-------------+-------------+---------------+---------------+-----+
  | Master_Host | Master_User | Master_Port | Connect_retry | Log_File      | Pos |
  +-------------+-------------+-------------+---------------+---------------+-----+
  | $master_ip  | $rejob_user | 3306        | 60            | $host-bin.101 | 729 |
  +-------------+-------------+-------------+---------------+---------------+-----+
  +---------------+-----------------+---------------------+------------+
  | Slave_Running | Replicate_do_db | Replicate_ignore_db | Last_errno |
  +---------------+-----------------+---------------------+------------+
  | Yes           | test            |                     | 0          |
  +---------------+-----------------+---------------------+------------+
  +------------+--------------+
  | Last_error | Skip_counter |
  +------------+--------------+
  |            | 0            |
  +------------+--------------+

이 경우를 보도록 하자.  processlist 에서는 읽기 실패후에 재접속을 기다리고 있다고 상황을
출력하고 있고, slave status 에서는 host-bin.101 에서 멈춰있다. 그리고 master 에서는 로그
파일이 host-bin.130 번을 생성하고 있을 경우이다. 즉 로그 101 에서 slave 는 멈춰진 상태이
다. 그리고 slave 의 에러로그 파일에는 다음과 같은 내용이 있다.

020312 17:52:37  Error reading packet from server: Could not open log file
                 (read_errno 0,server_errno=13)
020312 17:53:37  Slave: Failed reading log event, reconnecting to retry, log
                        '$host-bin.101' position 729
020312 17:53:37  Slave: reconnected to master '$rejob_user@$master_ip:3306',
                        replication resumed in log '$host-bin.101' at position 729

이런 경우에는, master 의 바이너리 로그 파일의 소유권을 잘 살펴보기 바란다. 보통 mysql 은
mysql 유저로서 구동을 하는 경우가 많은데 이때 로그파일이 간혹 root 의 권한으로 생성이 되
는 경우가 있다. 이 경우 읽기 권한이 없어 위와 같은 에러가 발생하는 경우가 존재한다.
2007/02/04 15:55 2007/02/04 15:55
Posted by 비온뒤하늘

트랙백 보낼 주소 : 이 글에는 트랙백을 보낼 수 없습니다

댓글을 달아주세요

<< PREV : [1] : ... [16] : [17] : [18] : [19] : [20] : [21] : [22] : [23] : [24] : ... [29] : NEXT >>

BLOG main image
마음을 열고 나의 생각을 넣고 나의 미래를 넣고 나의 하루를 넣는다. by 비온뒤하늘

공지사항

카테고리

전체 (29)
태중 세상 보기 (7)
apple (3)
내가 읽은 책들 (0)
리눅스 (9)
나의성공 (6)
태양광 (2)

최근에 받은 트랙백

태그목록

글 보관함

달력

«   2012/02   »
      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      
Total : 20496
Today : 19 Yesterday : 18