MySQL이 Oracle 에 인수될 즈음부터 MySQL을 기반으로 하면서 보다 향상된 개념으로 각자가 이름을 떨치며 꾸준히 진행되어 온 프로젝트가 바로 Percona와 MariaDB이다. 참고로 두 프로젝트의 연관성을 비교하는 내용은 이 곳의 포스팅을 보시면 되겠고, 이번 포스팅에서는 Codership이 만든 Synchronous Multimaster 방식의 Galera cluster 를 설치해 보고, 운영에 관련해서 고려할 점들을 정리해 두려 한다.


Multimaster, Synchronous 한 특징을 가지는 이러한 MM 솔루션이 나오기 전에는(물론 완성도가 떨어지고 운영상 불편했던 MMM 같은 것도 있기는 했다), Master-Slave 구조의 비동기 Replication 방식이 많이 쓰였다. 한 편으로는 Semi-sync(Master는 변경 사항을 Slave 로 전달하는 것 까지만 책임을 진다)라는 장점을 가지기는 했지만 태생적으로 비동기식에서 벗어날 수 없기에, 만약의 상황에서 데이터 손실을 감수해야 하는 한계를 지녔었다고 볼 수 있겠다.


다뤄 나가고자 하는 내용을 간단히 요약하면 다음과 같다


* MariaDB Galera Cluster 설치 및 설정 과정

* 노드의 추가(확장)과 Maintenance를 위한 제거 등 운영 방법



1. MariaDB Galera Cluster 설치 및 설정 과정


설치 방법은 소스 빌드, 바이너리 다운로드&설치, rpm 설치 등 여러 가지가 있지만, 여기서는 mariadb.org 에서 권고하는 distro별 링크를 통해 단계를 밟아 나가는 내용을 그대로 따르면서 진행해 보자.


본 글에서 선택한 설치, 운영 환경: Ubuntu 14.04 Trusty, MariaDB 10, Kaist archive


* 설치 & 테스트를 진행할 3개의 Ubuntu 14.4 머신을 준비한다

 - ubuntu14-pv1, 10.0.10.1

 - ubuntu14-pv2, 10.0.10.2

 - ubuntu14-pv3, 10.0.10.3

* Local network이 아닌 외부 망을 통하여 노드간 원격 접속이 필요한 경우(AWS AZ 도 포함) 또는 서버 자체 방화벽(ufw 등) 이 설정되어 있을 때는, 방화벽 설정에서 TCP 3306/4568/4444 port와 TCP, UDP 4567 을 개방해야 한다(☞참조)



첫 번째 Cluster, Doner 노드의 설치와 기동


* 대다수 작업이 root 권한을 필요로 하므로 super user 로 로그인하여 진행한다

* 설치 과정에서 mysql 관리자 계정인 root 암호를 2번 입력(여기서는 편의상 maria 로 정한다)

* 첫 번째로 설정되어 기동되는 MariaDB 머신 도너(Doner) 노드라고 부르며, 다음과 같이 설정

* 여러 머신간의 데이터 동기화가 중요한 환경에서는, DB 데몬이 머신 부팅 후 자동 실행되는 방식을 피하는 것이 바람직

ubuntu@ubuntu14-pv1:~$ su -

root@ubuntu14-pv1:~# apt-get install software-properties-common

root@ubuntu14-pv1:~# apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0xcbcb082a1bb943db

root@ubuntu14-pv1:~# add-apt-repository 'deb http://ftp.kaist.ac.kr/mariadb/repo/10.0/ubuntu trusty main'

root@ubuntu14-pv1:~# apt-get update

root@ubuntu14-pv1:~# apt-get install mariadb-galera-server

root@ubuntu14-pv1:~# mysql_secure_installation

root@ubuntu14-pv1:~# mysql -uroot -pmaria

MariaDB [(none)]> grant all on *.* to 'root'@'%' identified by 'maria';

MariaDB [(none)]> grant usage on *.* to sst_user@'%' identified by 'maria';

MariaDB [(none)]> grant all privileges on *.* to sst_user@'%';

MariaDB [(none)]> flush privileges;

MariaDB [(none)]> quit

root@ubuntu14-pv1:~# service mysql stop

root@ubuntu14-pv1:~# apt-get install sysv-rc-conf <== mysqld 의 자동 실행을 중지하기 위함

root@ubuntu14-pv1:~# sysv-rc-conf <== runlevel 2~5 에 대해 space 를 눌러서 해제


* 복제 방법으로 Percona 의 xtrabackup 을 사용하기 위함(rsync 를 선택할 경우 설치하지 않아도 됨)

* 이 경우 데이터스트림 전송을 위한 다용도 relay 솔루션인 socat은 꼭 설치해야 함

root@ubuntu14-pv1:~# apt-get install xtrabackup socat


* 중요 설정, 고유 입력 항목은 붉은 글씨로 표시

* wsrep_node_address 에는 머신 자체 ip 를 등록

* 초기 설정시에는 wsrep_cluster_address에 머신 자체 ip 만 등록

* wsrep_sst_receive_address 에는 자체 ip:4569 를 등록

root@ubuntu14-pv1:~# vi /etc/mysql/conf.d/mariadb.cnf

# MariaDB-specific config file.

# Read by /etc/mysql/my.cnf


[client]

default-character-set = utf8

 

[mysqld]

character-set-server = utf8

collation-server = utf8_general_ci

character_set_server = utf8

collation_server = utf8_general_ci

 

autocommit = 0


# Load Galera Cluster

wsrep_provider = /usr/lib/galera/libgalera_smm.so

wsrep_cluster_name='galera_cluster'

wsrep_retry_autocommit = 0

wsrep_sst_auth=sst_user:maria

#wsrep_sst_method = rsync

wsrep_sst_method = xtrabackup

wsrep_provider_options = "evs.keepalive_period = PT3S; evs.suspect_timeout = PT30S; evs.inactive_timeout = PT1M; evs.install_timeout = PT1M"

 

# Galera Node Option

wsrep_node_name='galera1'

wsrep_node_address='10.0.10.1'

wsrep_cluster_address = 'gcomm://10.0.10.1'

wsrep_sst_receive_address=10.0.10.1:4569

 

# Other mysqld options

default-storage-engine=innodb

binlog_format = ROW

innodb_autoinc_lock_mode = 2

innodb_flush_log_at_trx_commit = 2

innodb_locks_unsafe_for_binlog = 1

innodb_log_file_size=100M

innodb_file_per_table

query_cache_size=0

query_cache_type=0

bind-address=0.0.0.0

datadir=/var/lib/mysql

tmpdir=/tmp

user=mysql

log-error=/var/log/mysql/mysql.err


* Cluster 내에서 최초로 기동되는 MariaDB doner 노드이기에 --wsrep-new-cluster 옵션으로 시작

* [주의] Checking for corrupt, not cleanly closed... 메시지는 DB가 정상 기동 되었음을 의미함

root@ubuntu14-pv1:~# service mysql start --wsrep-new_cluster

 * Starting MariaDB database server mysqld                               [ OK ] 

 * Checking for corrupt, not cleanly closed and upgrade needing tables.


여기까지가 Doner 노드 설정 과정이다.


* 데이터베이스가 정상 작동하는지 간단히 테스트해 보고, 다음 Cluster 확장 단계로 넘어가자

root@ubuntu14-pv1:~# mysql -uroot -pmaria

MariaDB [(none)]> create database cluster_test;

MariaDB [(none)]> use cluster_test;

Reading table information for completion of table and column names

You can turn off this feature to get a quicker startup with -A


Database changed

MariaDB [cluster_test]> create table tbl1 (id varchar(20));

Query OK, 0 rows affected (0.25 sec)

MariaDB [cluster_test]> insert into tbl1 values ('abcdefg');

Query OK, 1 row affected (0.00 sec)

MariaDB [cluster_test]> commit;

Query OK, 0 rows affected (0.00 sec)



2. 운영 요령: 노드의 추가(확장)과 머신 점검을 위한 제거 등


앞의 단계는 Cluster 에 1개의 머신만 등록한 상태이다. 이번에는 Cluster 내에 2개의 머신을 더 추가하여, Galera Cluster 에서 권장하는 최소 홀수 개인 3개를 완성하는 과정과 Failover 및 자동 복구, Cluster 내에서 노드의 제거(머신 점검 등의 상황일 때)와 재투입 과정에 대해서 정리해 보자.


Cluster 의 두 번째 노드, 첫 Joiner 노드의 추가


* 앞의 Doner 노드 설정 과정과 거의 동일하며, config(maria.cnf) 의 일부 내용과 기동 방법이 다르다


* wsrep_node_address 에는 머신 자체의 ip 를 등록

* wsrep_cluster_address 에 기존의 Doner 노드와 Joiner 노드 ip 를 등록

* wsrep_sst_receive_address 에는 자체 ip:4569 를 등록

root@ubuntu14-pv2:~# scp root@10.0.10.1:/etc/mysql/conf.d/mariadb.cnf /etc/mysql/conf.d/

root@ubuntu14-pv2:~# vi /etc/mysql/conf.d/mariadb.cnf

# MariaDB-specific config file.

...

# Galera Node Option

wsrep_node_name='galera2'

wsrep_node_address='10.0.10.2'

wsrep_cluster_address = 'gcomm://10.0.10.1,10.0.10.2'

wsrep_sst_receive_address=10.0.10.2:4569

...


* Debian, Ubuntu 계열의 경우 특별히 신경 써서 작업해 주어야 하는 부분(debian-sys-maint 계정을 동일하게)

* Doner 노드의 /etc/mysql/debian.cnf 를 복사(password 만 Doner 노드의 것을 가져와도 됨)

root@ubuntu14-pv2:~# scp root@10.0.10.1:/etc/mysql/debian.cnf /etc/mysql/


* Cluster 내에 추가 되는 Joiner 노드는 별도 옵션 없이 시작

root@ubuntu14-pv1:~# service mysql start

 * Starting MariaDB database server mysqld                                [ OK ] 

 * Checking for corrupt, not cleanly closed and upgrade needing tables.


* Doner 노드의 config 를 새로이 추가된 Joiner 를 반영하여 수정해 둔다.

root@ubuntu14-pv1:~# vi /etc/mysql/conf.d/mariadb.cnf

 # MariaDB-specific config file.

...

# Galera Node Option

wsrep_node_name='galera1'

wsrep_node_address='10.0.10.1'

wsrep_cluster_address = 'gcomm://10.0.10.1,10.0.10.2'

wsrep_sst_receive_address=10.0.10.1:4569

...


* Doner 노드의 Mariadb 를 재시작할 필요는 없다(일단 맞추어 놓기만 하고, 다음에 재시작할 때 읽어 들이면 될 것이다). Joiner 가 추가되면서 이미 내부적으로 서로의 존재가 인식되었기 때문인데, Doner 노드에서 아래의 방법으로 확인할 수 있다. 즉, wsrep_cluster_address 변수는 config 에서 읽어들인 값을 가지고 있지만, Cluster 의 현재 상태 값을 가진 wsrep_incoming_addresses 는 2개 노드 접속 주소를 모두 가지고 있다.

root@ubuntu14-pv1:~# mysql -uroot -pmaria

MariaDB [(none)]> show variables like 'wsrep_cluster_address';

