MHA 특징

  • 한번의 failover 수행만 가능 ( mha daemon 은 한번의 failover 만 수행 가능 / failover 후 재구성 필요 )
  • candidate master 중 1번째로 지정된 slave 가 master 로 전환되며 기존 master 에 붙어있던 slave 는 new slave 로 전환
  • MHA로 failover가 되면, 모든 slave Node에 down되기 직전의 master Node 데이터 변경 내용을 모두 적용 함.
  • 모든 Node에 최신 데이터 변경 내용을 적용 후 시작 되기 때문에, master - slave 간 데이터 동기화 지연이 클수록 복구 시간이 오래 걸림.
  • vip 를 이동하는 형태로 failover 되므로 서버에서 새로운 마스터 장비의 ip 변경이 불필요함 ( old master 장비에 셋팅되어 있던 VIP를 new master 장비에 셋팅하는 방식 .. Application은 서버 정상 일때나 failover가 된 이후 모두 VIP로 DB에 접속함 )
  • MHA를 통해 DB가 스위칭 될때 일시적으로 기존 연결이 끊어지므로, application 서버는 connection 재구성 예외 처리 로직이 필요

MHA 구성 조건

  • MySQL 서버 최소 2대 이상 필요
  • MySQL Master - Slave Replication 구성 필요
  • Manager Server 1대 필요(Slave 장비에서 구성 가능)
  • VIP 1개
  • test 환경 master : 10.10.10.10 slave : 10.10.10.20 vip : 10.10.10.30

MySQL 설치

아래 rpm 설치 후 진행

yum install -y automake \
binutils bison \
gcc gcc-c++ \
gettext libtool \
make openssl \
openssl openssl-devel \
zlib zlib-devel \
cmake \
gcc-toolset-10-gcc gcc-toolset-10-gcc-c++ gcc-toolset-10-binutils gcc-toolset-10-annobin \
libaio libaio-devel \
perl ncurses-devel \
git redhat-rpm-config rpm-build rpm-sign \
cyrus-sasl cyrus-sasl-devel \
curl curl-devel \
libtirpc-devel \
libudev-devel

MHA 설치

rpm 다운로드 링크

manager : https://github.com/yoshinorim/mha4mysql-manager
node : https://github.com/yoshinorim/mha4mysql-node

mha 구성을 위해 필요한 rpm 설치

dnf config-manager --set-enabled powertools
yum install perl-Module-Install

yum install perl
yum install perl*

yum install perl-DBD-MySQL
yum install perl-Config-Tiny
yum install perl-Log-Dispatch
yum install perl-Parallel-ForkManager
yum install perl-Class-Load
yum install perl-Data-OptList
yum install perl-Date-Manip
yum install perl-Email-Date-Format
yum install perl-Log-Dispatch-FileRotate
yum install perl-Log-Log4perl
yum install perl-Mail-Sender
yum install perl-Mail-Sendmail
yum install perl-MailTools
yum install perl-MIME-Lite
yum install perl-MIME-Types
yum install perl-Params-Util
yum install perl-Params-Validate
yum install perl-Sub-Install
yum install perl-TimeDate
yum install perl-XML-DOM
yum install perl-XML-RegExp

install module 오류
해결 : yum install perl-Module-Install

Can't locate inc/Module/Install.pm in @INC (you may need to install the inc::Module::Install module) (@INC contains: /usr/local/lib64/perl5 /usr/local/share/perl5 /usr/lib64/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib64/perl5 /usr/share/perl5) at Makefile.PL line 1.
BEGIN failed--compilation aborted at Makefile.PL line 1.

perl-Log-Dispatch 오류

powertools 관련 rpm 설치

해결 : dnf config-manager --set-enabled powertools

perl-PAR-Packer-Tk conflicting 오류
yum install perl* 실행 시 아래 에러는 무시 가능

Error:
 Problem 1: conflicting requests
  - nothing provides perl(Tk::ColoredButton) needed by perl-PAR-Packer-Tk-1.052-2.el8.noarch
  - nothing provides perl(Tk::EntryCheck) needed by perl-PAR-Packer-Tk-1.052-2.el8.noarch
  - nothing provides perl(Tk::Getopt) needed by perl-PAR-Packer-Tk-1.052-2.el8.noarch
  - nothing provides perl(Tk::Pod) needed by perl-PAR-Packer-Tk-1.052-2.el8.noarch
 Problem 2: conflicting requests
  - nothing provides perl-HTML-Strip needed by perl-sword-1.8.1-18.el8.x86_64
(try to add '--skip-broken' to skip uninstallable packages or '--nobest' to use not only best candidate packages)

mha node 설치

모든 장비에 설치

tar -zxf mha4mysql-node-0.57.tar.gz
cd mha4mysql-node-0.57
perl Makefile.PL && make && make install

