MySQL Replication

MySQL 2005/07/04 10:25
1. Master 측 설정


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 를 참
고 하도록 한다.


2. SLAVE 측 설정

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 만
동기화를 하게 설정한 것이다.


3. 동기화 초기화 작업

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


4. Replication 확인

여기 까지의 작업이 완료 되었다면 이제 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]$



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


5. Replication Error 복구방법

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


6. Replication Error 유형

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 의 권한으로 생성이 되
는 경우가 있다. 이 경우 읽기 권한이 없어 위와 같은 에러가 발생하는 경우가 존재한다.
2005/07/04 10:25 2005/07/04 10:25

트랙백 주소 :: http://thinkit.or.kr/database/trackback/742