+-----------------------+-------------------+

| Variable_name         | Value             |

+-----------------------+-------------------+

| wsrep_cluster_address | gcomm://10.0.10.1 |

+-----------------------+-------------------+

1 row in set (0.00 sec)


MariaDB [(none)]> show status like 'wsrep_incoming_addresses';

+--------------------------+-------------------------------+

| Variable_name            | Value                         |

+--------------------------+-------------------------------+

| wsrep_incoming_addresses | 10.0.10.2:3306,10.0.10.1:3306 |

+--------------------------+-------------------------------+

1 row in set (0.00 sec)



Cluster 의 세 번째 노드, 새로운 Joiner 노드의 추가


* wsrep_node_address 에는 머신 자체의 ip 를 등록

* wsrep_cluster_address 에 기존의 노드에 추가하여 새로운 Joiner 노드 ip 를 등록

* wsrep_sst_receive_address 에는 자체 ip:4569 를 등록

root@ubuntu14-pv3:~# scp root@10.0.10.2:/etc/mysql/conf.d/mariadb.cnf /etc/mysql/conf.d/

root@ubuntu14-pv3:~# vi /etc/mysql/conf.d/mariadb.cnf

# MariaDB-specific config file.

...

# Galera Node Option

wsrep_node_name='galera3'

wsrep_node_address='10.0.10.3'

wsrep_cluster_address = 'gcomm://10.0.10.1,10.0.10.2,10.0.10.3'

wsrep_sst_receive_address=10.0.10.3:4569

...


* Doner 노드의 /etc/mysql/debian.cnf 를 복사

root@ubuntu14-pv3:~# scp root@10.0.10.1:/etc/mysql/debian.cnf /etc/mysql/


* Cluster 내에 추가 되는 Joiner 노드이므로 별도 옵션 없이 시작

root@ubuntu14-pv3:~# service mysql start

 * Starting MariaDB database server mysqld                               [ OK ] 

 * Checking for corrupt, not cleanly closed and upgrade needing tables.


* 기존의 Doner 노드와 Joiner 노드의 config 를 새로이 추가된 Joiner 를 반영하여 수정해 둔다. 앞 선 과정과 같은 요령

* 위와 마찬가지로 기존 MaraiDB들을 재시작할 필요는 없다

root@ubuntu14-pv1:~# vi /etc/mysql/conf.d/mariadb.cnf

 # MariaDB-specific config file.

...

# Galera Node Option

wsrep_node_name='galera1'

wsrep_node_address='10.0.10.1'

wsrep_cluster_address = 'gcomm://10.0.10.1,10.0.10.2,10.0.10.3'

wsrep_sst_receive_address=10.0.10.1:4569

...

root@ubuntu14-pv2:~# vi /etc/mysql/conf.d/mariadb.cnf

 # MariaDB-specific config file.

...

# Galera Node Option

wsrep_node_name='galera2'

wsrep_node_address='10.0.10.2'

wsrep_cluster_address = 'gcomm://10.0.10.1,10.0.10.2,10.0.10.3'

wsrep_sst_receive_address=10.0.10.2:4569

...


여기까지가  두 번째 Joiner 노드 추가 과정이며, 목표로 했던 3대로 이루어진 Galera cluster 가 완성되었다.


* 3대로 구성된 Galera Cluster 가 정상 작동하는지 간단한 테스트를 해 보자

root@ubuntu14-pv1:~# mysql -uroot -pmaria

MariaDB [(none)]> show variables like 'wsrep_cluster_address';

+--------------------------+----------------------------------------------+

| Variable_name            | Value                                        |

+--------------------------+----------------------------------------------+

| wsrep_incoming_addresses | 10.0.10.3:3306,10.0.10.2:3306,10.0.10.1:3306 |

+--------------------------+----------------------------------------------+

1 row in set (0.01 sec)

MariaDB [(none)]> insert into cluster_test.tbl1 values ('xyz123');

1 row in set (0.01 sec)

MariaDB [(none)]> commit;

0 row in set (0.00 sec)


* 최초에 Doner 에서 insert 했던 데이터와 직전에 insert 했던 데이터가 모두 조회된다

root@ubuntu14-pv3:~# mysql -uroot -pmaria -e "select * from cluster_test.tbl1;"

+--------+

| id     |

+--------+

| abcdefg   |

| xyz123   |

+--------+


<여기서 퀴즈1> node1(doner), node2, node3 구성일 때, node1의 MySQL이 shutdown 되었다면 node2, node3 중 하나가 doner 가 될 것이다. 잠시 후 node1이 다시 Cluster에 참여하면 node은 원래대로 doner가 될까?정답은 아래로 Drag!
정답: node1은 원래의 Doner 지위를 자동으로 되찾게 됨


Cluster 내의 노드를 제거/복원(재투입)하려면?


서버 머신 점검을 위해 Doner 노드(ubuntu14-pv1)를 Cluster 에서 제거해야 하는 상황이다. 아래의 과정으로 밟도록 하자.


* config 에서 wsrep_cluster_address 설정을 gcomm:// 로 클리어하고 DB를 재시작하면 Cluster 에서 제거됨

root@ubuntu14-pv1:~# vi /etc/mysql/conf.d/mariadb.cnf

...

# Galera Node Option

wsrep_node_name='galera1'

wsrep_node_address='10.0.10.1'

#wsrep_cluster_address = 'gcomm://10.0.10.1,10.0.10.2,10.0.10.3' <== Comment out

wsrep_cluster_address = 'gcomm://' <== 추가

wsrep_sst_receive_address=10.0.10.1:4569

...

root@ubuntu14-pv1:~# service mysql restart

 * Stopping MariaDB database server mysqld                               [ OK ] 

 * Starting MariaDB database server mysqld                               [ OK ] 

 * Checking for corrupt, not cleanly closed and upgrade needing tables.


root@ubuntu14-pv2:~# mysql -uroot -pmaria -e "show status like  'wsrep_incoming_addresses';"

+--------------------------+-------------------------------+

| Variable_name            | Value                         |

+--------------------------+-------------------------------+

| wsrep_incoming_addresses | 10.0.10.3:3306,10.0.10.2:3306 |

+--------------------------+-------------------------------+

root@ubuntu14-pv3:~# mysql -uroot -pmaria -e "show status like  'wsrep_incoming_addresses';"

+--------------------------+-------------------------------+

| Variable_name            | Value                         |

+--------------------------+-------------------------------+

| wsrep_incoming_addresses | 10.0.10.3:3306,10.0.10.2:3306 |

+--------------------------+-------------------------------+



ubuntu14-pv1 머신의 점검/수리가 끝났다. 원래 대로 재투입하려면 다음 과정을 밟으면 된다.


* config 를 이전 상태로 되돌리고 단순히 restart 하면 끝(이미 Galera Cluster 내에 노드가 1개 이상 작동중일 때에는 --wsrep-new-cluster 옵션을 쓰지 않음)

root@ubuntu14-pv1:~# vi /etc/mysql/conf.d/mariadb.cnf

...

# Galera Node Option

wsrep_node_name='galera1'

wsrep_node_address='10.0.10.1'

wsrep_cluster_address = 'gcomm://10.0.10.1,10.0.10.2,10.0.10.3' <== Uncomment

# wsrep_cluster_address = 'gcomm://' <== Comment out

wsrep_sst_receive_address=10.0.10.1:4569

...

root@ubuntu14-pv1:~# service mysql restart

 * Stopping MariaDB database server mysqld                               [ OK ] 

 * Starting MariaDB database server mysqld                               [ OK ] 

 * Checking for corrupt, not cleanly closed and upgrade needing tables.


root@ubuntu14-pv2:~# mysql -uroot -pmaria -e "show status like  'wsrep_incoming_addresses';"

+--------------------------+----------------------------------------------+

| Variable_name            | Value                                        |

+--------------------------+----------------------------------------------+

| wsrep_incoming_addresses | 10.0.10.3:3306,10.0.10.2:3306,10.0.10.1:3306 |

+--------------------------+----------------------------------------------+

root@ubuntu14-pv3:~# mysql -uroot -pmaria -e "show status like  'wsrep_incoming_addresses';"

+--------------------------+----------------------------------------------+

| Variable_name            | Value                                        |

+--------------------------+----------------------------------------------+

| wsrep_incoming_addresses | 10.0.10.3:3306,10.0.10.2:3306,10.0.10.1:3306 |

+--------------------------+----------------------------------------------+




3. 노드간 데이터 복제가 잘 되지 않는 것 같다. 확인/조치 방법은?


Cluster 내의 모든 노드들은 자신이 Primary 노드라고 인식한다(참고). 그러나 특정한 상황, 즉 네트워크 일시적 단절(network glitch), 과반수 이상의 노드가 장애를 겪거나 또는 split-brain 상태에 빠질 수도 있다. 이렇게 되면 데이터의 동기화에 문제가 발생할 가능성이 커지게 된다.


[여기서 잠깐] split-brain 에 대해 정리해 둘 필요가 있다. 일반적인 split-brain 이란 Master-Slave 상황에서 각자가 Master(또는 primary) 라고 인식하게 되는 상황을 말한다. Galera Cluster 와 같은 Multimaster 의 경우에도 Doner와 Joiner 관계가 있는 것과 같이 Master라 하더라도 '급' 이 다른 구분이 필요하다(즉, "데이터의 오리지널 소스가 누구지?"에 대한 답이 필요하다). 잠시 후 2-node 구성일 때의 네트워크 단절 상황에 대해 테스트 해보기로 하자.


첫 번째 장애: 3-node 구성일 때 1대의 머신에 네트워크 장애 발생


* node2의 네트워크 단절(머신 자체는 동작하지만 node1, node3 과 네트워킹이 안되도록 iptables 로 장애를 흉내 냄)

* 일정 시간이 지나면 node2 는 '쓰기 불가' 상태에 빠지며 wsrep_local_index가 0으로 떨어짐

root@ubuntu14-pv2:~# iptables -A INPUT -d 10.0.10.2 -s 10.0.10.1 -j REJECT

root@ubuntu14-pv2:~# iptables -A INPUT -d 10.0.10.2 -s 10.0.10.3 -j REJECT

root@ubuntu14-pv2:~# mysql -uroot -pmaria

MariaDB [(none)]> show status like 'wsrep_local_index';

+-------------------+-------+

| Variable_name     | Value |

+-------------------+-------+

| wsrep_local_index | 1     |

+-------------------+-------+


MariaDB [(none)]> show status like 'wsrep_local_index';

+-------------------+-------+

| Variable_name     | Value |

+-------------------+-------+

| wsrep_local_index | 0     |   <== 값이 0인 노드는 Doner 또는 Standalone 노드

+-------------------+-------+


MariaDB [(none)]> show status like 'wsrep_incoming_addresses';

+--------------------------+----------------+

| Variable_name            | Value          |

+--------------------------+----------------+

| wsrep_incoming_addresses | 10.0.10.2:3306 |

+--------------------------+----------------+


MariaDB [(none)]> show status like 'wsrep_cluster_size';

+--------------------+-------+

| Variable_name      | Value |

+--------------------+-------+

| wsrep_cluster_size | 1     |

+--------------------+-------+


MariaDB [(none)]>  show status like 'wsrep_cluster_status';