mha4mysql-node-0.57]# perl Makefile.PL && make && make install
*** Module::AutoInstall version 1.06
*** Checking for Perl dependencies...
[Core Features]
- DBI ...loaded. (1.627)
- DBD::mysql ...loaded. (4.023)
*** Module::AutoInstall configuration finished.
Checking if your kit is complete...
Looks good
Writing Makefile for mha4mysql::node
cp lib/MHA/BinlogManager.pm blib/lib/MHA/BinlogManager.pm
cp lib/MHA/BinlogPosFindManager.pm blib/lib/MHA/BinlogPosFindManager.pm
cp lib/MHA/BinlogPosFinderXid.pm blib/lib/MHA/BinlogPosFinderXid.pm
cp lib/MHA/BinlogHeaderParser.pm blib/lib/MHA/BinlogHeaderParser.pm
cp lib/MHA/BinlogPosFinder.pm blib/lib/MHA/BinlogPosFinder.pm
cp lib/MHA/NodeUtil.pm blib/lib/MHA/NodeUtil.pm
cp lib/MHA/BinlogPosFinderElp.pm blib/lib/MHA/BinlogPosFinderElp.pm
cp lib/MHA/SlaveUtil.pm blib/lib/MHA/SlaveUtil.pm
cp lib/MHA/NodeConst.pm blib/lib/MHA/NodeConst.pm
cp bin/filter_mysqlbinlog blib/script/filter_mysqlbinlog
/usr/bin/perl "-Iinc" -MExtUtils::MY -e 'MY->fixin(shift)' -- blib/script/filter_mysqlbinlog
cp bin/apply_diff_relay_logs blib/script/apply_diff_relay_logs
/usr/bin/perl "-Iinc" -MExtUtils::MY -e 'MY->fixin(shift)' -- blib/script/apply_diff_relay_logs
cp bin/purge_relay_logs blib/script/purge_relay_logs
/usr/bin/perl "-Iinc" -MExtUtils::MY -e 'MY->fixin(shift)' -- blib/script/purge_relay_logs
cp bin/save_binary_logs blib/script/save_binary_logs
/usr/bin/perl "-Iinc" -MExtUtils::MY -e 'MY->fixin(shift)' -- blib/script/save_binary_logs
Manifying blib/man1/filter_mysqlbinlog.1
Manifying blib/man1/apply_diff_relay_logs.1
Manifying blib/man1/purge_relay_logs.1
Manifying blib/man1/save_binary_logs.1
Installing /usr/local/share/perl5/MHA/BinlogManager.pm
Installing /usr/local/share/perl5/MHA/BinlogPosFindManager.pm
Installing /usr/local/share/perl5/MHA/BinlogPosFinderXid.pm
Installing /usr/local/share/perl5/MHA/BinlogHeaderParser.pm
Installing /usr/local/share/perl5/MHA/BinlogPosFinder.pm
Installing /usr/local/share/perl5/MHA/NodeUtil.pm
Installing /usr/local/share/perl5/MHA/BinlogPosFinderElp.pm
Installing /usr/local/share/perl5/MHA/SlaveUtil.pm
Installing /usr/local/share/perl5/MHA/NodeConst.pm
Installing /usr/local/share/man/man1/filter_mysqlbinlog.1
Installing /usr/local/share/man/man1/apply_diff_relay_logs.1
Installing /usr/local/share/man/man1/purge_relay_logs.1
Installing /usr/local/share/man/man1/save_binary_logs.1
Installing /usr/local/bin/filter_mysqlbinlog
Installing /usr/local/bin/apply_diff_relay_logs
Installing /usr/local/bin/purge_relay_logs
Installing /usr/local/bin/save_binary_logs
Appending installation info to /usr/lib64/perl5/perllocal.pod

mha manager 설치

manager 장비에서 설치

cd /home/dba_admin/mha-5.7/
tar -zxf mha4mysql-manager-0.57.tar.gz
cd mha4mysql-manager-0.57
perl Makefile.PL && make && make install

mha4mysql-manager-0.57]# perl Makefile.PL && make && make install
*** Module::AutoInstall version 1.06
*** Checking for Perl dependencies...
[Core Features]
- DBI ...loaded. (1.627)
- DBD::mysql ...loaded. (4.023)
- Time::HiRes ...loaded. (1.9725)
- Config::Tiny ...loaded. (2.14)
- Log::Dispatch ...loaded. (2.41)
- Parallel::ForkManager ...loaded. (1.18)
- MHA::NodeConst ...loaded. (0.57)
*** Module::AutoInstall configuration finished.
Checking if your kit is complete...
Looks good
Writing Makefile for mha4mysql::manager
cp lib/MHA/ManagerUtil.pm blib/lib/MHA/ManagerUtil.pm
cp lib/MHA/Config.pm blib/lib/MHA/Config.pm
cp lib/MHA/HealthCheck.pm blib/lib/MHA/HealthCheck.pm
cp lib/MHA/ServerManager.pm blib/lib/MHA/ServerManager.pm
cp lib/MHA/ManagerConst.pm blib/lib/MHA/ManagerConst.pm
cp lib/MHA/ManagerAdmin.pm blib/lib/MHA/ManagerAdmin.pm
cp lib/MHA/FileStatus.pm blib/lib/MHA/FileStatus.pm
cp lib/MHA/MasterFailover.pm blib/lib/MHA/MasterFailover.pm
cp lib/MHA/ManagerAdminWrapper.pm blib/lib/MHA/ManagerAdminWrapper.pm
cp lib/MHA/MasterMonitor.pm blib/lib/MHA/MasterMonitor.pm
cp lib/MHA/MasterRotate.pm blib/lib/MHA/MasterRotate.pm
cp lib/MHA/SSHCheck.pm blib/lib/MHA/SSHCheck.pm
cp lib/MHA/Server.pm blib/lib/MHA/Server.pm
cp lib/MHA/DBHelper.pm blib/lib/MHA/DBHelper.pm
cp bin/masterha_stop blib/script/masterha_stop
/usr/bin/perl "-Iinc" -MExtUtils::MY -e 'MY->fixin(shift)' -- blib/script/masterha_stop
cp bin/masterha_conf_host blib/script/masterha_conf_host
/usr/bin/perl "-Iinc" -MExtUtils::MY -e 'MY->fixin(shift)' -- blib/script/masterha_conf_host
cp bin/masterha_check_repl blib/script/masterha_check_repl
/usr/bin/perl "-Iinc" -MExtUtils::MY -e 'MY->fixin(shift)' -- blib/script/masterha_check_repl
cp bin/masterha_check_status blib/script/masterha_check_status
/usr/bin/perl "-Iinc" -MExtUtils::MY -e 'MY->fixin(shift)' -- blib/script/masterha_check_status
cp bin/masterha_master_monitor blib/script/masterha_master_monitor
/usr/bin/perl "-Iinc" -MExtUtils::MY -e 'MY->fixin(shift)' -- blib/script/masterha_master_monitor
cp bin/masterha_check_ssh blib/script/masterha_check_ssh
/usr/bin/perl "-Iinc" -MExtUtils::MY -e 'MY->fixin(shift)' -- blib/script/masterha_check_ssh
cp bin/masterha_master_switch blib/script/masterha_master_switch
/usr/bin/perl "-Iinc" -MExtUtils::MY -e 'MY->fixin(shift)' -- blib/script/masterha_master_switch
cp bin/masterha_secondary_check blib/script/masterha_secondary_check
/usr/bin/perl "-Iinc" -MExtUtils::MY -e 'MY->fixin(shift)' -- blib/script/masterha_secondary_check
cp bin/masterha_manager blib/script/masterha_manager
/usr/bin/perl "-Iinc" -MExtUtils::MY -e 'MY->fixin(shift)' -- blib/script/masterha_manager
Manifying blib/man1/masterha_stop.1
Manifying blib/man1/masterha_conf_host.1
Manifying blib/man1/masterha_check_repl.1
Manifying blib/man1/masterha_check_status.1
Manifying blib/man1/masterha_master_monitor.1
Manifying blib/man1/masterha_check_ssh.1
Manifying blib/man1/masterha_master_switch.1
Manifying blib/man1/masterha_secondary_check.1
Manifying blib/man1/masterha_manager.1
Installing /usr/local/share/perl5/MHA/ManagerUtil.pm
Installing /usr/local/share/perl5/MHA/Config.pm
Installing /usr/local/share/perl5/MHA/HealthCheck.pm
Installing /usr/local/share/perl5/MHA/ServerManager.pm
Installing /usr/local/share/perl5/MHA/ManagerConst.pm
Installing /usr/local/share/perl5/MHA/ManagerAdmin.pm
Installing /usr/local/share/perl5/MHA/FileStatus.pm
Installing /usr/local/share/perl5/MHA/MasterFailover.pm
Installing /usr/local/share/perl5/MHA/ManagerAdminWrapper.pm
Installing /usr/local/share/perl5/MHA/MasterMonitor.pm
Installing /usr/local/share/perl5/MHA/MasterRotate.pm
Installing /usr/local/share/perl5/MHA/SSHCheck.pm
Installing /usr/local/share/perl5/MHA/Server.pm
Installing /usr/local/share/perl5/MHA/DBHelper.pm
Installing /usr/local/share/man/man1/masterha_stop.1
Installing /usr/local/share/man/man1/masterha_conf_host.1
Installing /usr/local/share/man/man1/masterha_check_repl.1
Installing /usr/local/share/man/man1/masterha_check_status.1
Installing /usr/local/share/man/man1/masterha_master_monitor.1
Installing /usr/local/share/man/man1/masterha_check_ssh.1
Installing /usr/local/share/man/man1/masterha_master_switch.1
Installing /usr/local/share/man/man1/masterha_secondary_check.1
Installing /usr/local/share/man/man1/masterha_manager.1
Installing /usr/local/bin/masterha_stop
Installing /usr/local/bin/masterha_conf_host
Installing /usr/local/bin/masterha_check_repl
Installing /usr/local/bin/masterha_check_status
Installing /usr/local/bin/masterha_master_monitor
Installing /usr/local/bin/masterha_check_ssh
Installing /usr/local/bin/masterha_master_switch
Installing /usr/local/bin/masterha_secondary_check
Installing /usr/local/bin/masterha_manager
Appending installation info to /usr/lib64/perl5/perllocal.pod

