레이블이 mySQL인 게시물을 표시합니다. 모든 게시물 표시
레이블이 mySQL인 게시물을 표시합니다. 모든 게시물 표시

2015년 2월 3일 화요일

MySQL 5.5 Replication

MySQL 5.5 Replication



## Master : 계정 추가 ##

// Slave Server에서 Master Server에 접근할 수 있는 계정 필요
// user  rep_admin
// slave ip 192.168.0.20
// password  123456
mysql> grant replication slave on *.* to 'rep_admin'@'192.168.0.20' identified by '123456';
Query OK, 0 rows affected (0.00 sec)



## Master : DB 복사 ##

// Slave Server에 Master Server의 데이터를 백업한다.
// mysqldump등 이용… (알아서)



## Master : 설정 ##

// my.cnf 설정 
[root@master] # vi /etc/my.cnf
server-id       = 1 // 서버 식별 값
binlog-do-db    = database_name // 복제할 DB
binlog-ignore-db= database_name // 복제하지 않을 DB
log-bin         = mysql-master-bin // bin log file name


// my.cnf 재시작 및 확인 
[root@master] # service mysqld restart


// 마스터 상태 확인
mysql> show master status;
+-------------------------+----------+------------------------+-------------------------+
| File                    | Position | Binlog_Do_DB           | Binlog_Ignore_DB        |
+-------------------------+----------+------------------------+-------------------------+
| mysql-master-bin.000009 |      107 | backup_test,check_test | mysql,infomation_schema |
+-------------------------+----------+------------------------+-------------------------+
1 row in set (0.00 sec)



## Slave : DB 복제 ##

// Slave Server에 Master Server의 데이터를 복제한다.
// mysqldump등 이용… (알아서)



## Slave : 설정 ##

[root@slave etc]# service mysqld restart
mysqld 를 정지 중:                                         [  OK  ]
mysqld (을)를 시작 중:                                     [  OK  ]


[root@master] # vi /etc/my.cnf
server-id = 2
relay-log = slave-relay-bin

[root@slave etc]# service mysqld restart
mysqld 를 정지 중:                                         [  OK  ]
mysqld (을)를 시작 중:                                     [  OK  ]




mysql> stop slave;
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> change master to
    -> master_host='192.168.0.15',
    -> master_user='rep_admin',
    -> master_password='123456',
    -> master_log_file='mysql-master-bin.000009',
    -> master_log_pos=107;
Query OK, 0 rows affected (0.02 sec)


mysql> start slave;
Query OK, 0 rows affected (0.00 sec)

// 상태 확인
mysql> show slave status\G;
*************************** 1. row ***************************
               Slave_IO_State: Connecting to master
                  Master_Host: 192.168.0.15
                  Master_User: rep_admin
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-master-bin.000009
          Read_Master_Log_Pos: 107
               Relay_Log_File: slave-relay-bin.000001
                Relay_Log_Pos: 4
        Relay_Master_Log_File: mysql-master-bin.000009
             Slave_IO_Running: Connecting
            Slave_SQL_Running: Yes
              Replicate_Do_DB:
          Replicate_Ignore_DB:
           Replicate_Do_Table:
       Replicate_Ignore_Table:
      Replicate_Wild_Do_Table:
  Replicate_Wild_Ignore_Table:
                   Last_Errno: 0
                   Last_Error:
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 107
              Relay_Log_Space: 107
              Until_Condition: None
               Until_Log_File:
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File:
           Master_SSL_CA_Path:
              Master_SSL_Cert:
            Master_SSL_Cipher:
               Master_SSL_Key:
        Seconds_Behind_Master: NULL
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 1130
                Last_IO_Error: error connecting to master 'rep_admin@192.168.0.15:3306' - retry-time: 60  retries: 86400
               Last_SQL_Errno: 0
               Last_SQL_Error:
  Replicate_Ignore_Server_Ids:
             Master_Server_Id: 0
1 row in set (0.00 sec)

/* 

[참고] 끝에 \G를 하는 것과 하지 않은 것의 차이 

mysql> select now();
+---------------------+
| now()               |
+---------------------+
| 2015-01-20 23:04:16 |
+---------------------+
1 row in set (0.00 sec)


mysql> select now()\G;
*************************** 1. row ***************************
now(): 2015-01-20 23:04:24
1 row in set (0.00 sec)

*/