+----------------------+-------------+

| Variable_name        | Value       |

+----------------------+-------------+

| wsrep_cluster_status | non-Primary |

+----------------------+-------------+


MariaDB [(none)]> insert into cluster_test.tbl1 values ('data1234');

ERROR 1047 (08S01): WSREP has not yet prepared node for application use


[주의사항] Cluster에서 제외된 노드(여기서는 node2)에서는 정상적인 쿼리가 수행되지 않는다

* 이 때 wsrep_provider_options 변수에 pc.bootstrap=1(YES) 값을 설정하면 자체가 Standalone 모드로 작동하게 할 수 있다. 단, 네트워크를 정상화한 이후에 다시 Cluster 내에 투입하려면 반드시 MySQL을 재시작해야 한다

* Cluster 내에서 하나의 노드에서만 수행해야 한다(galera Cluster 에서는 Automatic Bootstrap 이라고 함)

root@ubuntu14-pv2:~# mysql -uroot -pmaria

MariaDB [(none)]> SET GLOBAL wsrep_provider_options='pc.bootstrap=1';


* [주의사항] 또 다른 장애 발생 가능성: 이 상황에서 node2의 특정 테이블에 insert 후 PK 변경 DDL 수행시,  Cluster에 재투입하면 node1, node3 에서는 Deadlock 발생 가능성이 있음

* 따라서, Cluster 에서 제외된 노드에서는 더 이상의 DDL이나 insert/update 쿼리가 돌지 않도록 특별히 유의해야 함

root@ubuntu14-pv1:~# 

MariaDB [cluster_test]> select * from tbl1;

ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction

root@ubuntu14-pv3:~# 

MariaDB [cluster_test]> select * from tbl1;

ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction


* [원상복귀] node1, node3 은 정상 작동 중인 상황, node2를 되살린다

* node2 의 네트워크를 되살리면 일정 시간이 지나 node1, node2가 있는 Cluster 로 자동 복귀

root@ubuntu14-pv2:~# iptables -F <== 네트워크 장애가 해결되었음을 시뮬레이션



[특정 노드의 전체 데이터 수동 동기화]

* node2 가 Cluster에서 분리된 이후에 Update되어 데이터가 node1, node3 에 비해 지나치게 상이한 경우의 조치(초기화)

* 아래 과정대로 하면 node1, node3로부터 전체 데이터에 대해 동기화(mysqldump, xtrabackup, rsync 등 방법도 있음)

root@ubuntu14-pv2:~# rm -rf /var/lib/mysql/*

root@ubuntu14-pv2:~# rm -rf /var/log/mysql/*

root@ubuntu14-pv2:~# mysql_install_db

root@ubuntu14-pv2:~# service mysql start --wsrep_cluster_address='gcomm://'

root@ubuntu14-pv2:~# mysql_secure_installation

root@ubuntu14-pv2:~# mysql -uroot -pmaria

MariaDB [(none)]> grant all on *.* to 'root'@'%' identified by 'maria';

MariaDB [(none)]> grant usage on *.* to sst_user@'%' identified by 'maria';

MariaDB [(none)]> grant all privileges on *.* to sst_user@'%';

MariaDB [(none)]> flush privileges;

MariaDB [(none)]> quit

root@ubuntu14-pv2:~# service mysql stop

root@ubuntu14-pv2:~# vi /etc/mysql/conf.d/mariadb.cnf

...

# Galera Node Option

wsrep_node_name='galera2'

wsrep_node_address='10.0.10.2'

wsrep_cluster_address = 'gcomm://10.0.10.1,10.0.10.2,10.0.10.3' <== Uncomment

# wsrep_cluster_address = 'gcomm://' <== Comment out

wsrep_sst_receive_address=10.0.10.2:4569

...

root@ubuntu14-pv1:~# service mysql start

 * Stopping MariaDB database server mysqld                               [ OK ] 

 * Starting MariaDB database server mysqld                               [ OK ] 

 * Checking for corrupt, not cleanly closed and upgrade needing tables.


두 번째 장애: 2-node 구성일 때 1대의 머신에 네트워크 장애 발생(split-brain)


* Cluster내에 2개의 노드(node1, node2) 만 남아 있는 상황

* node2 에 네트워크 장애 발생, 2개의 노드에서 동일하게 데이터베이스가 정상작동하지 않음

* Cluster 내의 Master 노드 정족수가 부족(과반수를 초과해야 하나, quorom=1/2)하게 되기 때문(이러한 한계를 무시하는 설정도 있고, 노드를 흉내내 주는 대안적 방법으로 garbd(Galera Arbiter로 2개 노드일 때 quorom 값을 +1 증가시켜 줌, ☞참고) 를 쓰는 방법도 있으나, 썩 바람직하지 않으므로 Skip)

root@ubuntu14-pv2:~# iptables -A INPUT -d 10.0.10.2 -s 10.0.10.1 -j REJECT


root@ubuntu14-pv1:~# mysql -uroot -pmaria

MariaDB [(none)]> select * from cluster_test.tbl1;

ERROR 1047 (08S01): WSREP has not yet prepared node for application use


root@ubuntu14-pv2:~# mysql -uroot -pmaria

MariaDB [(none)]> use cluster_test;

ERROR 1047 (08S01): WSREP has not yet prepared node for application use


* [원상복귀] node2 의 네트워크를 되살리면 일정 시간이 지나 node1이 있는 Cluster 로 자동 복귀

root@ubuntu14-pv2:~# iptables -F


root@ubuntu14-pv1:~# mysql -uroot -pmaria
MariaDB [(none)]> show status like 'wsrep_local_index';
+-------------------+-------+
| Variable_name     | Value |
+-------------------+-------+
| wsrep_local_index | 0     |
+-------------------+-------+


root@ubuntu14-pv2:~# mysql -uroot -pmaria

MariaDB [(none)]> show status like 'wsrep_local_index';

+-------------------+-------+

| Variable_name     | Value |

+-------------------+-------+

| wsrep_local_index | 1     |

+-------------------+-------+



- Barracuda -


저작자 표시 비영리 변경 금지
신고
블로그 이미지

Barracuda

Bryan의 MemoLog. 쉽게 익혀 보는 IT 실습과 개념원리, 코딩 세계의 얕은 맛보기들, 평범한 삶 주변의 현상 그리고 進上, 眞想, 진상들

Opensuse 12.1 환경에서 PHP5 + lighttpd fastcgi + mongodb + mysql 개발/운영 환경 설정

* howtoforge.com 내용 참조, 테스트 실행 & 보완


1. Lighttpd & php5 환경 설정


# zypper in -y lighttpd

# systemctl enable lighttpd.service

# systemctl start lighttpd.service


* 기존의 php5 fastcgi 가 php5-fpm 패키지로 통합 업그레이드 되었고 별도 daemon으로 동작한다.

# zypper in -y php5-fpm


# mv /etc/php5/fpm/php-fpm.conf.default /etc/php5/fpm/php-fpm.conf

# chmod 1733 /var/lib/php5


* error_log 부분을 un-comment 하고 아래와 같이 수정한다

# vi /etc/php5/fpm/php-fpm.conf

error_log = /var/log/php-fpm.log


* 아래 라인들을 찾아서 확인하고 몇 가지 mandatory 설정을 un-comment 한다(pm=dynamic 일 경우)

* howtoforge.com 에서는 해당 설정 부분이 누락되어 있다

pm = dynamic

pm.max_children = 50

pm.min_spare_servers = 5

pm.max_spare_servers = 35


* fpm용으로 별도의 php.ini 파일이 없으므로 cli용을 복사한다.

# cp /etc/php5/cli/php.ini /etc/php5/fpm/


* 아래 해당 라인을 찾아서 un-comment 한다.

# vi /etc/php5/fpm/php.ini

cgi.fix_pathinfo=1


# systemctl enable php-fpm.service

# systemctl start php-fpm.service


# vi /etc/lighttpd/modules.conf -> 아래 라인을 찾아서 un-comment

include "conf.d/fastcgi.conf"


server.modules = (

...

  "mod_auth",

...

)


* 아래 라인을 추가

# vi /etc/lighttpd/lighttpd.conf

include "conf.d/auth.conf"


* 아래 라인들을 un-comment 하고 내용을 수정

# vi /etc/lighttpd/conf.d/auth.conf

auth.debug = 2

auth.backend = "plain"

auth.backend.plain.userfile  = "/etc/lighttpd/lighttpd.user"


auth.require = ( "/" =>

                      (

                        "method"  => "basic",

                        "realm"   => "Password protected area",

                        "require" => "user=loginid"

                      ),

                    )


* 아래 로그인 정보를 등록하고 저장

# vi /etc/lighttpd/lighttpd.user

loginid:loginpassword


# vi /etc/lighttpd/conf.d/fastcgi.conf -> 아래 라인이 있는지 확인

server.modules += ( "mod_fastcgi" )


* 아래 내용을 추가(기존의 fastcgi.server 부분의 comment 는 그대로 둔다)

fastcgi.server += ( ".php" =>

        ((

                "host" => "127.0.0.1",

                "port" => "9000",

                "broken-scriptfilename" => "enable"

        ))

)


# systemctl restart lighttpd.service


* lighttpd의  default 문서 홈디렉토리는 /srv/www/htdocs 이다


# vi /srv/www/htdocs/info.php

<?php

phpinfo();

?>


* 브라우저로 접속 확인




2. MySQL과 utility 패키지 설치


* Web 을 통하지 않고 직접 DB접속을 위해 접속 클라이언트를 사용할 경우에는 아래와 같이 클라이언트를 설치한다.

# zypper in -y mysql-community-server-client


* MySQL 및 일반적으로 많이 사용하는 드라이버 설치

# zypper in -y php5-mysql php5-bcmath php5-bz2 php5-calendar php5-ctype php5-curl php5-dom php5-ftp php5-gd php5-gettext php5-gmp php5-iconv php5-imap php5-ldap php5-mbstring php5-mcrypt php5-odbc php5-openssl php5-pcntl php5-pgsql php5-posix php5-shmop php5-snmp php5-soap php5-sockets php5-sqlite php5-sysvsem php5-tokenizer php5-wddx php5-xmlrpc php5-xsl php5-zlib php5-exif php5-pear php5-sysvmsg php5-sysvshm


3. mongodb 드라이버 설치


* 11.x 환경과는 다르게 12.1 부터는 pecl 을 통해 php용 mongo 드라이버를 쉽게 설치할 수 있다


# pecl install mongo


# vi /etc/php5/fastcgi/php.ini -> 아래 라인을 추가

extension=mongo.so


# systemctl restart lighttpd.service

# systemctl restart php-fpm.service


* 1의 과정과 같이 브라우저를 통해 php 환경에 맞게 설치된 드라이버들을 최종 확인한다.






저작자 표시 비영리 변경 금지
신고
블로그 이미지

Barracuda

Bryan의 MemoLog. 쉽게 익혀 보는 IT 실습과 개념원리, 코딩 세계의 얕은 맛보기들, 평범한 삶 주변의 현상 그리고 進上, 眞想, 진상들

Opensuse 11.3, 12.1 각각에 대해 2회에 걸쳐서 정리

* howtoforge.com 내용 참조, 테스트 실행 & 보완