MySQL 설정

MySQL 계정 생성

master 및 slave 모두 생성

GRANT ALL PRIVILEGES ON *.* TO 'mhauser'@'%' IDENTIFIED BY 'mhauser비밀번호';
GRANT REPLICATION SLAVE ON *.* TO 'repluser'@'%' IDENTIFIED BY 'repluser비밀번호';

MySQL 설정 변경

relay-log=/log/mysqld_relay_bin
relay_log_purge=0

Mysql binary File Copy

cp /usr/local/mysql/bin/* /usr/bin/ ( ln -s /usr/local/mysql/bin/* /usr/bin/ )

MySQL Backup 및 Restore

backup
mysqldump ... --master-data=2 --user=root -p --port=3306 TestDB > TestDB.sql
restore
mysql -h 10.10.10.20 -u root -p -P 3306 < testDB.sql

MySQL Replication 구성

slave에서 실행

change master to
master_host='10.10.10.10',
master_port=3306,
master_user='repluser',
master_password='repluser비밀번호',
master_log_file='mysql-bin.000XXX', – master 백업 파일에서 참고
master_log_pos= XXX; – master 백업 파일에서 참고

start slave;

OS 설정

모든 장비에서 실행

유저 생성

adduser mhauser

passwd mhauser
usermod -G mysql mhauser

유저 기간 만료 확인 및 수정

chage -l mhauser | grep -i "^password expires"

위의 값이 never가 아닐 경우 아래 명령어로 영구화 필요

chage -E -1 -M 99999 "mhauser"

mha directory 생성

mhatest의 경우는 서비스명이나 서비스코드 형태를 사용

mkdir -p /mha/{log,conf,remote,scripts,work}
mkdir /mha/work/mhatest
mkdir /mha/remote/mhatest
chown -R mhauser.mhauser /mha
chmod -R 750 /mha

mhauser 권한 부여

~]# vi /etc/ssh/sshd_config

아래 부분 주석해제 후 저장

RSAAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys


-- visudo 명령어로 암호없이 ssh계정 사용하기위해 아래 부분 변경 
(ssh 통신 시 암호없이 통신을하기 위한 방법이며, 보안을 위해 VIP 알리아스를 만든 후 
ohnew 계정은 VIP 알리아스만 실행하고자 변경)

~]# visudo

23라인 부근의 아래 커멘트 부근에 아래 명령어 추가 
## Command Aliases
## These are groups of related commands...

Cmnd_Alias VIP = /sbin/ifconfig, /sbin/arping


57라인 부근에 이부분 주석 처리
# Defaults requiretty


105 라인 부근에 아래 부분 추가
## Allow root to run any commands anywhere
mhauser ALL=(ALL) NOPASSWD: VIP

mha user ssh 설정

su - mhauser ( 반드시 mhauser 계정으로 실행 )
ssh-keygen -t rsa ( 암호없이 생성을 위해 enter 연타 )

# source 서버에서 target 서버로 전달
ssh-copy-id mhauser@10.10.10.10
ssh-copy-id mhauser@10.10.10.20

================================================================================================================
 ~]$ ssh-copy-id mhauser@10.10.10.10
The authenticity of host '10.10.10.10 (10.10.10.10)' can't be established.
ECDSA key fingerprint is 38:58:d9:71:8a:ed:89:af:1d:c8:d1:69:e0:e1:b8:dd.
Are you sure you want to continue connecting (yes/no)? yes
/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
mhauser@10.10.10.10's password:
/etc/profile.d/logging.sh: line 7: ifconfig: command not found
Number of key(s) added: 1
Now try logging into the machine, with: "ssh 'mhauser@10.10.10.10'"
and check to make sure that only the key(s) you wanted were added.
================================================================================================================

# 접속 테스트 ( 모든 장비 Node, Manager 간 비밀번호 없이 접속 가능 )
ssh mhauser@10.10.10.10
ssh mhauser@10.10.10.20

VIP 설정

master node 장비에서만 실행

-- IP 확인
~]# ifconfig
bond0: flags=5187<UP,BROADCAST,RUNNING,MASTER,MULTICAST> mtu 1500
inet 10.10.10.10 netmask 255.255.255.0 broadcast 10.10.10.255
.....

-- VIP 설정
~]# ifconfig bond0:0 10.10.10.30 up netmask 255.255.255.128 up

-- VIP 적용
~]# arping -c3 -D -I bond0 -s 10.10.10.30 -U 10.10.10.1
ARPING 10.10.10.1 from 10.10.10.10 bond0
Unicast reply from 10.162.131.10 [00:00:5E:00:01:15] 0.770ms
Sent 1 probes (1 broadcast(s))
Received 1 response(s)
[root@Nmsprofdb01 ~]#

-- VIP 확인
[root@Nmsprofdb01 ~]# ifconfig
bond0: flags=5187<UP,BROADCAST,RUNNING,MASTER,MULTICAST> mtu 1500
inet 10.10.10.10 netmask 255.255.255.0 broadcast 10.10.10.255
.....
bond0:0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.10.10.30 netmask 255.0.0.0 broadcast 10.255.255.255

master_ip_failover 파일 생성

manager 장비 /mha/script/master_ip_failover 파일 생성 후 추가

#!/usr/bin/env perl
# use strict;
# use warnings FATAL => 'all';
use Getopt::Long;
my (
$command, $ssh_user, $orig_master_host, $orig_master_ip, $orig_master_ssh_port,
$orig_master_port, $new_master_host, $new_master_ip, $new_master_port, $new_master_user,
$new_master_password, $new_master_ssh_port
);
my $vip = '10.10.10.30'; # Virtual IP
my $key = "0";
my $devicenm = "bond0";
my $ssh_start_vip = "sudo /sbin/ifconfig $devicenm:$key $vip netmask 255.255.255.128 up";
my $ssh_stop_vip = "sudo /sbin/ifconfig $devicenm:$key down";
my $ssh_mac_refresh = "sudo /sbin/arping -c3 -D -I $devicenm -s 10.10.10.30 10.10.10.1";
GetOptions(
'command=s' => \$command,
'ssh_user=s' => \$ssh_user,
'orig_master_host=s' => \$orig_master_host,
'orig_master_ip=s' => \$orig_master_ip,
'orig_master_port=i' => \$orig_master_port,
'orig_master_ssh_port=i' => \$orig_master_ssh_port,
'new_master_host=s' => \$new_master_host,
'new_master_ip=s' => \$new_master_ip,
'new_master_port=i' => \$new_master_port,
'new_master_user=s' => \$new_master_user,
'new_master_password=s' => \$new_master_password,
'new_master_ssh_port=i' => \$new_master_ssh_port,
);
exit &main();
sub main {
print "\n\nIN SCRIPT TEST====$ssh_stop_vip==$ssh_start_vip===\n\n";
if ( $command eq "stop" || $command eq "stopssh" ) {
# $orig_master_host, $orig_master_ip, $orig_master_port are passed.
# If you manage master ip address at global catalog database,
# invalidate orig_master_ip here.
my $exit_code = 1;
eval {
print "Disabling the VIP on old master: $orig_master_host \n";
&stop_vip();
$exit_code = 0;
};
if ($@) {
warn "Got Error: $@\n";
exit $exit_code;
}
exit $exit_code;
}
elsif ( $command eq "start" ) {

# all arguments are passed.
# If you manage master ip address at global catalog database,
# activate new_master_ip here.
# You can also grant write access (create user, set read_only=0, etc) here.
my $exit_code = 10;
eval {
print "Enabling the VIP - $vip on the new master - $new_master_host \n";
&start_vip();
$exit_code = 0;
};
if ($@) {
warn $@;
exit $exit_code;
}
exit $exit_code;
}
elsif ( $command eq "status" ) {
print "Checking the Status of the script.. OK \n";
`ssh -p $orig_master_ssh_port $ssh_user\@$orig_master_host \" $ssh_start_vip \"`;
exit 0;
}
else {
&usage();
exit 1;
}
}
# A simple system call that enable the VIP on the new master
sub start_vip() {
`ssh -p $new_master_ssh_port $ssh_user\@$new_master_host \" $ssh_start_vip \"`;
`ssh -p $new_master_ssh_port $ssh_user\@$new_master_host \" $ssh_mac_refresh\"`;
}
# A simple system call that disable the VIP on the old_master
sub stop_vip() {
`ssh -p $orig_master_ssh_port $ssh_user\@$orig_master_host \" $ssh_stop_vip \"`;
}
sub usage {
print
"Usage: master_ip_failover --command=start|stop|stopssh|status --orig_master_host=host --orig_master_ip=ip --orig_master_port=port --new_master_host=host --new_master_ip=ip --new_master_port=port\n";
}

scripts/master_ip_failover 실행 권한 추가

chmod +x /mha/scripts/master_ip_failover

conf 파일 추가

/mha/conf/mhatest.conf 파일 생성 후 작성

[server default]
# mysql user and password
user=mhauser
password=mhauserDB비밀번호
ssh_user=mhauser
repl_user=repluser
repl_password=repluserDB비밀번호

# manager log file
manager_log=/mha/log/mhatest.log

# working directory on the manager
manager_workdir=/mha/work/mhatest/

# working directory on MySQL servers
remote_workdir=/mha/remote/mhatest/

master_binlog_dir=/log/

master_ip_failover_script=/mha/scripts/master_ip_failover --orig_master_ssh_port=22 --new_master_ssh_port=22

[server1]
hostname=10.10.10.10
port=59306
candidate_master=1

[server2]
hostname=10.10.10.20
port=59306
candidate_master=1

#no_master=1
#ignore_fail=1

relay log 삭제 스크립트 추가

relay log purge 스크립트 등록
vi /mha/scripts/relay_log_purge.sh
chmod 755 /mha/scripts/relay_log_purge.sh

#!/bin/sh

source ~/.bash_profile

USER=mhauser
PORT=$1
PASSWORD='mhauser패스워드'


# Slave Check
v_mysql=`which mysql`
SLAVE_STATUS=`$v_mysql -u root -p XXXX -P 3306 -e 'show slave status\G;' | grep Running | grep Yes | wc -l`

if [ $SLAVE_STATUS -lt 2 ]
then
echo 'The master does not execute purge...' >> /mha/log/purge_relay.log
exit;
fi

/usr/local/bin/purge_relay_logs --user=$USER --port=$PORT --password=$PASSWORD --disable_relay_log_purge >> /mha/log/purge_relay.log 2>&1

crontab 등록

crontab -e

######################################################################
#
# Relay Log Purge Daily
#
######################################################################
0 5 * * * /mha/scripts/relay_log_purge.sh 3306

perl 실행 권한 부여

chmod 755 /usr/bin/perl 

MHA 설정 Test

mhauser OS 계정으로 실행

masterha_check_ssh

ll /usr/bin/perl
su - mhauser
masterha_check_ssh --conf=/mha/conf/mhatest.conf


~]$ masterha_check_ssh --conf /mha/conf/mhatest.conf
Thu Jun 1 18:52:28 2017 - [warning] Global configuration file /etc/masterha_default.cnf not found. Skipping.
Thu Jun 1 18:52:28 2017 - [info] Reading application default configurations from /mha/conf/mhatest.conf..
Thu Jun 1 18:52:28 2017 - [info] Reading server configurations from /mha/conf/mhatest.conf..
Thu Jun 1 18:52:28 2017 - [info] Starting SSH connection tests..
Thu Jun 1 18:52:28 2017 - [debug]
Thu Jun 1 18:52:28 2017 - [debug] Connecting via SSH from mhauser@10.10.10.20(10.10.10.20:22) to mhauser@10.10.10.10(10.10.10.10:22)..
Thu Jun 1 18:52:28 2017 - [debug] ok.
Thu Jun 1 18:52:29 2017 - [debug]
Thu Jun 1 18:52:28 2017 - [debug] Connecting via SSH from mhauser@10.10.10.20(10.10.10.20:22) to mhauser@10.10.10.10(10.10.10.10:22)..
Thu Jun 1 18:52:29 2017 - [debug] ok.
Thu Jun 1 18:52:29 2017 - [info] All SSH connection tests passed successfully.
===============================================================================================================

masterha_check_repl

ll /usr/bin/perl
su - mhauser
masterha_check_repl --conf=/mha/conf/mhatest.conf


~]$ masterha_check_repl --conf=/mha/conf/mhatest.conf
Mon Jun 5 14:15:35 2017 - [warning] Global configuration file /etc/masterha_default.cnf not found. Skipping.
Mon Jun 5 14:15:35 2017 - [debug] MHA::MasterMonitor version 0.56.
Mon Jun 5 14:15:35 2017 - [debug] Connecting to servers..
Mon Jun 5 14:15:36 2017 - [debug] Connected to: 10.10.10.10(10.10.10.10:59306), user=mhauser
Mon Jun 5 14:15:36 2017 - [debug] Connected to: 10.10.10.20(10.10.10.20:59306), user=mhauser
Mon Jun 5 14:15:36 2017 - [debug] Comparing MySQL versions..
Mon Jun 5 14:15:36 2017 - [debug] Comparing MySQL versions done.
Mon Jun 5 14:15:36 2017 - [debug] Connecting to servers done.
.....
Checking the Status of the script.. OK
Bad port 'mhauser@10.10.10.20'
Mon Jun 5 14:15:38 2017 - [debug] OK.
Mon Jun 5 14:15:38 2017 - [warning] shutdown_script is not defined.
Mon Jun 5 14:15:38 2017 - [debug] Disconnected from 10.10.10.10(10.10.10.10:59306)
Mon Jun 5 14:15:38 2017 - [debug] Disconnected from 10.10.10.20(10.10.10.20:59306)
Mon Jun 5 14:15:38 2017 - [debug] Got exit code 0 (Not master dead).
MySQL Replication Health is OK.

Mysql 버전 확인 부분 오류 수정

~]$ masterha_check_repl --conf=/mha/conf/mhatest.conf

## 에러 내용
Fri Nov  4 11:30:59 2022 - [warning] Global configuration file /etc/masterha_default.cnf not found. Skipping.
Fri Nov  4 11:30:59 2022 - [info] Reading application default configuration from /mha/conf/mhatest.conf..
Fri Nov  4 11:30:59 2022 - [info] Reading server configuration from /mha/conf/mhatest.conf..
Fri Nov  4 11:30:59 2022 - [info] MHA::MasterMonitor version 0.57.
Fri Nov  4 11:31:00 2022 - [error][/usr/local/share/perl5/MHA/MasterMonitor.pm, ln427] Error happened on checking configurations. Redundant argument in sprintf at /usr/local/share/perl5/MHA/NodeUtil.pm line 190.
Fri Nov  4 11:31:00 2022 - [error][/usr/local/share/perl5/MHA/MasterMonitor.pm, ln525] Error happened on monitoring servers.
Fri Nov  4 11:31:00 2022 - [info] Got exit code 1 (Not master dead).

## 수정 방법
/usr/local/share/perl5/MHA/NodeUtil.pm 파일의 190번 라인을 아래 형태로 수정

~]# vi  /usr/local/share/perl5/MHA/NodeUtil.pm

182 sub parse_mysql_version($) {
183   my $str = shift;
184   my $result = sprintf( '%03d%03d%03d', $str =~ m/(\d+)/g );
185   return $result;
186 }
187
188 sub parse_mysql_major_version($) {
189   my $str = shift;
190   my $result = sprintf( '%03d%03d%03d', $str =~ m/(\d+)/g );
191   return $result;
192 }

mha 실행

su - mhauser

nohup masterha_manager --conf=/mha/conf/mhatest.conf > /mha/log/mhatest.log 2>&1 &

현재 지원되는 SQL Server에 사용 가능한 최신 업데이트

다음 각 링크는 적용 가능한 모든 제품 및 기술에 대한 정보를 제공합니다.

버전 최신 서비스 팩 최신 GDR 최신 누적 업데이트 전체 버전 정보 일반 지침
SQL Server 2019 없음 GDR(15.0.2095.3 - 2022년 6월) 2019용 CU17(15.0.4249.2 - 2022년 8월)
CU16 + GDR(15.0.4236.7 - 2022년 6월)
SQL Server 2019 빌드 SQL Server 2019 설치
SQL Server 2017 없음 GDR(14.0.2042.3 - 2022년 6월) 2017년 CU31(14.0.3456.2 - 2022년 9월)
CU29 + GDR(14.0.3445.2 - 2022년 6월)
SQL Server 2017 빌드 SQL Server 2017 설치
SQL Server 2016 Azure Connect 팩 (13.0.7000.253 - 2022년 5월)
SP3(13.0.6300.2 - 2021년 9월)
SP2(13.0.5026.0 - 2018년 4월)
SP1(13.0.4001.0 - 2016년 11월)
Azure Connect용 GDR(13.0.7016.1 - 2022년 6월)
SP3용 GDR(13.0.6419.1 - 2022년 6월)
SP2용 GDR(13.0.5108.50 - 2022년 6월)
SP1용 GDR(13.0.4259.0 - 2019년 7월)
RTM용 GDR(13.0.1745.2 - 2018년 1월)
SP2용 CU17 + GDR(13.0.5893.48 - 2022년 6월)
2016 SP2용 CU17(13.0.5888.11 – 2021년 3월)
SP1용 CU15 + GDR(13.0.4604.0 - 2019년 7월)
SP1용 CU15(13.0.4574.0 - 2019년 5월)
RTM용 CU9(13.0.2216.0 – 2017년 11월)
SQL Server 2016 빌드 SQL Server 2016 설치
SQL Server 2014 SP3(12.0.6024.0 - 2018년 10월)
SP2(12.0.5000.0 - 2016년 7월)
SP1(12.0.4100.1 - 2015년 5월)
SP3용 GDR(12.0.6169.19 - 2022년 6월)
SP2용 GDR(12.0.5223.6 - 2019년 7월)
SP1용 GDR(2017년 8월)
MS 15-058(2015년 7월)
SP3용 CU4 + GDR(12.0.6439.10 – 2022년 6월)
SP3용 CU4(12.0.6329.1 – 2019년 7월)
SP2용 CU18(12.0.5687.1 - 2019년 7월)
SP1용 CU13(12.0.4522.0 - 2017년 8월)
SQL Server 2014 빌드 SQL Server 2014 설치
SQL Server 2012 SP4(11.0.7001.0 - 2017년 9월)
SP3(11.0.6020.0 - 2015년 11월)
SP2(11.0.5058.0 - 2014년 6월)
SP1(11.0.3000.00 - 2012년 11월)
SP4용 GDR(11.0.7507.2 - 2021년 1월)
SP3용 GDR(2018년 1월)
MS 16-136(2016년 11월)
MS 15-058(2015년 12월)
SP3용 CU10(11.0.6607.3 - 2017년 8월)
SP2용 CU16(11.0.5678.0 - 2017년 1월)
SP1용 CU16(11.0.3487.0 - 2015년 5월)
SQL Server 2012 SQL Server 2012 설치
SQL Server 2008 R2 SP3(10.50.6000.34 - 2014년 9월)
SP2(10.50.4000.0 - 2012년 7월)
SP3용 GDR(2018년 1월)
MS 15-058(2015년 7월)
없음 SQL Server 2008 R2 빌드 SQL Server 2008 R2 SP3 설치
SQL Server 2008 SP4(10.0.6000.29 - 2014년 9월)
SP3(10.00.5500.00 - 2011년 10월)
SP4용 GDR(2018년 1월)
MS 15-058(2015년 7월)
없음 SQL Server 2008 빌드 SQL Server 2008 서비스

Query 형태

Example

t1 테이블과 t2 테이블의 조건에 해당하는 행 모두 삭제 ( t1, t2 테이블 동시 삭제 )

  t1 id값이 1인 행 삭제

  21 id값이 1인 행 삭제

Delete 실행

결과

참고

https://www.mysqltutorial.org/mysql-delete-join/

MSSQL  패치 버전 선정 기준

2017 이상의 버전은 Service Packs 없이 CU로만 업데이트가 진행됨

CU 패치의 경우 대부분 버그 및 보안 관련 내용이 진행됨

CU 패치 이후 버그가 확인되면 "WithDrawn" 문구가 포함되며 대부분 한달 이내로 수정 버전이 패치됨.

2019 

CU18 버전이 최신, 최신 버전 패치일이 얼마 되지 않기 때문에 CU17을 선정.

링크 : https://sqlserverbuilds.blogspot.com/#sql2019x

CU 17 다운로드

Recommended를 선택 시, 가장 최신 버전(현 시점 CU18)이 선택되기 때문에 두번째 메뉴를 클릭

CU 17 다운로드 링크 : https://support.microsoft.com/en-us/topic/kb5016394-cumulative-update-17-for-sql-server-2019-3033f654-b09d-41aa-8e49-e9d0c353c5f7#obtain

 

2016

Service Pack 3를 패치 하거나, Service Pack 2 및 CU 17 버전을 패치

CU 17 버전의 경우 확인 시점 기준 약 1년간 이슈 없이 서비스됨.

링크 : https://sqlserverbuilds.blogspot.com/#sql2016x

CU 17 다운로드

Recommended를 선택 시, 가장 최신 버전(현 시점 CU18)이 선택되기 때문에 두번째 메뉴를 클릭

CU 17 다운로드 링크 : https://support.microsoft.com/en-us/topic/kb5001092-cumulative-update-17-for-sql-server-2016-sp2-5876a4d6-59ac-484a-93dc-4be456cd87d1

원인

jemalloc 설치가 되지 않아 발생

 

해결

jemalloc 설치

  centOS 7.0 이하 : yum -y install jemalloc

  centOS 7.0 이상 : yum -y install epel-release

                               yum -y install varnish

jemalloc make

  redis 폴더의 deps로 이동

  make hiredis jemalloc linenoise lua

redis install

  redis 폴더의 src로 이동

  make & make install

MongoDB의 쓰기( UPDATE와 DELETE ) 오퍼레이션은 도큐먼트 단위의 원자성( Atomicity )만 제공한다.

하나의 쓰기 오퍼레이션으로 여러 도큐먼트를 변경하거나 삭제하더라도, MongoDB 서버는 내부적으로 하나의 트랜잭션으로 하나의 도큐먼트만 처리하는 방식으로 작동한다.

 

그래서 MongoDB 서버에서 일반적으로 쓰기 오퍼레이션으로 여러 도큐먼트를 변경하면, 오퍼레이션이 완료되기도 전에 먼저 변경된 데이터들은 다른 컨넥션에서 즉시 조회를 할 수 있게 된다.

 

 

만약 하나의 UPDATE나 DELETE 명령이 완료되기 전까지는 다른 커넥션에서 변경 내용을 확인하지 못하게 하려면, 격리된 UPDATE 또는 DELETE 또는 REMOVE 명령을 사용해야 한다.

 

다음 예제는 UPDATE와 REMOVE 명령을 사용하는 방법을 보여주고 있다.

UPDATE 명령과 REMOVE 명령 모두 업데이트 대상 도큐먼트를 검색하는 조건과 함께 "$isolated : 1" 옵션을 사용하면 된다.

mongo> db.users.remove( { score : { $lt : 50 }, $isolated : 1 } );

mongo> db.users.update(
      { score : { $gt : 90 }, $isolated : 1 }
    , { $set : { grade : "A" } }
    , { multi : true }
);

 

MongoDB 서버는 UPDATE나 REMOVE 명령에 $isolated 옵션을 사용하면, 데이터 변경 작업이 완료될 때까지 다른 컨넥션이 변경 중인 데이터를 조회할 수 없다.

 

즉 UPDATE나 REMOVE 명령이 10건의 도큐먼트를 변경해야 하는데, 작업 도중 에러가 발생하면 MongoDB 서버가 이미 처리된 도큐먼트에 대해서 롤백을 수행하거나 하지는 않는다.

 

$isolated 옵션은 정상적으로 처리될 때에만 필요한 격리 수준을 보장해 준다.

 

※ 주의

MongoDB의 $isolated 옵션은 꼭 필요한 경우에만 제한적으로 사용할 것을 권장한다. MongoDB 서버는 $isolated 옵션을 사용한 업데이트 명령의 격리 수준을 보장하기 위해서 업데이트 대상 컬렉션에 대해서 쓰기 잠금( Exclusive Lock )을 걸고 처리를 한다. 이는 MongoDB 엔진이 컬렉션 레벨의 잠금을 걸기 때문에 MMAPv1 스토리지 엔진뿐만 아니라 도큐먼트 레벨의 잠금을 지원하는 WiredTiger 스토리지 엔진에서도 동일하게 작동한다. 즉 $isolated 옵션을 설정한 UPDATE나 REMOVE 명령이 수행되는 동안에는 다른 컨넥션에서 어떤 쿼리나 데이터 변경 명령을 실행하지 못한다. 만약 읽고 쓰기가 빈번하게 실행되는 컬렉션에 대해서 $isolated 옵션을 설정한 UPDATE나 DELETE 명령이 실행되면 다른 컨넥션의 수많은 쿼리나 업데이트 명령들이 일시적으로 처리를 멈추게 되고, 응용 프로그램은 데이터베이스의 응답을 받지 못해서 더 많은 쓰레드나 컨넥션을 생성하면서 처리 불가 상태로 빠지게 될 가능성이 높다.

 

참고 : https://secretartbook.tistory.com/6

---  MEMORY  ----

 * innodb buffer pool size를 크게 가져갈수록 디스크 IO를 줄일수 있음
 * 일반적으로 OS의 70&~80% 사용

 

---  CPU  ----

 * 하이퍼 스레딩 활성화
 * 일반적으로 CPU보다는 memory 및 Disk IO를 올리는것이 성능 향상에 효과적
 * MySQL 버전에 따른 코어수 제한 
   - MySQL 5.1 : ~ 4코어 
   - MySQL 5.5 : ~ 16코어 
   - MySQL 5.6 : ~ 36 쓰레드(Core)
   - MySQL 5.7 : ~ 64 쓰레드(32 Core-HT)
   - MySQL 8.0 : ~ 100 쓰레드(48 Core-HT)

 

---  Disk  ----

 * SSD, NVMe 사용시 innodb_page_size=4K, innodb_flush_neighbors=0 로 사용을 추천
 * innodb datadir, tmp 파일 및 undo 로그 모두 Ramdom IO가 발생함으로 SSD로 할당
 * 로그(빈로그 등등)의 경우 Sequnential IO가 발생함으로 디스크로 할당
 * innodb_io_capacity
   - innodb가 사용 가능한 I/O 대역폭
   - 너무 큰 값을 사용한다고 해서 많은 이점이 있지는 않음( 20000 이상은 권장되지 않음 )
   - 쓰기 작업이 많은 시스템은 높은 값이 유리 ( Ex LogDB )
   - 쓰기 작업이 적은 시스템은 낮은 값이 유리
 * innodb_io_capacity_max
   - innodb가 사용 가능한 I/O 최대 대역폭 
   - 일반적으로 innodb_io_capacity 값의 두배로 설정
 

---  OS  ---- 

 * MySQL은 Linux 에 최적화 되어 있다. 
 * MySQL 이외에 OS에서 설정을 해줘야되는 부분
   - ulimit -n, 파일 수 제한 (connections, open tables, ...)
   - ulimit -u, 스레드 수 제한 (connections, InnoDB background threads, event scheduler, ....)
 * NUMA 기반 서버의 경우 innodb_numa_interleave를 1로 설정 
   - mysql과 os의 numa 설정이 다른경우, 노드간 메모리 사용 불균형으로 swap이 발생하여 성능 이슈가 발생할 가능성이 있음.
 * InnoDB를 사용하는 경우 OS의 파일시스템 캐시를 사용하지 않는다.( 더블 버퍼링을 막아 메모리를 효율적으로 사용 )
   - set inndbo_flush_method=O_DIRECT
   - innodb pool이 훨씬 고도화된 형태로 동작

---  ETC   ---

 * innodb_log_file_size(redo log 사이즈)
   - 크게 가져 갈수록 체크포인트 동작이 덜 필요하여 성능에 좋으나, 너무 크게 설정하는 경우 DB 복구 시간이 느려짐.
   - 운영서버 최소 512MB 이상 권장.   
 * innodb_log_files_in_group(리두 로그 파일 갯수)
   - Default는 2이지만 일반적으로 3으로 운영
 * skip-name-resolve
   - client에서 server로 접속시 dns lookup 과정을 생략
   - dns 서버가 느리거나 장애 발생시 DB 접속문제가 발생하는 것을 해결할 수 있음.
 * innodb_write_io_threads / innodb_read_io_threads
   - SHOW ENGINE INNODB STATUS 에서 지연된 쓰기/읽기 요청이 64개 이상인 경우 값을 올려주는것이 좋음.
 * innodb_log_file_size
   - 로그 파일 크기
   - innodb_buffer_pool_size의 25% 정도로 유지
   - 이 값이 클수록 버퍼 풀에서 체크포인트 발생 빈도가 낮음.
   - 이 값이 클수록 크래시 발생시 복구가 그만큼 느려짐.

 

---  ACID 유지  ---   

 * innodb_flush_log_at_trx_commit = 1 
   - commit마다 리두 로그에 기록하고 디스크에 flush
   - ACID가 보장이 되지만, 디스크 I/O가 높음
   - 성능 위주 DB로 설정하고 싶은 경우 0
 * sync_binlog = 1
   - 트랜잭션이 커밋되기 전에 이진 로그를 디스크에 동기화
   - 정전 및 운영 체제 충돌에도 ACID가 보장되지만, 디스크 I/O가 높음
   - 성능 위주 DB로 설정하고 싶은 경우 0
 * innodb_doublewrite = 1
   - innoDB의 페이지를 쓰기 전에 버퍼 풀에서 플러시된 페이지를 중복해서 저장
   - MySQL Crash 복구 중에 이중으로 쓰여진 버퍼에서 페이지 복사본을 찾아 복구 진행
   - 데이터 무결성을 유지할 수 있으나, 이중으로 데이터를 기록하여 I/O가 높음. (이중으로 기록 하지만 2배의 I/O가 발생하지는 않음)
   - 성능 위주 DB로 설정하고 싶은 경우 0   

 

---  Buffer per Client Connections  ---

 * connection(세션)당 할당되는 버퍼들 
   - read_buffer_size : Sequnential scan (full table scan)을 사용할 때 사용하는 버퍼 
   - read_rnd_buffer_size : 정렬 작업후, 정렬된 순서대로 데이터를 다시 읽어 들일 때 사용하는 버퍼 
   - join_buffer_size : 인덱스를 사용하지 않는 조인에 사용되는 버퍼, Session level에서 join 단위로 생성
   - sort_buffer_size : 인덱스를 사용하지 않는 정렬에 사용하는 버퍼 
   - binlog_cache_size (if binary logginigs is enabled)
 * connection이 많을 경우 이 버퍼들이 메모리를 점유하기 때문에 크게 세팅하면 안된다.
   - 만약 크게 필요한 경우가 있다면 필요한 세션에서만 크게 잡아서 사용한다. 

 

참고

https://iamwhat.tistory.com/entry/MySQL-%ED%8F%AC%ED%8D%BC%EB%A8%BC%EC%8A%A4-%ED%8A%9C%EB%8B%9D

   

RUNAS

Run as different user' 클릭 이후 계정 정보를 입력

CMD Line

runas.exe /netonly /user:myidomain\domain.useracc "Ssms.exe"

확인

 

참고

https://jasonbrimhall.info/2018/06/28/use-ssms-with-a-different-windows-account-back-to-basics/

MSSQL AlwaysOn 환경에서는 Job Agent에 등록시, Active에서만 Job Schedule이 실행되어야 한다.

dmv 정보를 활용하여 Active 환경을 체크 후 Job을 실행 하도록 설정 필요

 

설정

DECLARE @ROLE NVARCHAR(100)

IF SERVERPROPERTY ('IsHadrEnabled') = 1
BEGIN
    SELECT @ROLE=ARS.role_desc  -- Replica Role
    FROM sys.dm_hadr_availability_replica_cluster_states AS RCS
    INNER JOIN sys.dm_hadr_availability_replica_states AS ARS
    ON ARS.replica_id = RCS.replica_id
    WHERE RCS.replica_server_name = HOST_NAME()
END

IF @ROLE IS NULL OR @ROLE = 'PRIMARY'
BEGIN

    -- Job 실행 구문 추가

END

 

예외 사항

Secondary 환경에서 Job을 등록하였을때 아래와 같이 실행이 되지 않는 경우가  발생

아래는 Job Schedule의 로그 화면

Secondary 환경에서 동기화 중인 DB 선택 시, 아래와 같은 에러 발생

해결

Active 장비의 AlwaysON 속성에 들어가서 '읽을 수 있는 보조(E)' 항목을 '예'로 변경

서버가 잠겨 있거나 비정상적인 상태로 SQL Server에 연결이 되지 않는 경우

 

DAC 접근을 위한 설정

remote admin connection 옵션을 활성화

SSMS -> DB 인스턴스 우클릭 -> 패싯(A) 클릭

패싯 속성(P) -> 'RemoteDacEnabled' Ture 설정

스크립트 적용

SP_CONFIGURE 'remote admin connections', 1
GO
 
RECONFIGURE
GO

DAC 접근 방법

cmd창에서 sqlcmd 명령어로 접속

cmd> sqlcmd -S localhost -U sa -P [패스워드] -A

sqlcmd 설명 : https://docs.microsoft.com/ko-kr/previous-versions/sql/sql-server-2008-r2/ms162773(v=sql.105)?redirectedfrom=MSDN 

 

참고
https://sungwookkang.com/368


to Top