상세 컨텐츠

본문 제목

mySQL 일반적인 문제 해결 방법

프로그래밍/DB

by 라제폰 2008. 12. 22. 17:49

본문

17. 일반적인 문제 해결 방법

17. 1. 데이터베이스 복사(복제?)

데이터베이스를 복사하는 가장 일반적인 방법은 업데이트 로그를 이용하는 것이다. 9.2 [Th
e update log] 참고. 이 경우 마스터로 작동하는 데이터베이스 하나(데이터가 변경된 곳)와
슬레이브로 작동하는 다른 하나의 데이터베이스가 필요하다. 슬레이브를 업데이트하려면 단
지 mysql < update_log을 하면 된다. 슬레이드 데이터베이스에 맞는 호스트, 유저, 패스워
드 옵션을 지정한다. 그리고 입력값으로 마스터 데이터베이스의 업데이트 로그를 사용한다.

테이블에서 삭제한 것이 없다면, 마지막으로 복사를 한 후 (마지막으로 복사한 시간을 비
교) 테이블에서 입력되거나 변경된 열을 찾아내기 위해 TIMESTAMP 컬럼을 사용할 수 있고
미러링되는 데이터베이스에 변경된 자료만 복사를 한다.

업데이트 로그(for deletes)와 timestamps(on both sides)를 같이 사용하여 두가지 방법으
로 업데이트하는 시스템을 만들 수 있다. 그러나 이런 경우 두가지 ends(?)에서 변경된 동
일한 데이터에서 충돌을 관리할 수 있어야 한다. 아마도 어떤 것이 업데이트되었는지 결정
하기 위해 예전 버전을 유지하고 싶을 것이다.

It is possible to make a two-way updating system using both the update log (for delet
es) and timestamps (on both sides). But in that case you must be able to handle confl
icts when the same data have been changed in both ends. You probably want to keep the
old version to help with deciding what has been updated.

이 경우 복사(복제)는 SQL문으로 이루어지기 때문에, 데이터베이스를 업데이트하는 문장에
서 다음의 함수를 사용해서는 안된다; 여기에서는 원본 데이터베이스와 동일한 값을 반환하
지 않을 수 있다:

     DATABASE()
     GET_LOCK() and RELEASE_LOCK()
     RAND()
     USER(), SYSTEM_USER() or SESSION_USER()
     VERSION()

timestamp는 필요한 경우에 미러되는 곳으로 보내기지 때문에 모든 time 함수는 안전하게
사용할 수 있다. LAST_INSERT_ID() 또한 안전하게 사용할 수 있다.

All time functions are safe to use, as the timestamp is sent to the mirror if needed.
LAST_INSERT_ID() is also safe to use.


17.2 데이터베이스 백업

mysql 테이블은 파일로 저장되기 때문에 백업하기가 쉽다.  일관된 백업 작업을 위해
관련된 테이블에 LOCK TABLES를 실행하자. 7.23 [LOCK TABLES/UNLOCK TABLES synta
x]를 참고. 단지 읽기 락만이 필요하다; 데이터베이스 디렉토리의 파일 복사본을 만드
는 동안에도 다른 스레드에서는 테이블에 질의를 계속 할 수 있다. SQL 레벨의 백업을
하고자 한다면 SELECT INTO OUTFILE을 사용할 수 있다.

데이터베이스를 백업하는 다른 방법은 mysqldump 프로그램을 사용하는 것이다:

데이터베이스에 대한 풀 백업 실행:
    