1. Lighttpd & php5 환경 설정


# zypper in -y lighttpd

# chkconfig --add lighttpd

# chkconfig lighttpd on

# service lighttpd start


# zypper in -y php5-fastcgi


* 아래 라인을 찾아서 un-comment

# vi /etc/php5/fastcgi/php.ini 

cgi.fix_pathinfo=1


* 아래 라인을 찾아서 un-comment

# vi /etc/lighttpd/modules.conf

include "conf.d/fastcgi.conf"


server.modules = (

...

  "mod_auth",

...

)


* 아래 라인을 추가

# vi /etc/lighttpd/lighttpd.conf

include "conf.d/auth.conf"


* 아래 라인들을 un-comment 하고 내용을 수정

# vi /etc/lighttpd/conf.d/auth.conf

auth.debug = 2

auth.backend = "plain"

auth.backend.plain.userfile  = "/etc/lighttpd/lighttpd.user"


auth.require = ( "/" =>

                      (

                        "method"  => "basic",

                        "realm"   => "Password protected area",

                        "require" => "user=loginid"

                      ),

                    )


* 아래 로그인 정보를 등록하고 저장

# vi /etc/lighttpd/lighttpd.user

loginid:loginpassword


* 아래 라인이 있는지 확인

# vi /etc/lighttpd/conf.d/fastcgi.conf

server.modules += ( "mod_fastcgi" )


* 아래 부분을 찾아서 un-comment

fastcgi.server = ( ".php" =>

                   ( "php-local" =>

                     (

                       "socket" => socket_dir + "/php-fastcgi-1.socket",

                       "bin-path" => server_root + "/cgi-bin/php5",

                       "max-procs" => 1,

                       "broken-scriptfilename" => "enable",

                     )

                   ),

                   ( "php-tcp" =>

                     (

                       "host" => "127.0.0.1",

                       "port" => 9999,

                       "check-local" => "disable",

                       "broken-scriptfilename" => "enable",

                     )

                   ),


                   ( "php-num-procs" =>

                     (

                       "socket" => socket_dir + "/php-fastcgi-2.socket",

                       "bin-path" => server_root + "/cgi-bin/php5",

                       "bin-environment" => (

                         "PHP_FCGI_CHILDREN" => "8",

                         "PHP_FCGI_MAX_REQUESTS" => "10000",

                       ),

                       "max-procs" => 2,

                       "broken-scriptfilename" => "enable",

                     )

                   ),

                )

* 위의 옵션은 소규모 접속일 경우이고, 일반적인 다중 접속 사이트일 경우 아래와 같이 규모에 맞게 적당히 옵션을 조정한다.

"PHP_FCGI_CHILDREN" => "16"

"max-procs" => 5


# service lighttpd restart


* lighttpd의  default 문서 홈디렉토리는 /srv/www/htdocs 이다


# vi /srv/www/htdocs/info.php

<?php

phpinfo();

?>


* 브라우저로 접속 확인




2. MySQL과 utility 패키지 설치


* Web 을 통하지 않고 직접 DB접속을 위해 접속 클라이언트를 사용할 경우에는 아래와 같이 클라이언트를 설치한다.

# zypper in -y mysql-community-server-client


* MySQL 및 일반적으로 많이 사용하는 드라이버 설치

# yast2 -i php5-mysql php5-bcmath php5-bz2 php5-calendar php5-ctype php5-curl php5-dom php5-ftp php5-gd php5-gettext php5-gmp php5-iconv php5-imap php5-ldap php5-mbstring php5-mcrypt php5-odbc php5-openssl php5-pcntl php5-pgsql php5-posix php5-shmop php5-snmp php5-soap php5-sockets php5-sqlite php5-sysvsem php5-tokenizer php5-wddx php5-xmlrpc php5-xsl php5-zlib php5-exif php5-pear php5-sysvmsg php5-sysvshm


3. mongodb 드라이버 설치


* pecl.php.net 사이트를 이용하여 최신 버전의 php mongo 드라이버를 찾아서 다운로드 한다.


# zypper in -y php5-devel

# wget http://pecl.php.net/get/mongo-1.3.0beta2.tgz

# tar xvzf mongo-1.3.0beta2.tgz; cd mongo-1.3.0beta2

# phpize

# ./configure

# make

# make install

# ldconfig

# vi /etc/php5/fastcgi/php.ini -> 아래 라인을 추가

extension=mongo.so


# service lighttpd restart


* 1의 과정과 같이 브라우저를 통해 php 환경에 맞게 설치된 드라이버들을 최종 확인한다.





저작자 표시 비영리 변경 금지
신고
블로그 이미지

Barracuda

Bryan의 MemoLog. 쉽게 익혀 보는 IT 실습과 개념원리, 코딩 세계의 얕은 맛보기들, 평범한 삶 주변의 현상 그리고 進上, 眞想, 진상들


5.1.X~5.5.X 까지도 가끔 발생되는 오류인데

mysqldump 를 실행하면 로그상에 보이는 오류메시지이다.


[ERROR] mysqld: Table './mysql/proc' is marked as crashed and should be repaired

[Warning] Checking table:   './mysql/proc'


이 때는 mysql 유틸리티에 포함된 mysqlcheck 을 사용하여 해결할 수 있다.


# mysqlcheck --repair mysql proc -uroot -ppassword

저작자 표시 비영리 변경 금지
신고
블로그 이미지

Barracuda

Bryan의 MemoLog. 쉽게 익혀 보는 IT 실습과 개념원리, 코딩 세계의 얕은 맛보기들, 평범한 삶 주변의 현상 그리고 進上, 眞想, 진상들


* 2011/09/22에 update됨
* MySQL이 MySQL 5.5 부터는 SemiSync 라는 쓸만한 기능으로 Availability가 더 향상되었다.
즉, M-S1S2 형태의 Replication에서 M의 Transaction과 S로의 binlog write가 병렬로 처리되며(Master가 Slave의 binlog로의 전송을 보장, 동기=sync), S의 binlog에서 Storage 로의 write 는 비동기(async)로 처리된다(==> 반동기=SemiSync)
[참조] http://www.mysqlkorea.co.kr/gnuboard4/bbs/board.php?bo_table=develop_03&wr_id=73

* 기존의 5.1.x 대에 비해서 script의 위치나 Replication 설정 방식에서 약간의 차이를 보이고 있다.

* M1=Master1, M2=Master2

* 선행 패키지 설치

# zypper in -y cmake ncurses-devel readline-devel bison



* 다운로드 & 빌드

wget http://www.percona.com/redir/downloads/Percona-Server-5.5/Percona-Server-5.5.15-21.0/source/Percona-Server-5.5.15-rel21.0.tar.gz
#  tar xvzf Percona-Server-5.5.15-rel21.0.tar.gz
# cd Percona-Server-5.5.15-rel21.0/
# groupadd mysql 
# useradd -g mysql -s /bin/false mysql
# sh BUILD/autorun.sh
./configure --prefix=/user/service/mysql --with-mysqld-user=mysql --sysconfdir=/user/service/mysql/conf --with-unix-socket-path=/tmp/mysqld/mysql.sock --with-charset=utf8 --with-extra-charsets=all --with-plugins=innobase,innodb_plugin,myisam,partition
# make && make install



* 디렉토리, my.cnf 설정

# cd /user/service/mysql
# export PATH=$PATH:/user/service/mysql/bin (.bashrc 에도 추가) 
# mkdir conf



# vi conf/my.cnf
[client]

port                                    = 3306
socket                                  = /tmp/mysql.sock
[mysqld_safe]
socket                                  = /tmp/mysql.sock
nice                                    = 0
# TimeZone
#default-time-zone                       = 'Asia/Seoul'

[mysqld]
# TimeZone
#default-time-zone                       = 'Asia/Seoul'

# UTF8
init_connect=SET collation_connection   = utf8_general_ci
init_connect                            = SET NAMES utf8
character-set-server                    = utf8
collation-server                        = utf8_general_ci
# Storage engine
default-storage-engine                  = innodb
# no difference between upper and lowercases
lower_case_table_names                  = 1
# General settings
user                                    = mysql
pid-file                                = /tmp/mysqld/mysql.pid
socket                                  = /tmp/mysqld/mysql.sock
port                                    = 3306
# Directory settings
basedir                                 = /user/service/mysql
datadir                                 = /user/service/mysql/data
tmpdir                                  = /tmp
# ETC
skip-external-locking
# Tunnig options
key_buffer_size                         = 384M
max_allowed_packet                      = 16M
table_open_cache                        = 512
sort_buffer_size                        = 2M
read_buffer_size                        = 2M
read_rnd_buffer_size                    = 8M
myisam_sort_buffer_size                 = 64M
thread_cache_size                       = 8
# for MyIsam
myisam-recover                          = BACKUP
max_connections                         = 250
max_user_connections                    = 200
# Try number of CPU's*2 for thread_concurrency, 5.5.3+ ignored
# thread_concurrency                    = 8
# Important for bulk loading
query_cache_size                        = 32M
# * Logging and Replication
slow_query_log                          = /user/service/mysql/data/mysql-slow.log
long_query_time                         = 2

# Replication Master Server (default)
server-id                               = 1

log-bin                                = mysql-bin
log-warnings
log-slave-updates
replicate-same-server-id                 = 0
auto-increment-increment               = 1
relay-log                               = mysql-relay-bin

expire_logs_days                        = 10
max_binlog_size                         = 100M
binlog_format                           = ROW
# * InnoDB
innodb_data_home_dir                    = /user/service/mysql/data
innodb_data_file_path                   = ibdata1:2000M;ibdata2:10M:autoextend
innodb_log_group_home_dir               = /user/service/mysql/data

# buffer_pool_size up to 50 - 80 % of RAM
#innodb_buffer_pool_size                 = 1536M # 사용 가능 memory 에 맞게 설정
innodb_buffer_pool_size                 = 256M
innodb_additional_mem_pool_size         = 20M
# log_file_size to 25 % of buffer pool size
innodb_log_file_size                    = 384M
innodb_log_buffer_size                  = 8M
innodb_flush_log_at_trx_commit          = 1
innodb_lock_wait_timeout                = 10
innodb_file_per_table
innodb_file_format                      = barracuda

[mysqldump]
quick
max_allowed_packet                      = 32M
[mysql]
no-auto-rehash # faster start of mysql but no tab completition
[myisamchk]
key_buffer_size                         = 256M
sort_buffer_size                        = 256M
read_buffer                             = 2M
write_buffer                            = 2M
[mysqlhotcopy]
interactive-timeout


* 기본 데이터베이스 스키마 생성 & Grant 설정

# ./scripts/mysql_install_db --defaults-file=/user/service/mysql/conf/my.cnf --user=mysql

# mysqld_safe --defaults-file=/user/service/mysql/conf/my.cnf --log-bin-trust-function-creators=1 &

# mysqladmin -u root password 'password'
# mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -uroot -ppassword mysql 
## Database에서 Timezone 을 사용할 경우, my.cnf 에서 comment 로 막아 둔 default-time-zone 의 comment 를 해제
# mysqladmin  -uroot -ppassword shutdown
# mysqld_safe --defaults-file=/user/service/mysql/conf/my.cnf --log-bin-trust-function-creators=1 --skip-slave --relay-log=mysql-relay-bin &
# mysql -uroot -ppassword
M1> use mysql;
M1> grant all privileges on *.* to 'root'@'%' identified by 'password' with grant option;
M1> grant all privileges on *.* to 'root'@'localhost' identified by 'password' with grant option;
M1> flush privileges; 

