2020. 3. 23. 00:57ㆍ참고
사전 작업
- 미리 두개의 서버에 이중화할 DB를 생성합니다.
- 이중화에 사용할 MySQL 유저를 생성합니다. ex) master(쓰기전용), slave(읽기전용), repluser(이중화 전용)
- 보안을 위해 MySQL 접속은 키 파일로 변경. (mysql_config_editor)
- RSA private key를 사용하여 원격 서버에 ssh 접속(AWS)할 경우 RSA 키 파일 권한은 600 적용.
[참고] 독커 기반 MySQL 리플리케이션
https://jupiny.com/2017/11/07/docker-mysql-replicaiton/
https://teamsmiley.github.io/2018/08/05/docker-mysql-replication/
이제 위 내용을 bash 스크립트로 한방에.
(filename : make_mysql_replication)
#!/bin/bash
if [ -z $1 ]
then
sourceip="your write db(master) server ip"
else
sourceip=$1
fi
if [ -z $2 ]
then
remoteip="your read db(slave) server ip"
else
remoteip=$2
fi
echo "source ip: $sourceip"
echo "remote ip: $remoteip"
if [[ -z $sourceip && -z $remoteip ]]
then
echo "arg1 : remote ip or 'remote' when remote copied"
elif [ $sourceip = "remote" ]
then
# recover db
IFS=' ' read -ra inforepls <<< $(<inforepl);
echo "${inforepls[0]} ${inforepls[1]} ${inforepls[2]}";
IFS=' ' read -ra containerids <<< $(docker ps | grep 'mymon');
echo "${containerids[0]} DROP DATABASE ct";
docker exec ${containerids[0]} mysql --login-path=slave -e 'DROP DATABASE ct';
echo "CREATE DATABASE ct";
docker exec ${containerids[0]} mysql --login-path=slave -e 'CREATE DATABASE IF NOT EXISTS ct';
echo "RECOVER backup.sql";
cat backup.sql | docker exec -i ${containerids[0]} mysql --login-path=slave ct;
echo "STOP SLAVE";
docker exec ${containerids[0]} mysql --login-path=slave -e 'STOP SLAVE';
sql="CHANGE MASTER TO master_host='${inforepls[0]}', master_user='repluser', master_password='replpw', master_log_file='${inforepls[1]}',
master_log_pos=${inforepls[2]}";
echo $sql;
docker exec ${containerids[0]} mysql --login-path=slave -e "$sql";
echo "START SLAVE";
#docker exec ${containerids[0]} mysql --login-path=slave -e 'RESET SLAVE;START SLAVE;';
docker exec ${containerids[0]} mysql --login-path=slave -e 'START SLAVE;';
else
# backup sql
IFS=' ' read -ra containerids <<< "$(docker ps | grep 'mymon')"
docker exec ${containerids[0]} mysqldump --login-path=master ct > backup.sql
echo ${containerids[0]}
# file name
filename=$(docker exec ${containerids[0]} mysql --login-path=master -e "SHOW MASTER STATUS\G" | grep 'File:')
filename=${filename##*:}
echo $filename
# file position
position=$(docker exec ${containerids[0]} mysql --login-path=master -e "SHOW MASTER STATUS\G" | grep 'Position:')
position=${position##*:}
echo $position
echo "$sourceip $filename $position"
echo "$sourceip $filename $position" > inforepl
echo "send backup.sql to $remoteip"
scp -i "private.pem" ./backup.sql ubuntu@$remoteip:/home/ubuntu/mysql &
wait $!
echo "copy makerepl script to $remoteip"
scp -i "private.pem" ./makerepl ubuntu@$remoteip:/home/ubuntu/mysql &
wait $!
echo "copy inforepl to $remoteip"
scp -i "private.pem" ./inforepl ubuntu@$remoteip:/home/ubuntu/mysql &
wait $!
echo "run remote makerepl 'remote'"
tempscript="cd mysql;pwd;. ./makerepl remote"
ssh -i "private.pem" ubuntu@$remoteip $tempscript &
wait $!
fi
동작 설명
쓰기 DB 서버에서 위 스크립트를 실행합니다.
ex) make_mysql_replication src_ip dst_ip
쓰기 DB 서버 IP(src_ip)와 읽기 DB 서버 IP(dst_ip)를 입력하면 쓰기 DB를 덤프하여 읽기 DB에 복사하고 MySQL 리플리케이션 설정을 진행합니다.
사고 발생 시 5분 정도 수작업하는 시간을 5초로 단축하는 효과.
물론 DB가 커지면 쓰기 DB 파일을 읽기에덮어 쓰고 갱신하고 적용하는 방식으로 바뀌지 않을까 예상합니다.
참고
MySQL 외부 접속 사용자 추가
https://linuxism.ustd.ip.or.kr/33
Docker 기반 위에서 동작하는 MariaDB 백업하기
https://elfinlas.github.io/2018/06/09/docker-mariadb-backup/
How to trim whitespace from a Bash variable
https://stackoverflow.com/questions/369758/how-to-trim-whitespace-from-a-bash-variable
Bash 문자열 변수 조작 (자르기, 삭제, 치환)
https://www.snoopybox.co.kr/1811
How to Split String in Bash Script.
https://linuxhandbook.com/bash-split-string/
Bash 배열
https://wiki.kldp.org/HOWTO/html/Adv-Bash-Scr-HOWTO/arrays.html
고급 Bash 스크립팅 가이드
https://wiki.kldp.org/HOWTO/html/Adv-Bash-Scr-HOWTO/index.html
MySQL 복원시 덮어쓰기
http://blog.daum.net/_blog/BlogTypeView.do?blogid=0MwDd&articleno=7617621&_bloghome_menu=recenttext
Bash 초보자를 위한 핵심 요약 정리
https://blog.gaerae.com/2015/01/bash-hello-world.html