shell> mysqldump --tab=/path/to/some/dir --lock-tables --opt
    
     서버에서 업데이트를 하지 않는한 간단하게 모든 테이블 파일(`*.frm', `*.ISD' , `*.
     ISM' 파일)을 복사할 수 있다. mysqld가 실행되고 있으면 멈추어야 한다. 그러고나서
     --log-update 옵션으로 다시 시작하자. ''hostname.n'의 형식을 가진 로그 파일이 생
     성될 것이다. n은 mysqladmin refresh, mysqladmin flush-logs, the FLUSH LOGS 문,
     또는 서버를 재시작할때마다 증가하는 숫자이다. 이렇게 생긴 로그 파일을 이용해 mys
     qldump를 수행하고 나서 데이터베이스에 변화된 내용을 복사(복제)하는데 필요한 정보
     를 얻을 수 있다.
    
복원하고자 한다면, 먼저 isamchk -r을 사용해 테이블을 복구하자. 모든 경우 99.9%가 제대
로 수행된다. isamchk가 실패하면 다음의 과정대로 따르자:

       
     기존의 mysqldump 백업을 복원한다.
     업데이트 로그에서 업데이트를 다시 수행하기 위해 다음의 명령을 실행한다:
    
shell> ls -1 -t -r hostname.[0-9]* | xargs cat | mysql

ls는 정확한 순서대로 로그 파일을 가져오는데 사용된다.

또한 SELECT * INTO OUTFILE 'file_name' FROM tbl_name을 이용해 선택적인 백업을 할 수
있으며 레코드가 중복되는 것을 방지하기 위해  LOAD DATA INFILE 'file_name' REPLACE ... 
을 이용해 복원할 수 있다. 이경우에는 테이블에서 PRIMARY 키나 UNIQUE 키가 필요하다. RE
PLACE 키워드는 새로운 레코드에서 unique 키 값이 같은 이전의 레코드가 중복되는 경우 이
전의 레코드를 새로운 레코드로 교체한다.


17.3 같은 머신에서 여러개의 mysqld 서버 실행하기
같은 머신에서 다중의 서버를 사용하길 원할 수 있다. 예를 들어, 이전의 서버를 그대
로 두고 새로운 mysql 릴리즈를 테스팅하는 경우가 있을 수 있다. 또는 다른 고객들
에게 독립적인 mysql 설치를 제공하길 원하는 인터넷 서비스 제공자일 수 있다.

다중 서버를 사용하길 원하면, 가장 쉬운 방법은 다른 TCP/IP 포트와 소켓 파일로 서버를
컴파일해서 서버에서 동일한 TCP/IP 포트나 소켓 파일을 청취하지 않도록 할 수 있다.

이미 사용하고 있는 서버가 기본 포트와 소켓 파일로 구성되어 있다고 가정해보자. 그러면
다음과 같은 명령으로 새로운 서버를 설정하자:

shell> ./configure  --with-tcp-port=port_number \
             --with-unix-socket=file_name \
             --prefix=/usr/local/mysql-3.22.9

여기서 port_number와 file_name은 기본 포트 숫자 및 소켓 파일의 경로와는 달라야하며, -
-prefix 값은 현재 설치되어 있는 mysql과는 다른 디렉토리를 지정해야 한다.

Here port_number and file_name should be different than the default port number and s
ocket file pathname, and the --prefix value should specify an installation directory
different than the one under which the existing MySQL installation is located.

다음의 명령으로 현재 실행되고 있는 mysql 서버의 소켓과 파일을 확인할 수 있다:

shell>; mysqladmin -h hostname --port port_number variables

사용하고 있는 포트에서 실행되고 있는 mysql 서버가 있다면, 소켓 이름을 포함해 mysql의
가장 중요한 설정 변수의 목록을 알 수 있다. 다중 mysqld 서버를 시작하고 중지시키기 위
해 시스템의 초기화 스크립트(일반적으로 ''mysql.server')를 수정해야 한다.

다른 포트와 소켓으로 서버를 시작하기 위해 새로운 mysql 서버를 재컴파일할 필요는 없다.
safe_mysqld를 시작할 때 옵션으로 포트와 소켓을 지정할 수 있다:

shell>; /path/to/safe_mysqld --socket=file-name --port=file-name

동일한 데이터베이스 디렉토리에서 로그를 기록하도록 하면서 또 다른 서버를 실행하고자
한다면, safe_mysqld 에 --log 와 --log-update 를 이용해 로그 파일의 이름을 지정해 주어
야 한다. 그렇지 않으면 두 서버가 같은 로그 파일에 기록을 하려고 할 것이다.

주의 : 일반적으로 동일한 데이터베이스의 자료를 업데이트하는 두개의 서버를 사용해서는
안된다! 운영체제에서 fault-free 시스템 로킹(locking)을 지원하지 않는다면,  좋지 않은
결과를 보게 될 것이다. (** fault-free란 정확히 무엇인지 모르겠군요. 아마도 락을 거는
데 문제가 있다면 그 락을 해제하는 것으로 보입니다. **)

두번재 서버에서 다른 데이터베이스 디렉토리를 사용하기 원하면 safe_mysqld 에 --datadir
=path 옵션을 사용할 수 있다.

다른 포트에서 실행중인 mysql 서버에 접근하길 원한다면 다음의 방법을 사용할 수 있다:

        ㅇ 클라이언트에서 다음의 옵션을 가지고 시작. --host 'hostname'  --port=port-n
umer or [--host localhost] --socket=file-name.
        ㅇ C나 펄 프로그램에서 mysql 서버에 접속할 때 포트와 소켓 인자를 준다.
        ㅇ 클라이언트를 시작하기 전에 MYSQL_UNIX_PORT 와 MYSQL_TCP_PORT 환경 변수를
설정. 일반적으로 특정한 소켓이나 포트를 사용하면,  'login' 파일에 환경 변수를 설정하
자. 12.1 [Programs] 참고.
        ㅇ 홈 디렉토리에서 '.my.cnf' 파일에 기본 소켓과 TCP/IP 소켓을 지정.  4.15.4
[Option files] 참고.


관련글 더보기