root 권한 설정/ 확인
M1> GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO root@"%" IDENTIFIED by 'password';
M1> flush privileges; 

사용하려고 하는 database명이 mydb 라고 가정하고, 데이터베이스 생성과 개발자(사용자) 계정을 생성하고 권한을 아래과 같이 설정한다
M1>  insert into mySql.User (host, User, Password) values ('%', 'devuser', password('dev_passwd'));
M1> insert into mySql.User (host, User, Password) values ('localhost', 'devuser', password('dev_passwd'));
M1> flush privileges; 
M1> create database mydb;
M1> GRANT ALL PRIVILEGES ON mydb.* TO 'devuser'@'localhost' IDENTIFIED BY 'dev_passwd';
M1> GRANT ALL PRIVILEGES ON mydb.* TO 'devuser'@'%' IDENTIFIED BY 'dev_passwd'; 
M1> REVOKE ALTER, DROP ON mydb.* FROM 'devuser'@'localhost';
M1> REVOKE ALTER, DROP ON mydb.* FROM 'devuser'@'%'; 
M1> flush privileges; 
M1> GRANT ALL PRIVILEGES ON mysql.func TO 'devuser'@'localhost' IDENTIFIED BY 'dev_passwd';
M1> GRANT ALL PRIVILEGES ON mysql.func TO 'devuser'@'%' IDENTIFIED BY 'dev_passwd'; 
M1> GRANT ALL PRIVILEGES ON mysql.proc TO 'devuser'@'localhost' IDENTIFIED BY 'dev_passwd';
M1> GRANT ALL PRIVILEGES ON mysql.proc TO 'devuser'@'%' IDENTIFIED BY 'dev_passwd'; 
M1> GRANT ALL PRIVILEGES ON mysql.procs_priv TO 'devuser'@'localhost' IDENTIFIED BY 'dev_passwd';
M1> GRANT ALL PRIVILEGES ON mysql.procs_priv TO 'devuser'@'%' IDENTIFIED BY 'dev_passwd'; 
M1> flush privileges; 



* M1의 DB를 source로 하여 M2 로 동기화 후 Master-Master 설정하기
   M1, M2 의 DB shutdown(또는 M1을 down 시키기 곤란한 경우 flush logs; flush tables wih read lock 으로 lock 설정, M2는 down)

# rsync -rpv root@M1_ip_addr:/user/service/mysql/data /user/service/mysql/
## Default port 22가 아닌 sshd  접속의 경우
# rsync -rpv -e "ssh -p 55000" root@M1_ip_addr:/user/service/mysql/data /user/service/mysql/ 
## CloudN, EC2 등과 같은 Cloud Platform의 pem 보안 키 접속일 경우
# rsync -rpv -e "ssh -i XXXX,pem" root@M1_ip_addr:/user/service/mysql/data /user/service/mysql/ 
# chown -R mysql.mysql ./data

* M1, conf/my.cnf 에서 server_id = 1 임을 확인
* M2, conf/my.cnf 에서 server_id = 2(또는 2보다 큰 정수) 임을 확인

* M1, M2 Database start
# mysqld_safe --defaults-file=/user/service/mysql/conf/my.cnf --log-bin-trust-function-creators=1 --skip-slave --relay-log=mysql-relay-bin &



* M1에서
# mysql -uroot -ppassword
M1> show master status;

| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
| mysql-bin.000010 |      107 |              |                  |
1 row in set (0.00 sec)

* M2에서
# mysql -uroot -ppassword
M2> change master to master_host='M1_ip_addr', master_user='root', master_password='password', master_log_file='mysql-bin.000010', master_log_pos=107;
M2> slave start;
M2> show slave status;

* M1에서 M2 를 source로 하여 마찬가지로 change master to 로 Replication 을 설정하고 slave start 로 복제를 시작시킨다



* MySQL 5.5 에서는, 5.1.X 에서 적용되던 my.cnf 에서의 master_host, master_user, master-password 변수를 통한 Replication 설정은 더 이상 사용되지 않게 바뀌었다.
 


저작자 표시 비영리 변경 금지
신고
블로그 이미지

Barracuda

Bryan의 MemoLog. 쉽게 익혀 보는 IT 실습과 개념원리, 코딩 세계의 얕은 맛보기들, 평범한 삶 주변의 현상 그리고 進上, 眞想, 진상들


Haproxy 의 option mysqlchk 로 DB 의 가용 여부를 점검하는 데에 쓸 수 있으나
정상적인 점검이 정확하게 되지 않으며, MySQL의 connection을 잠식하는 문제점이 있다.
단순히 DB 접속 port만 감시하는 방법도 쓸 수 있으나, DB의 정상 가동여부를 체크하는 방법으로는 적합하지 않다.