// 시작
mysql> start slave;



## Slave : 설정 초기화 ##

// MySQL 5.5부터 가능, 이전 버전에서는 stop slave; change to master master_host=‘';
mysql> stop slave; reset slave all; 
Query OK, 0 rows affected, 1 warning (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

// 초기화 상태 확인
mysql> show slave status\G;
Empty set (0.00 sec)




2015년 1월 15일 목요일

CentOS MySQL 업그레이드 5.1 to 5.5

- 버전 확인

[root@localhost ~]# cat /etc/redhat-release
CentOS release 6.6 (Final)


- 설치된 mysql 확인

[root@localhost ~]# yum list installed | grep -i mysql
MySQL-python.x86_64  1.2.3-0.3.c1.1.el6 @base
mysql.x86_64         5.1.73-3.el6_5     @base
mysql-libs.x86_64    5.1.73-3.el6_5     @base
mysql-server.x86_64  5.1.73-3.el6_5     @base
perl-DBD-MySQL.x86_64
php-mysql.x86_64     5.3.3-40.el6_6     @updates


- mysql 중지

[root@localhost ~]# service mysqld stop



- 백업

[root@localhost ~]# cp /etc/my.cnf /etc/my.cnf.5.1
[root@localhost ~]# cp -R /var/lib/mysql /var/lib/mysql.5.1 // 복구하는 경우 권한 주의


- reposiroey 추가

## 이미 추가 되어 있을 수 있다 ##
[root@localhost ~]# rpm -Uvh http://repo.webtatic.com/yum/centos/5/latest.rpm 

## Remi Dependency on CentOS 6 and Red Hat (RHEL) 6 ##
[root@localhost ~]# rpm -Uvh http://download.fedoraproject.org/pub/epel/6/i386/epel-release-6-8.noarch.rpm
 ## CentOS 6 and Red Hat (RHEL) 6 ##
[root@localhost ~]# rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-6.rpm


- mysql 제거

[root@localhost ~]# yum remove mysql mysql-*

. . . 

Removed:
  mysql.x86_64 0:5.1.73-3.el6_5               
  mysql-libs.x86_64 0:5.1.73-3.el6_5               
  mysql-server.x86_64 0:5.1.73-3.el6_5

Dependency Removed:
  MySQL-python.x86_64 0:1.2.3-0.3.c1.1.el6            
  perl-DBD-MySQL.x86_64 0:4.013-3.el6            
  php-mysql.x86_64 0:5.3.3-40.el6_6



- libmysqlclient16 설치

[root@localhost ~]# yum install libmysqlcliecnt16 --enablerepo=webtatic



- mysql 5.5 설치

[root@localhost ~]# yum install mysql mysql-server --enablerepo=remi


Installed:
  mysql.x86_64 0:5.5.41-1.el6.remi                           
  mysql-server.x86_64 0:5.5.41-1.el6.remi

Dependency Installed:
  compat-mysql51.x86_64 0:5.1.54-1.el6.remi    
  mysql-libs.x86_64 0:5.5.41-1.el6.remi    
  perl-DBD-MySQL.x86_64 0:4.013-3.el6



- mysql 5.1 삭제된 package 설치

[root@localhost ~]# yum install MySQL-python
[root@localhost ~]# yum install php-mysql



- mysql 시작 및 업그레이드

[root@localhost ~]# /etc/init.d/mysqld start
[root@localhost ~]# /usr/bin/mysql_upgrade -u root -p


- mysql 재 시작

[root@localhost ~]# service mysqld restart

MySQL (증분) 백업을 위한 XtraBackup 설치 및 사용

[comment]


가상 머신에서 테스트 실시 (Mac + Parallels(CPU 1, 메모리 1G, CentOS6.6 + MySQL 5.5)

dump 파일 약 1.1G를 DB에 import하는 경우 about 2분 38초 소요, DB를 export하는데 about 2분 소요
Xtrabackup을 이용한 백업 및 복원 각각 약 10~20초 소요
백업시간이나 복원 시간도 매우 우수

업무에 참고 바랍니다.



[설치]


## repository 추가 ##



## install ##

[root@localhost ~]# yum install xtrabackup


## 백업 디렉토리 생성 ##

[root@localhost ~]# mkdir /home/mysqlbackup/



[백업]

## timestamp 사용 ##

[root@localhost ~]# /usr/bin/innobackupex --user 사용자아이디 --password 비밀번호 /home/mysqlbackup


## 백업 확인 ##

[root@localhost ~]# ls -al /home/mysqlbackup/
합계 12
drwxr-xr-x  3 root root 4096 2015-01-14 23:14 .
drwxr-xr-x. 5 root root 4096 2015-01-14 23:12 ..
drwxr-xr-x  6 root root 4096 2015-01-14 23:14 2015-01-14_23-14-48


## 백업 (timestamp를 사용하지 않고 명시적으로 파일명 부여) ##

[root@localhost ~]# /usr/bin/innobackupex --user  사용자아이디  --password 비밀번호  --no-timestamp /home/mysqlbackup/full_backup


## 백업된 log sequence number (LSN) 확인 ##

[root@localhost ~]# cat /home/mysqlbackup/full_backup/xtrabackup_checkpoints
backup_type = full-backuped
from_lsn = 0
to_lsn = 1605114
last_lsn = 1605114
compact = 0


## 증분백업 (1차) ##
[root@localhost ~]# /usr/bin/innobackupex --user 사용자아이디 --password 비밀번호 --incremental --incremental-lsn=1605114 --no-timestamp /home/mysqlbackup/incremental_1606114


## 증분백업 LSN 확인 ##

[root@localhost mysqlbackup]# cat /home/mysqlbackup/incremental_1606114/xtrabackup_checkpoints
backup_type = incremental
from_lsn = 1605114
to_lsn = 1622319
last_lsn = 1622319
compact = 0


## 증분백업 (2차) ##

[root@localhost ~]# /usr/bin/innobackupex --user 사용자아이디  --password 비밀번호  --incremental --incremental-lsn=1622319 --no-timestamp /home/mysqlbackup/incremental_1622319



[복원]


/* 전체 백업한 것을 복원
 * 증분까지 복원하고 싶으면, 전체백업과 증분을 합한후 복원
 * 복원하는 경우 당연히 mysql 중지 및 만약을 위해 my.cnf의 datadir을 변경하여 복원
 */


## mysql중지 ##

[root@localhost ~]# service mysqld stop



## 복원용 디렉토리 생성 ##

[root@localhost ~]# mkdir /var/lib/mysql_restore


## my.cnf  수정 ##

[mysqld]
datadir=/var/lib/mysql_restore


## 전체백업 복원 ##

[root@localhost ~]# /usr/bin/innobackupex --apply-log /home/mysqlbackup/full_backup
[root@localhost ~]# /usr/bin/innobackupex --copy-back /home/mysqlbackup/full_backup


## 전체백업 확인 (복원된 디렉토리의 권한 확인 할것) ##

[root@localhost ~]# service mysqld start


## 증분백업 복원 ##
/* 전체 백업과 증북 합치기위 전체 백업을 --redo-ony 적용 */

[root@localhost ~]# /usr/bin/innobackupex --apply-log --redo-only /home/mysqlbackup/full_backup



## 증분한 순서대로 합치기 ##
# 합치면 전체 백업에 증분 백업이 포함된다. (증분 백업 파일은 필요 없다)

[root@localhost ~]# /usr/bin/innobackupex --apply-log --redo-only /home/mysqlbackup/full_backup -incremental-dir /home/mysqlbackup/incremental_1606114

[root@localhost ~]# /usr/bin/innobackupex --apply-log --redo-only /home/mysqlbackup/full_backup -incremental-dir /home/mysqlbackup/incremental_1622319



## 합친 전체 백업 LSN 확인 ##
[root@localhost mysql_restore]# cat /home/mysqlbackup/full_backup/xtrabackup_checkpoints
backup_type = full-prepared
from_lsn = 0
to_lsn = 1628142
last_lsn = 1628142
compact = 0


## 전체 백업 복원과 동일 ##

2009년 12월 23일 수요일

MySQL 트리거 미리 배우기


시험중인 새로운 기능을 이용할 수 있는 MySQL의 알파버전, MySQL 5.0은 트리거(Trigger)를 지원한다. MySQL 개발 로드맵에 약속된 기능이므로 놀라운 것은 아니지만, "MySQL은 할 수 없는 것들의 목록" 중에서 자주 언급되던 것을 사용하고, 동작하는 것을 지켜보는 것은 놀라운 경험이다.

이번 테스트를 위해 MySQL 레퍼런스 매뉴얼에서 개발 소스 트리에서 설치하기 절의 설명대로 가장 최신의 MySQL 5.0 소스를 다운로드하였다. 소스 트리에서 다운 받는 것은 MySQL 5.0 다운로드 페이지에서 받을 수 있는 것보다 최신판이며, 당연히 덜 테스트된 버전을 의미한다.

트리거 시험해보기

리눅스 쉘에서 mysql 클라이언트 프로그램을 실행했으며, 버전 5를 설치한 것이 맞는지 확인하기 위해 다음과 같은 코드를 작성하였다.

mysql> SELECT version();
+-------------------+
| version()         |
+-------------------+
| 5.0.2-alpha-debug |
+-------------------+
1 row in set (0.00 sec)

버전을 확인한 후에 테스트 데이터베이스에 테이블과 트리거를 차례대로 생성하고, 트리거를 테스트하기 위해 INSERT 문을 실행해보았다.

mysql> CREATE DATABASE test_db;
Query OK, 1 row affected (0.27 sec)
mysql> USE test_db;
Database changed
mysql> CREATE TABLE t (column1 TINYINT);
Query OK, 0 rows affected (0.28 sec)

mysql> CREATE TRIGGER t_bi              /* line 1 */
    -> BEFORE INSERT ON t               /* line 2 */
    -> FOR EACH ROW                     /* line 3 */
    -> SET @x = @x + 1;                 /* line 4 */
Query OK, 0 rows affected (0.00 sec)

mysql> SET @x = 0;                      /* line 5 */
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO t VALUES (1),(NULL); /* line 6 */
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> SELECT @x;                       /* line 7 */
+------+
| @x   |
+------+
| 2    |
+------+
1 row in set (0.01 sec)

위 예제에서 알 수 있는 것처럼 MySQL에서 트리거는 제대로 동작한다. 동작을 설명하기 위해 CREATE TRIGGER 문을 한번에 한줄씩 살펴보자.


트리거 이해하기

CREATE TRIGGER trigger_name            /* line 1 */

당연히 첫번째는 CREATE TRIGGER 문과 트리거의 이름이다. 나는 테이블 이름 다음에 언더스코어(_), 그 다음에 bi, ai, bu, au, bd, ad와 같은 코드를 사용하는 방식으로 트리거 이름을 지정한다. 6개의 코드는 다음과 같은 의미를 지닌다.

BEFORE INSERT ON table_name            /* line 2 */
or AFTER INSERT ON table_name
or BEFORE UPDATE ON table_name
or AFTER UPDATE ON table_name
or BEFORE DELETE ON table_name
or AFTER DELETE ON table_name

트리거가 동작할 수 있는 부분은 6곳이 있다. 트리거는 항상 테이블 하나에서 데이터 변경문이 발생할 때 동작하게 된다. 내가 작성한 BEFORE INSERT ON t 트리거는 테이블 t에 INSERT가 실행되기 전에 수행된다.

FOR EACH ROW                           /* line 3 */

위 문장은 내가 INSERT 문을 사용하는 각 열에 대해 동작하는 것을 지정한다. INSERT … SELECT 문을 사용하는 경우에 0개의 행이 삽입되는 경우가 발생한다면 트리거는 0번 동작하게 된다. 마찬가지로, 1,000개의 열을 삽입(INSERT)하게 되면 트리거도 1,000번 발생하게 된다. 표준 SQL 에서는 삽입되는 열의 수에 상관없이 트리거를 한번만 동작하게 하는 FOR EACH STATEMENT 문을 정의한다.

SET @x = @x + 1;                       /* line 4 */

마지막으로 살펴볼 것은 트리거의 "몸체"부분이다. 트리거가 동작하게 될 때 트리거 몸체 부분에 있는 문장이 실행된다. 예제의 트리거에서는 SET @x = @x + 1 문장이 실행된다. 이 코드는 트리거가 실행될 때마다 @x 변수를 증가시킨다.

다시 말해서, @x는 카운터다. 각 열에 INSERT가 발생할 때 마다 @x는 증가한다. 물론, @x의 기본값은 NULL이기 때문에 코드가 동작하기 않기 때문에 카운터를 초기화했다.

SET @x = 0;                            /* line 5 */

INSERT를 실행해서 트리거를 테스트할 차례다.

INSERT INTO t VALUES (1),(NULL);       /* line 6 */

테이블 t에 ROW EACH ROW 트리거를 두었기 때문에 열을 삽입할 때마다 @x의 값이 증가해야한다. 따라서 다음과 같은 SELECT 문을 실행하였을 때,

SELECT @x;                              /* line 7 */

열을 두 개 추가했으므로 결과도 2가 되어야 한다.


트리거 길들이기

앞으로 작성할 UPDATE 트리거는 ;를 포함한 여러 개의 문장으로 되어 있기 때문에 UPDATE 트리거를 작성하기 전에 mysql 클라이언트에서 문장의 끝을 나타내는 구분자를 //로 변경할 것이다.

mysql> DELIMITER //

이제 UPDATE 트리거를 작성할 차례다.

mysql> CREATE TRIGGER t_bu
    -> BEFORE UPDATE ON t
    -> FOR EACH ROW
    -> BEGIN
    ->   DECLARE CONTINUE HANDLER FOR 1264 SET new.column1 = -1;
    ->   SET new.column1 = new.column1 * 2;
    ->   END;//
Query OK, 0 rows affected (0.00 sec)

트리거 t_bu는 여러 개의 SQL 문장(compound statement)으로 되어 있으며, 각 열을 업데이트할 때마다 수행된다. 저장 프로시저에서 사용하는 복합문(compound statement)에 대한 구문은 MySQL 레퍼런스 매뉴얼을 참고하기 바란다. 위 트리거의 의미를 문장으로 옮기면 다음과 같다:

column1의 값에 2를 곱하고, 범위를 벗어남(out-of-range) 오류가 발생하면 column1의 값을 -1로 설정하라.

트리거의 몸체에는 MySQL 문장 및 함수들까지 모두 사용할 수 있으며, 뿐만 아니라, 해당 열의 이전 값을 "old"로, 새로운 값은 "new"로 참조할 수 있다.

에러가 발생할 때는 무엇을 할 수 있는가?

어떤 경우 에러가 발생할 수 있는가? 예를 들어, column1의 데이터 타입은 TINYINT이며, 이것의 최대값은 127이다. MySQL 5.0에서는 정상적인 동작환경에서는 타입에 대해 적절한 값이 들어가는지를 검사한다. 다음은 UPDATE 문은 "값의 범위를 벗어남(out of range value)" 오류를 고의로 만든다.

mysql> UPDATE t SET column1 = column1 + 100;//
Query OK, 1 row affected (0.00 sec)
Rows matched: 2 Changed: 1 Warnings: 1

테이블 t의 첫번째 열에 대해서 column1의 값이 1이고, 여기에 100을 더해서 101로 만들면 트리거가 이 값을 2배, 즉 202로 만든다. TINYINT 타입의 최대값은 127 이므로 예외 처리기가 동작하게 되며, column1의 값을 -1로 설정한다. 두번째 열에 있는 column1의 값은 NULL이므로 아무일도 발생하지 않는다. 이와 같은 동작이 테이블 t에 일어난 것을 증명하기 위해 테이블 t를 살펴보자.

mysql> SELECT * FROM t//
+---------+
| column1 |
+---------+
|      -1 |
|    NULL |
+---------+
2 rows in set (0.00 sec)


결론 및 주의할 점

INSERT와 UPDATE 문 양쪽에 대해 트리거가 동작하며, 트리거 몸체에는 복잡한 SQL 문장을 작성할 수 있다. BEFORE 트리거는 값을 삽입하거나 업데이트할 때 값을 읽고 변경할 수 있다. 이런 지원은 멋진 소식이다. 따라서, 여기서는 MySQL의 새로운 기능에 대해 주의할 점으로 끝을 맺겠다.

주의: MySQL 알파 버전은 불안정하다. MySQL 버그 데이터베이스(http://bugs.mysql.com/)에서 trigger* 키워드로 검색하고, 알려진 버그에 대해 주의해야 한다.

주의: MySQL 함수는 매우 엄격한 제약을 갖고 있다. 예를 들어, MySQL 함수는 테이블에서 SELECT를 수행할 수 없다. 트리거 동작은 함수 호출과 같이 동작하기 때문에 MySQL 함수와 같은 제약을 갖는다.