xinetd service와, 간단한 db connection & query script를 이용
Assumption: MySQL home - /user/service/mysql
Thanks to Unai Rodriguez(script author) & Sysbible(http://sysbible.org/)

1. script 작성

# cd /user/service/mysql/bin; vi mysql_hc
#!/bin/bash MYSQL_HOST="localhost" MYSQL_PORT="3306" MYSQL_USERNAME="mysql_hc" MYSQL_PASSWORD="password" TMP_FILE="/user/service/mysql/var/mysqlchk.out" ERR_FILE="/user/service/mysql/var/mysqlchk.err" # a simple query /user/service/mysql/bin/mysql --host=$MYSQL_HOST --port=$MYSQL_PORT --user=$MYSQL_USERNAME --password=$MYSQL_PASSWORD -e "show databases;" > $TMP_FILE 2> $ERR_FILE # Check the output. If it is not empty then everything is fine and we return # something. Else, we just do not return anything. # if [ "$(/bin/cat $TMP_FILE)" != "" ] then # mysql is fine, return http 200 /bin/echo -e "HTTP/1.1 200 OK\r\n" /bin/echo -e "Content-Type: Content-Type: text/plain\r\n" /bin/echo -e "\r\n" /bin/echo -e "MySQL is running.\r\n" /bin/echo -e "\r\n" else # mysql is fine, return http 503 /bin/echo -e "HTTP/1.1 503 Service Unavailable\r\n" /bin/echo -e "Content-Type: Content-Type: text/plain\r\n" /bin/echo -e "\r\n" /bin/echo -e "MySQL is *down*.\r\n" /bin/echo -e "\r\n" fi

# chown root.mysql mysql_hc; chmod 744 mysql_hc
# mysql -uroot -ppassword
  > GRANT SELECT on mysql.* TO 'mysql_hc'@'%' \
  > IDENTIFIED BY 'password' WITH GRANT OPTION;
  > GRANT SELECT on mysql.* TO 'mysql_hc'@'localhost' \
  > IDENTIFIED BY 'password' WITH GRANT OPTION;
  > flush privileges;
# ./mysql_hc - 실행 결과 확인(HTTP/1.x 200 OK)


2.  vi /etc/services 에 아래 라인 추가

mysql_hc    28001/tcp                      # mysql_hc - mysql health checker

3. vi /etc/xinetd.d/mysql_hc

# default: on
# description: mysql_hc
service mysql_hc
{
        flags           = REUSE
        socket_type     = stream
        port            = 28001
        wait            = no
        user            = root
        server          = /user/service/mysql/bin/mysql_hc
        log_on_failure  += USERID
        disable         = no
        only_from       = 0.0.0.0/0      # recommended to put the IPs that need
                                                 # to connect exclusively (security purposes)
        per_source      = UNLIMITED
}
 
# service xinetd restart

4. 정상 작동 test

# telnet 10.10.0.10 28001

Trying 10.10.0.10... Connected to 10.10.0.10. Escape character is '^]'. HTTP/1.1 200 OK Content-Type: Content-Type: text/plain MySQL is running. Connection closed by foreign host.


5. HaProxy configuration 에 설정 추가

listen RDB-1
        bind 10.10.0.71:28000
        mode tcp
        option httpchk
        timeout connect 5m
        timeout client 30m
        timeout server 30m
        server RDB-1 10.10.0.10:3306 check port 28001 inter 5s rise 1 fall 3
        server RDB-2 10.10.0.30:3306 check port 28001 inter 5s rise 1 fall 3 backup
        log global


저작자 표시 비영리 변경 금지
신고
블로그 이미지

Barracuda

Bryan의 MemoLog. 쉽게 익혀 보는 IT 실습과 개념원리, 코딩 세계의 얕은 맛보기들, 평범한 삶 주변의 현상 그리고 進上, 眞想, 진상들


MySQL에서 NOT FOUND exception은 Cursor Fetch 시에만 발생한다.

따라서 update 아래의 IF 문 내의 처리는 의도한 대로 동작하지 않는다. 즉, 코더의 의도는 Update 문을 실행해서 해당 데이터가 없다면 If 문 내의 문장이 처리되기를 원한 거겠지만, 아래의 이 IF 문 내의 문장은 전혀 실행되지 못하게 된다.
DECLARE MyErr INT default 0;
DECLARE CONTINUE HANDLER FOR NOT FOUND set MyErr = -1;
...
UPDATE table
   SET COL = 'data'
WHERE
   KEY_COL = 'key data';

IF MyErr < 0 THEN
    statements_for_not_found...;
END IF;

또한 update에서 해당 row가 없을 경우에 found_rows()=0 역시 동작하지 않는다.
이런 경우 반드시 아래와 같이 ROW_COUNT() 를 이용해서 코딩해야 한다.
/* DECLARE CONTINUE HANDLER FOR NOT FOUND set MyErr = -1; */
...
...
/* IF MyErr < 0 THEN */
IF ROW_COUNT()=0 THEN
    statements_for_not_found...;
END IF;
...


- Barracuda -


저작자 표시 비영리 변경 금지
신고
블로그 이미지

Barracuda

Bryan의 MemoLog. 쉽게 익혀 보는 IT 실습과 개념원리, 코딩 세계의 얕은 맛보기들, 평범한 삶 주변의 현상 그리고 進上, 眞想, 진상들


Database 내에서 발생하는 모든 쿼리들을 logging할 필요가 있을 때
SHOW VARIABLES LIKE 'general_log';
SHOW VARIABLES LIKE 'log_output';

SET GLOBAL general_log = 1;
SET GLOBAL log_output = 'table';
-- 필요시에만 켜서 사용

SET GLOBAL general_log = 0;
SET GLOBAL log_output = 'file';
-- 평상시에는 이렇게 disable해 두어야 엔진의 성능에 부담이 가지 않으므로 주의

Query logging table: mysql.general_log

* MySQL에서는 milli-second 단위로 시간을 처리하지 않으므로 timestamp는 초 단위까지만 기록된다.
ALTER TABLE mysql.general_log 
    ADD COLUMN seq BIGINT UNSIGNED NOT NULL AUTO_INCREMENT AFTER argument,
    ADD PRIMARY KEY(seq),
    ENGINE=MYISAM;
으로 log table을 alter한 후 order by seq desc와 같이 select 해서 실행 순서대로 정렬하여 활용하면 된다.
MySQL에서 사용되는 기본 general_log 테이블에는 index 가 없으므로, 위와 같이 index 를 이용한 조회를 하지 않으면
데이터베이스 성능에 부담을 주게 되며,

확인이 끝 난 후 반드시 general_log를 disable해 두어야만 성능상의 문제로 재난이 생기지 않으니 반드시 유의해야 한다.

general_log 테이블을 비워야 할 경우, delete 쿼리를 수행하면 '로그테이블에 대한 처리 불가'라고 오류가 발생하게 되므로
아래와 같이 처리해야 한다.
SET GLOBAL general_log = OFF; -- log를 계속 쌓도록 하려면 생략
USE mysql;
create table tmp_general_log like general_log;
rename table generlal_log to old_general_log, tmp_general_log to general_log;


저작자 표시 비영리 변경 금지
신고
블로그 이미지

Barracuda

Bryan의 MemoLog. 쉽게 익혀 보는 IT 실습과 개념원리, 코딩 세계의 얕은 맛보기들, 평범한 삶 주변의 현상 그리고 進上, 眞想, 진상들


(MySQL은 Percona XtraDB 5.1.49 기준)
binutils
automake
libtool 
bison 
make 
termcap 
libtermcap.x86_64 
libtermcap-devel.x86_64 
gcc
gcc-c++.x86_64 
libstdc++.x86_64 
ncurses 
ncurses-devel.x86_64 
glibc.x86_64 
glibc-common.x86_64 
glibc-devel.x86_64 
glibc-headers.x86_64 
glibc-utils.x86_64


저작자 표시 비영리 변경 금지
신고
블로그 이미지

Barracuda

Bryan의 MemoLog. 쉽게 익혀 보는 IT 실습과 개념원리, 코딩 세계의 얕은 맛보기들, 평범한 삶 주변의 현상 그리고 進上, 眞想, 진상들

Tag centos, mysql

Full dump 파일이 100MB 이상 되면 slave 에서 로드하다보면 제대로 되는지 확인이 안되서
시간은 급한데 억장이 무너진다면 아래의 방법을 써본다.

* Master: 10.10.0.200, Slave: 10.10.0.201

1. Master database read lock
# mysql -uroot -prootpass
<Master> flush logs;
<Master> flush tables with read lock;

2. Rsync from master to slave(Slave)
# mysqladmin -uroot -prootpass shutdown
# rm -rf /user/services/mysql/data/*
# rsync -r -p -v root@10.10.0.200:/user/service/mysql/data /user/service/mysql/

* Check my.cnf
server-id=2 (or other number, not 1)
master-host=10.10.0.200
master-user=root
master-password=rootpass

# chown -R mysql.mysql /user/service/mysql/data
# mysqld_safe --user=mysql --log-bin-trust-function-creators=1 --skip-slave --relay-log=mysql-relay-bin &
# mysql -uroot -prootpass
<Slave> stop slave;
<Slave> reset slave;

3. Reset master & start slave thread
<Master> unlock tables;
<Master> reset master; -- purge all log-bins
<Master> show master status;
<Slave> start slave;
<Slave> show slave status;

* Slave_IO_State : Waiting for master to send event, Master_Host : master_ip, ... => Successful 


- Barracuda -


저작자 표시 비영리 변경 금지
신고
블로그 이미지

Barracuda

Bryan의 MemoLog. 쉽게 익혀 보는 IT 실습과 개념원리, 코딩 세계의 얕은 맛보기들, 평범한 삶 주변의 현상 그리고 進上, 眞想, 진상들



* make 시에 아래와 같은 오류 발생
------------------------------------------------------------------------------------------------------
gcc -DHAVE_CONFIG_H -I. -I../include -I../include -I../include -I../sql    -O3 -m32
-march=core2 -fomit-frame-pointer -pipe -fno-exceptions   -DUNIV_LINUX
@ndbcluster_includes@  -c perror.c
gcc: @ndbcluster_includes@: No such file or directory
make[3]: *** [perror.o] Error 1
------------------------------------------------------------------------------------------------------

[Solution]
* configure 직후에 ./extra/Makefile에서 @ndbcluster_include@ 삭제 -- (1)
            "             ./sql/Makefile에서 @ndbcluster_inclide@, @NDB_SCI_LIBS@ 삭제 -- (2)

# ./configure --prefix=/user/service/mysql --with-mysqld-user=mysql --sysconfdir=/user/service/mysql/conf --with-unix-socket-path=/tmp/mysqld/mysql.sock --with-charset=utf8 --with-extra-charsets=all --with-plugins=innobase,myisam,semisync,partition

# vi ./extra/Makefile --(1)
# vi ./sql/Makefile --(2)

# make && make install

* Enjoy & have fun ~


저작자 표시 비영리 변경 금지
신고
블로그 이미지

Barracuda

Bryan의 MemoLog. 쉽게 익혀 보는 IT 실습과 개념원리, 코딩 세계의 얕은 맛보기들, 평범한 삶 주변의 현상 그리고 進上, 眞想, 진상들


MySQL InnoDB 사용자를 위한 모니터링 툴( http://code.google.com/p/innotop/ , http://code.google.com/p/innotop/wiki/Screenshots )

2010/11 에 새 버전이 나와서 update합니다.

* Run as superuser
# wget http://innotop.googlecode.com/files/innotop-1.7.2.tar.gz
# wget http://innotop.googlecode.com/files/innotop-1.8.0.tar.gz
# zypper install perl-DBD-mysql
[참고] # yum install perl-TermReadKey (Fedora의 경우, 빠져 있기 쉬운 패키지)
# tar xvzf innotop-1.8.0.tar.gz
# cd innotop-1.8.0
# perl Makefile.PL
# make install

* Run and enjoy
# innotop -uroot -prootpass --socket /tmp/mysql.sock (socket option 필요 없으면 제외)

* Thannks to aracine( http://code.google.com/u/aracine/ )


저작자 표시 비영리 변경 금지
신고
블로그 이미지

Barracuda

Bryan의 MemoLog. 쉽게 익혀 보는 IT 실습과 개념원리, 코딩 세계의 얕은 맛보기들, 평범한 삶 주변의 현상 그리고 進上, 眞想, 진상들


[Mysql NDB Cluster 설정] - 5.1.44-ndb-7.1.4b

1. 소스 다운로드
http://dev.mysql.com/get/Downloads/MySQL-Cluster-7.1/mysql-cluster-gpl-7.1.4b.tar.gz/from/http://mirror.khlug.org/mysql/

2. 압축 해제, 설치
(필수 패키지: curses*, termcap, gcc-c++)
# ./configure --prefix=/user/service/mysql --with-mysqld-user=mysql --sysconfdir=/user/service/mysql/conf --with-unix-socket-path=/tmp/mysqld/mysql.sock --with-charset=utf8 --with-extra-charsets=all --with-plugins=innobase,myisam,partition,heap,ndbcluster
# make && make install

5. cnf 복사, 설정
# cp /ForMysqlBaseDir/mysql/share/mysql/my-huge.cnf /ForMysqlBaseDir/mysql/conf/my.cnf
* cnf 편집, 디렉토리 설정
  또는 미리 준비한 my.cnf 복사(cp /home/myaccound/mysql554/my.cnf /ForMysqlBaseDir/mysql/conf)

* Sample 설정
------------------------------------------------------
[mysqld]
init_connect=SET collation_connection = utf8_general_ci
init_connect=SET NAMES utf8
character-set-server=utf8
collation-server=utf8_general_ci
# Storage engine
default-storage-engine = innodb
# no difference between upper and lowercases
lower_case_table_names = 1
user            = mysql
pid-file        = /tmp/mysqld/mysql.pid
socket          = /tmp/mysqld/mysql.sock
port            = 3306
basedir         = /user/service/mysql
datadir         = /user/service/mysql/data
tmpdir          = /tmp
------------------------------------------------------

6. 초기데이터베이스 생성
# cd /ForMysqlBaseDir/bin
# ./mysql_install_db --user=mysql

7. Directory 생성, 권한 설정
# mkdir -p /ForMysqlBaseDir/mysql/conf
# chown -R root.mysql /ForMysqlBaseDir/mysql
# chown -R mysql.mysql /ForMysqlBaseDir/mysql/data

8. 테스트 실행
> cd /ForMysqlBaseDir/mysql/bin
> ./mysqld_safe --user=mysql &
> ./mysqladmin shutdown

9. Daemon 등록 실행
> cp /ForMysqlBaseDir/mysql/share/mysql/mysql.server /etc/init.d/mysqld
> chkconfig --add mysqld
> chkconfig | grep mysql
> chkconfig mysqld on
> /etc/init.d/mysqld start

10. Root 암호 등록, Daemon  종료
> mysqladmin -u root password 'xxxx'
> /etc/init.d/mysqld stop

* 여기까지 기본 설치(모든 노드)
* 총 4대의 서버중 2대(10.10.0.7, 10.10.0.8)을 MGM+SQL node 로, 2대(10.10.0.9, 10.10.0.10)을 NDB node 로
   설정한다고 가정

11. MGM, Mysql node
mkdir /user/service/mysql-cluster

* Cluster configuration(vi cluster.ini)
[ndbd default]
NoOfReplicas= 2
DataMemory= 512M
IndexMemory= 128M
DataDir= /user/service/mysql-cluster
TimeBetweenWatchDogCheck= 30000
MaxNoOfConcurrentOperations= 10000
MaxNoOfOrderedIndexes = 10000 
MaxNoOfUniqueHashIndexes = 15000 
MaxNoOfTables= 250
[ndb_mgmd default]
DataDir= /user/service/mysql-cluster
[ndb_mgmd]
Id=1
HostName= 10.10.0.7
[ndb_mgmd]
Id=2
HostName= 10.10.0.8
[ndbd]
Id= 3
HostName= 10.10.0.9
[ndbd]
Id= 4
HostName= 10.10.0.10
[mysqld]
Id= 5
HostName= 10.10.0.7
[mysqld]
Id= 6
HostName= 10.10.0.8
[mysqld]
Id= 7
[mysqld]
Id= 8
[tcp default]
PortNumber= 63132

* MySQL configuration
vi /user/service/mysql/my.cnf
[mysqld]
ndbcluster
ndb-connectstring=10.10.0.7,10.10.0.8
[mysql_cluster]
ndb-connectstring=10.10.0.7,10.10.0.8

* Daemon 등록(ndb_mgmd)
echo '/user/service/mysql/libexec/ndb_mgmd -f /user/service/mysql-cluster/cluster.ini' > /etc/init.d/ndb_mgmd
chmod 755 /etc/init.d/ndb_mgmd

12. NDB node

* mkdir /user/service/mysql-cluster

* MySQL configuration
vi /user/service/mysql/my.cnf
[mysqld]
ndbcluster
ndb-connectstring=10.10.0.7,10.10.0.8
[mysql_cluster]
ndb-connectstring=10.10.0.7,10.10.0.8

* Daemon 등록(ndbd)
echo '/user/service/mysql/libexec/ndbd' > /etc/init.d/ndbd
chmod +x /etc/init.d/ndbd
chkconfig --add ndbd
chkconfig ndbd on

13. Service start

<MGM node>
/etc/init.d/ndb_mgmd

<NDB node>
/user/service/mysql/libexec/ndbd --initial => 처음에 한번, 설정 변경시 적용
/etc/init.d/mysqld start

* Remote connect Grant
# mysql -uroot -prootpass
> use mysql;
> grant all privileges on *.* to 'root'@'%' identified by 'rootpass' with grant option;
> flush privileges;

14. Cluster 적용 상태 확인
# ndb_mgm


[MySQL Replication 시 작업] - 앞서 빌드 했던 5.5.4-m3 사용

* Master측
vi my.cnf
[mysqld]
server-id=1
log-bin

/user/service/mysql/bin/mysql_install_db --user=mysql
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO root@"%" IDENTIFIED by 'qrwe1423';
flush privileges;
show master status;

/etc/init.d/mysqld restart

* Slave측
vi my.cnf
log-bin
server-id=2
log-slave-updates
log-warning
max_allow_packet=32M -- sqldump backup/restore시 중요

CHANGE MASTER TO MASTER_HOST='10.10.10.11', MASTER_USER='root', MASTER_PASSWORD='qrwe1423';
* Restart mysql !!!
SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1;
slave start;
show slave status;

* Error 발생시(ERROR 1418 (HY000))

show global variables like 'log_bin_trust_function_creators';
set global log_bin_trust_function_creators = 1;
mysqld 실행시 옵션 추가:  --log-bin-trust-function-creators=1

* show slave status에서 Duplicate PRIMARY ...mysql.tmp_db... blahblah Erro 발생시
master에서 reset master, slave에서 slave stop; reset slave; change master...; DB restart, slave start...

* 동기화 오류로 sync가 동작하기 않을 때의 임시 조치
(1) 1차 조치
<Slave> slave stop ;
<Slave> set global sql_slave_skip_counter=1;
<Slave> slave start ;

(2) 1차 조치로 해결되지 않으면
<Slave> /etc/init.d/mysqld stop
<Slave> ./mysqld_safe --skip-slave
<Slave> MYSQL> stop slave;
<Master> MYSQL> reset master; -- Qery log 파일 초기화
<Slave> MYSQL> reset slave;
<Slave> MYSQL> CHANGE MASTER TO MASTER_HOST='10.10.0.9', MASTER_USER='root', MASTER_PASSWORD='qrwe1423';
<Slave> MYSQL> slave start;
<Slave> MYSQL> start slave;


저작자 표시 비영리 변경 금지
신고
블로그 이미지

Barracuda

Bryan의 MemoLog. 쉽게 익혀 보는 IT 실습과 개념원리, 코딩 세계의 얕은 맛보기들, 평범한 삶 주변의 현상 그리고 進上, 眞想, 진상들


1. Source 다운로드, 압축해제
다운로드 http://dev.mysql.com/get/Downloads/MySQL-5.5/mysql-5.5.4-m3.tar.gz/from/http://mirror.khlug.org/mysql/
# tar xvzf mysql-5.5.4-m3.tar.gz

2. mysql 사용자 추가
# groupadd mysql
# useradd -M -g mysql -s /bin/false mysql

3. Configure Makefile
* ForMysqlBaseDir : /usr/local/ or /dev/local/service/, etc...
# rm -rf /ForMysqlBaseDir

# ./configure --prefix=/ForMysqlBaseDir/mysql --with-mysqld-user=mysql --sysconfdir=/ForMysqlBaseDir/mysql/conf --with-unix-socket-path=/tmp/mysqld/mysql.sock --with-charset=utf8 --with-extra-charsets=all --with-plugins=innobase,myisam,semisync,partition

* Clustering을 위해서는 plugin option에 ndbcluster 추가
  Clustering 을 위해서는 cluster버전 소스를 따로 받을 것

4. Build & Install ( libtool 이 필요할지도... zypper install libtool)
# make && make install

5. cnf 복사, 설정
# cp /ForMysqlBaseDir/mysql/share/mysql/my-huge.cnf /ForMysqlBaseDir/mysql/conf/my.cnf
* cnf 편집, 디렉토리 설정
  또는 미리 준비한 my.cnf 복사(cp /home/myaccound/mysql554/my.cnf /ForMysqlBaseDir/mysql/conf)

* Sample 설정
------------------------------------------------------
[mysqld]
init_connect=SET collation_connection = utf8_general_ci
init_connect=SET NAMES utf8
character-set-server=utf8
collation-server=utf8_general_ci
# Storage engine
default-storage-engine = innodb
# no difference between upper and lowercases
lower_case_table_names = 1
user            = mysql
pid-file        = /tmp/mysqld/mysql.pid
socket          = /tmp/mysqld/mysql.sock
port            = 3306
basedir         = /user/service/mysql
datadir         = /user/service/mysql/data
tmpdir          = /tmp
------------------------------------------------------

6. 초기데이터베이스 생성
# cd /ForMysqlBaseDir/bin
# ./mysql_install_db --user=mysql

7. Directory 생성, 권한 설정
# mkdir -p /ForMysqlBaseDir/mysql/conf
# chown -R root.mysql /ForMysqlBaseDir/mysql
# chown -R mysql.mysql /ForMysqlBaseDir/mysql/data

8. 테스트 실행
> cd /ForMysqlBaseDir/mysql/bin
> ./mysqld_safe --user=mysql &
> ./mysqladmin shutdown

9. Daemon 등록 실행
> cp /ForMysqlBaseDir/mysql/share/mysql/mysql.server /etc/init.d/mysqld
> chkconfig --add mysqld
> chkconfig | grep mysql
> chkconfig mysqld on
> /etc/init.d/mysqld start

10. Root 암호 등록

> mysqladmin -u root password 'xxxx'


저작자 표시 비영리 변경 금지
신고
블로그 이미지

Barracuda

Bryan의 MemoLog. 쉽게 익혀 보는 IT 실습과 개념원리, 코딩 세계의 얕은 맛보기들, 평범한 삶 주변의 현상 그리고 進上, 眞想, 진상들


SET @mac := '00afafafafaf'; -- ==> '00afafafafb0' 로 주소 값을 1증가 시키려고 한다
CONV(@mac, 16, 10) + 1; -- 12자리 mac address string을 BigInt 정수로 변환하여 +1
HEX(정수); -- 정수값을 hexadecimal string으로 변환
LPAD(string, digits, '0'); digits자리수 만큼 왼쪽에 '0'을 채운다
-- 결과
SELECT LPAD(HEX(CONV(@mac, 16, 10)+1), 12, '0');

<참고> SELECT INET_ATON( '168.126.63.1') = 2826845953 -- BigInt
           SELECT INET_NTOA( 2826845953 ) = '168.126.63.1'


저작자 표시 비영리 변경 금지
신고
블로그 이미지

Barracuda

Bryan의 MemoLog. 쉽게 익혀 보는 IT 실습과 개념원리, 코딩 세계의 얕은 맛보기들, 평범한 삶 주변의 현상 그리고 進上, 眞想, 진상들


Linux 패키지 종류가 다양하고 Compiler version과 라이브러리 버전이 워낙 다양하므로
MySQL connector c++ 1.0.5 버전 rpm을 설치하면
컴파일시 libstdc++.so.5 버전이 필요한데 libstdc++.so.6 버전이라서 경고가 뜨는 경우가 있다.
대개는 오류가 주루룩 뜨지만, 가끔 경고만 뜨고 컴파일은 되나 실행하면 거의 core가 생긴다.

이 때는 어쩔수 없이 직접 source 로부터 connector c++을 빌드해서 써야한다(아니면 statifier 같은걸 쓸 수도 있지만 편법이라 별로다)

우선 cmake 2.6.2 버전 이상이 필요하다.
# wget http://www.cmake.org/files/v2.8/cmake-2.8.0.tar.gz
# tar -xvzf 로 압축 풀고
# ./configure
# gmake
# sudo gmake install
cmake 빌드, 설치 완료

MySQL-devel-5.1.43-1.glibc23.x86_64.rpm 다운로드, 설치(cmake 할 때 mysql_config utility를 찾기 때문에
받아서 설치해 둔다)
mysql-connector-c++-1.0.5 받아서 압축 풀고 change directory

# cmake .
# cmake -L (여기서 오류 뜨면 cmake -i 로 해서 wizard mode로 진행할수도 있다)
# make
# make install





저작자 표시 비영리 변경 금지
신고
블로그 이미지

Barracuda

Bryan의 MemoLog. 쉽게 익혀 보는 IT 실습과 개념원리, 코딩 세계의 얕은 맛보기들, 평범한 삶 주변의 현상 그리고 進上, 眞想, 진상들


NetBeans 6.8 에서 C++을 통하여 MySQL을 다루기 위해 Connector C++을 사용하기로 하였다.
처음부터 쉬운 길을 택한 것에 대한 징벌인가 ㅡ_-;; 샘플 소스 받고 빌드 하니
ld 에서 오류가 떨어진다...엉뚱한 버전의 라이브러리를 찾고 난리도 아니다.

Binary 버전(Redhat, SUSE, Max OSX, FreeBSD, Windows 용 다 있는데 Karmic 용은 없네...generic 을 받을 수 밖에...)을
다운로드 받고 tar로 압축 풀고 /usr/include, /usr/lib 에 적당히 복사하고
Library link 정보까지 깔끔하게 업데이트 하기 위해 ldconfig 까지 돌렸는데;;; 안된다.

구글링을 해 보니, MySQL Connector C++ binary는 glibc-2.3 을 통해 컴파일된 거라서 Generic 으로 Binary를 복사 설치할 경우
링크단계에서 잘 넘어가면 기적이지 싶다. 2.3 버전이면 몇년 전거냐...지금 glibc-2.9 가 돌아가는 시대 아닌가.
거기다가 c++은 namespace 를 민감하게 따져서 이런 일이 많이 생기지 싶다.

해결을 위해 두번째 삽질에 들어간다. MySQL Connector/C++ 소스를 자체적으로 컴파일해서 설치에 성공하면 끝이다.
소스 받고, 압축 풀고 설치하려니...cmake로 돌려야 된다 ㅡ_-;; 유명한 Platform independant Cross maker !!!
Synaptic Package manager로 cmake 설치하고
대망의...cmake

> sudo cmake .
> sudo make clean (옳지! 잘 된다)
> sudo make (Shieeeeet 오류 뜬다)

.../mysql_art_resultset.cpp: snprintf was not declared in this scope 어쩌구...

namespace 관련 버그 같은데 몇년 동안 아직 그대로인가...제공된 소스를 직접 뜯어 고쳐야 한다.

.../mysql_art_resultset.cpp
.../mysql_resultbind.cpp
.../test/unit/classes/resultsetmetadata.cpp

위의 3개 파일을 모두 에디터로 열어서 첫 번째 라인에 아래의 include 문을 추가한다.

#include <cstdio>

이제 마무리

> sudo make
> sudo make install

이제 Netbeans에서 빌드/실행하면 훌륭하게 동작 한다.
저작자 표시 비영리 변경 금지
신고
블로그 이미지

Barracuda

Bryan의 MemoLog. 쉽게 익혀 보는 IT 실습과 개념원리, 코딩 세계의 얕은 맛보기들, 평범한 삶 주변의 현상 그리고 進上, 眞想, 진상들


먼저 상태를 확인해 본다.
> mysqladmin -u root -p status

root로 mysql db로 접속
> mysql -u root -p (또는 mysql -uroot -ppassword) 

만약 root 암호를 변경하려면
mysql> update mysql.user set password = password('root-password') where user = 'root';
를 수행한다

사용자를 추가하려면
> mysql -uroot -ppassword mysql

INSERT INTO mysql.user (Host, User, Password) VALUES ('%', 'username', password('password'));
-- %를 쓰지 않고 localhost를 쓸 경우 remote 접속이 불가능하게 되므로 주의
FLUSH privileges;

CREATE DATABASE TestDB;

* 아래는 Grant 옵션을 example로 정리한 것이다
GRANT ALL privileges ON TestDB.* TO 'username'@'localhost' IDENTIFIED BY 'password' WITH GRANT OPTION;
FLUSH privileges;
-- username 사용자에게 TestDB에만 모든 권한을 준다. localhost 의 접속만 허용한다

GRANT SELECT ON TestDB.* TO 'username'@'%.domain.com' IDENTIFIED BY 'password' WITH GRANT OPTION;
FLUSH privileges;
-- username 사용자에게 TestDB에 대해 SELECT 권한을 준다. domain.com 도메인 내에서의 모든 호스트로부터의 접속을 허용한다

GRANT ALL privileges ON TestDB.* TO 'username'@'%' IDENTIFIED BY 'password' WITH GRANT OPTION;
FLUSH privileges;
-- username 사용자에게 TestDB에만 모든 권한을 준다. 모든 호스트로부터의 접속을 허용한다

GRANT ALL privileges ON *.* TO 'root'@'%' IDENTIFIED BY 'password' WITH GRANT OPTION;
FLUSH privileges;
-- root 사용자에게 모든 DB object에 모든 권한을 준다. 모든 호스트로부어의 접속을 허용한다


저작자 표시 비영리 변경 금지
신고
블로그 이미지

Barracuda

Bryan의 MemoLog. 쉽게 익혀 보는 IT 실습과 개념원리, 코딩 세계의 얕은 맛보기들, 평범한 삶 주변의 현상 그리고 進上, 眞想, 진상들


APM에서 UTF-8을 구현하려면 아래 여러 부분을 수정해야 한다.

1. apache 환경파일 편집 (httpd.conf)
2. php 환경파일 편집 (php.ini)
3. mysql 환경파일 편집 (my.cnf)
4. apache, mysql 서비스 재시작
5. mysql에서 캐릭터셋 확인 및 디비생성
6. php 소스코드에 mysql_query("set names utf8;"); 함수 추가
7. php 소스에 한글문자열이 있으면 파일저장할때 UTF-8 파일형식으로 저장
8. 웹브라우즈의 보기-인코딩-UTF-8로 선택

1. /etc/httpd/conf/httpd.conf 에서 캐릭터셋 수정
/*------------
AddDefaultCharset UTF-8

2. /etc/php.ini 에서 캐릭터셋 수정
/*------------
;default_charset = "iso-8859-1"
default_charset = "utf-8"

3. /etc/my.cnf(또는 /etc/mysql/my.cnf) 에서 캐릭터셋 수정
/*------------
[client]
#password = your_password
default-character-set=utf8

[mysqld]
init_connect=SET collation_connection = utf8_general_ci
init_connect=SET NAMES utf8
default-character-set=utf8
character-set-server=utf8
collation-server=utf8_general_ci

[mysql]
default-character-set=utf8

4. 환경변수를 모두 수정후 apache 및 mysql 서비스 재시작
/*------------

5. mysql에서 캐릭터셋 확인
/*------------
# mysql
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 247 to server version: 4.1.10a

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> use test
Database changed
mysql> show variables like 'c%';
+---------+-----------+
| Variable_name | Value |
+---------+-----------+
| character_set_client | utf8 |
| character_set_connection | utf8 |
| character_set_database | utf8 |
| character_set_results | utf8 |
| character_set_server | utf8 |
| character_set_system | utf8 |
| character_sets_dir | /usr/share/mysql/charsets/ |
| collation_connection | utf8_general_ci |
| collation_database | utf8_general_ci |
| collation_server | utf8_general_ci |
| concurrent_insert | ON |
| connect_timeout | 5 |
+---------+-----------+
12 rows in set (0.00 sec)

* MySql에서 데이터베이스 생성
mysql>CREATE DATABASE 디비명 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;


저작자 표시 비영리 변경 금지
신고
블로그 이미지

Barracuda

Bryan의 MemoLog. 쉽게 익혀 보는 IT 실습과 개념원리, 코딩 세계의 얕은 맛보기들, 평범한 삶 주변의 현상 그리고 進上, 眞想, 진상들

1. MySQL 서버의 타임존 설정방법에 관하여


일반적으로 MySQL 설치시 timezone에 대해서 별도 옵션을 지정하지 않으면
태평양표준시인 PST(Pacific Standard Time) 으로 설정된다(PST/PDT 등에 대해서는 여기 참조).

* 참고로 Ubuntu에서 시스템의 표준시를 KST(대한민국 표준시)로 바꾸려면
# ln -sf /usr/share/zoneinfo/Asia/Seoul /etc/localtime

(MySQL 관련한 세부 정보 및 사용법은 http://www.mysqlkorea.com 참조)

DB 서버에 클라이언트로 접속해서 타임존 설정을 확인해 보자


mysql> select @@system_time_zone;
+--------------------+
| @@system_time_zone |
+--------------------+
| PST                |
+--------------------+
1 row in set (0.00 sec)

이 값은 설정 후에는 변경되지 않으며, 따라서 DB엔진 입장에서는 시스템의 설정 값을 가져다 쓰는 것이다.


실제로 MySQL 내애서 사용하기 위한 타임존 값은 서버가 기동중일 때 사용하는 시스템 변수인
time_zone 이라는 값으로, 이 값은


(1)서버 기동시에 --default-time-zone='timezone' 으로 지정하거나
(2) MySQL root 권한을 이용해서


mysql> SET GLOBAL time_zone='timezone;
이라고 설정해 주거나, 또는


(3) 클라이언트 접속시에 이미 설정된 time_zone 변수의 값을 명시적으로 자체적인(세션에 국한된)  time_zone 값으로


mysql> SET time_zone='timezone;


와 같이 세션변수 갑으로 설정하여 사용할 수도 있다.

(2), (3) 의 결과를 아래에서 확인한다.


mysql> select @@global.time_zone, @@session.time_zone;
+--------------------+---------------------+
| @@global.time_zone | @@session.time_zone |
+--------------------+---------------------+
| SYSTEM             | Asia/Seoul          |
+--------------------+---------------------+
1 row in set (0.00 sec)


*** 최초 기본 설정 상태의 time_zone 변수의 값을 확인한 결과
mysql> select @@time_zone;
+-------------+
| @@time_zone |
+-------------+
| SYSTEM      |
+-------------+
1 row in set (0.00 sec)

*** 이 상태에서 Quiery로 시간 값을 조회해 보면,
mysql> select now();
+---------------------+
| now()               |
+---------------------+
| 2009-12-29 04:51:21 |
+---------------------+
1 row in set (0.00 sec)
===> 실제 시간은 21:51:21 이므로 한국 현재 시간 -17 시간이 된다

*** 이제 타임존을 서울로 설정하고 시간을 조회해보면
mysql> set time_zone = 'Asia/Seoul';
Query OK, 0 rows affected (0.00 sec)

mysql> select @@time_zone;
+-------------+
| @@time_zone |
+-------------+
| Asia/Seoul  |
+-------------+
1 row in set (0.00 sec)

mysql> select now();
+---------------------+
| now()               |
+---------------------+
| 2009-12-29 21:57:45 |
+---------------------+
1 row in set (0.00 sec)


'timezone' 의 값은 아래의 여러 가지 포맷으로 줄 수 있으며, 대소문자 구분이 없다(보다 자세한 사항은 MySQLkorea.com의 매뉴얼을 참고한다)
  - 'SYSTEM' 은 타임존이 시스템의 타임존과 동일하도록 설정할 때 쓴다
  - '+10:00' 또는 '-6:00' 과 같이 GMT/UTC기준 offset을 가리키는 문자열로 쓸 수도 있다
  - 'US/Eastern', 'Asia/Seoul' 과 같은 named timezone 형태의 값을 줄 수도 있다.


2. Named timezone 설정 및 사용 방법


이번 내용에서는 위의 named timezone 형태의 값을 시스템 설정파일에서 불러내어 MySQL 시스템오브젝트(테이블)에 등록하고 사용하는 방법을 정리한다.

MySQL을 설치하면 'mysql' 이라는 데이터베이스 내에 time_zone, time_zone_name, time_zone_transition,
time_zone_transition_type, time_zone_leap_second 의 시스템 테이블이 생성되지만 실제로 값이 들어 있지는 않다.

사용하려고 하는 MySQL 데이터베이스가 Global한 서비스를 하게 될 경우의 시간 값이 중요해지는 상황의 IT환경이라면 시스템에 내장되어 있는 타임존 설정값들을 읽어서 위의 테이블들에 등록해 주어야 한다.

MySQL이 설치되는 OS가 Linux, Solaris 계열, BSD계열(물론 Mac OS X도 여기에 해당)이라면
방법은 아주 간단하다. 타임존에 해당하는 설정데이터들은 주로 /usr/share/zoneinfo 디렉토리 아래에 존재하는데 MySQL에서 제공하는 utility query인 mysql_tzinfo_to_sql 을 이용해서 간단히 등록할 수 있다.


root 계정 명령라인에서 아래와 같이 실행하면 된다.


root@ubuntu:/home/somewhere# mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -uroot -prootpassword mysql

이제 데이터베이스에 접속하여 텅 비어 있던 타임존 관련 테이블들에 데이터가 등록 되었는지 확인해 보자.

mysql> select count(*) from mysql.time_zone;
+----------+
| count(*) |
+----------+
|     1724 |
+----------+
1 row in set (0.00 sec)

mysql> select b.name, a.time_zone_id  from mysql.time_zone a, mysql.time_zone_name b where a.time_zone_id = b.time_zone_id and b.name like '%Seoul';
+------------------+--------------+
| name             | time_zone_id |
+------------------+--------------+
| Asia/Seoul       |          287 |
| posix/Asia/Seoul |          862 |
| right/Asia/Seoul |         1437 |
+------------------+--------------+
3 rows in set (0.00 sec)

만약 MySQL이 설치되는 OS가 Windows 계열 또는 HP/UX 등이라면 MySQL 사에서 제공하는
MyISAM 파일들을 http://dev.mysql.com/downloads/timezones.html 에서 다운 받은 다음
MySQL 데이터베이스를 중단시키고 'mysql' 서브디렉토리에 직접 복사해 넣어야 한다.

이제 여기서 설정된 named timezone 값들을 1번에서와 같이 'timezone' 값으로 설정하여
마음대로 사용하면 된다.


- Barracuda -


저작자 표시 비영리 변경 금지
신고
블로그 이미지

Barracuda

Bryan의 MemoLog. 쉽게 익혀 보는 IT 실습과 개념원리, 코딩 세계의 얕은 맛보기들, 평범한 삶 주변의 현상 그리고 進上, 眞想, 진상들