ProxySQL 쿼리룰 설정으로 Read, Write 부하 분산하기

 

l  Version : ProxySQL, MySQL 8.X

 

ProxySQL MySQL 포크된 데이터베이스(Percona Server MariaDB) 위한 고성능, 고가용성을 제공하는 프록시이다.

l  ProxySQL이란 무엇인가 : https://sungwookkang.com/1528

 

ProxySQL 구성할 MySQL 서버 환경이 복제 구성이 되어 있으면 Write, Read 효과적으로 분산하여, ProxySQL장점을 조금 효율적으로 활용할 있다. MySQL설치, 복제구성, ProxySQL 설치는 아래 링크를 참고한다.

l  ProxySQL 설치 (MySQL 설치부터, 복제 구성, ProxySQL 설정까지 한번에) : https://sungwookkang.com/1529

 

이번 포스트에서는 ProxySQL + MySQL Replication 환경에서, 쿼리 타입(INSET UPDATE, DELET, SELECT) 따라 Write, Read 분기하여 호출하는 방법에 대해서 알아본다. 실습에 사용된 서버 환경은 아래와 같다.

Server Name IP OS Service Version
proxy-sql 172.30.1.49 Ubuntu 22.04.2 LTS ProxySQL version 2.4.2-0-g70336d4, codename Truls
mysql-master 172.30.1.97 Ubuntu 22.04.2 LTS mysql  Ver 8.0.33
mysql-slave1 172.30.1.10 Ubuntu 22.04.2 LTS mysql  Ver 8.0.33
mysql-slave2 172.30.1.13 Ubuntu 22.04.2 LTS mysql  Ver 8.0.33

 

이전의 (https://sungwookkang.com/1529)에서 ProxySQL 구성할 서버를 등록하는 과정에서, 모든 서버를 동일한 그룹으로 지정하였다. 쿼리 타입에 따라 각기 다른 서버로 호출하기 위해서는 서버 특성에 따라 그룹 할당이 필요 하다. 이번 포스트에서는 1대의 Write서버와 2대의 Read서버로 구성하는 그룹으로 구성한다. proxy-sql 서버에서 아래 스크립트를 사용하여 데이터베이스에 접속한다.

mysql -uadmin -padmin -h 127.0.0.1 -P6032 --prompt='Admin> '

 

proxy-sql 데이터베이스에 접근이 되었으면, 아래 스크립트를 사용하여, write read 서버를 등록한다. 이때 필요한 그룹을 지정할 있도록 한다.

l  Write : hostgroup_id = 1

l  Read : hostgroup_id = 2

--기존 서버 목록 삭제
DELETE FROM mysql_servers;
 
--master (write) 추가
INSERT INTO mysql_servers (hostgroup_id, hostname, port) VALUES (1, '172.30.1.97', 3306);
 
--slave (read) 추가
INSERT INTO mysql_servers (hostgroup_id, hostname, port) VALUES (2, '172.30.1.10', 3306);
INSERT INTO mysql_servers (hostgroup_id, hostname, port) VALUES (2, '172.30.1.13', 3306);
 
--추가된 서버 확인
select * from mysql_servers;
 
-- 변경사항 반영
LOAD MYSQL SERVERS TO RUNTIME;
SAVE MYSQL SERVERS TO DISK;

 

 

사용자 기본 호스트 그룹을 지정한다. hostgroup_id = 1 기본으로 지정하였다.

-- hostgroup_id 기본 1 지정
UPDATE mysql_users SET default_hostgroup = 1;
 
-- 변경사항 반영
LOAD MYSQL USERS TO RUNTIME;
SAVE MYSQL USERS TO DISK;

 

 

쿼리 타입에 따라 그룹으로 분기할 룰을 지정한다. SELECT쿼리는 hostgroup_id = 2 서버로 호출하고, 나머지 쿼리는 hostgroup_id = 1 서버로 호출한다. 이때 동일 호스트 그룹에 2 이상의 서버가 있으면 ProxySQL에서 라운드로빈으로 로드밸런싱을 한다.

-- 기존 쿼리 삭제
DELETE FROM mysql_query_rules;
 
-- SELECT 시작하는 쿼리는 hostgroup=2(slave) 라우팅
INSERT INTO mysql_query_rules (rule_id, active, apply, match_digest, destination_hostgroup) VALUES (1, 1, 1, '^SELECT', 2);
 
-- 변경사항 반영
LOAD MYSQL QUERY RULES TO RUNTIME;
SAVE MYSQL QUERY RULES TO DISK;

 

 

 

쿼리 설정이 완료되었으면, 쿼리를 실행하고 정상적으로 분기되는지 확인이 필요하다. 전에 서버에 general_log 활성화하여, 서버로 호출되는 쿼리를 기록할 있도록 한다. 아래 스크립트는 로그를 테이블 파일에 동시에 기록한다.

mysql-master mysql-slave1 mysql-slave2
set global log_output = 'TABLE,FILE';
set global general_log = on;
show variables like '%general%';
show variables LIKE '%log_output%';

 

 

 

모든 설정이 완료되었으면, 클라이언트 도구(ex : MySQL Workbench) 사용하여, proxy-sql 서버에 접속한 다음, INSERT SELECT 쿼리를 호출 한다. 여러번 호출하여 라운드로빈이 발생하였을 서버로 유입 있도록 한다.

proxy-sql
#proxy-sql
select * from testdb.tbl_a;
 
insert into testdb.tbl_a (name) values ('insert test for proxy5');
 
select * from testdb.tbl_a;

 

 

 

mysql-master 서버에서 아래 스크립트를 사용하여, 제네럴로그를 살펴본다. argument컬럼이 BLOB 타입이어서, 문자형식으로 캐스팅하였다. 쿼리 결과를 살펴보면 INSERT 쿼리만 기록된 것을 확인할 있다.

mysql-master
#mysql-mster
SELECT
                  event_time, user_host, thread_id, server_id, command_type, argument,
                  CAST(argument as char(100)) as 'cast_arg'
FROM mysql.general_log
WHERE argument LIKE 'select%'
                  or argument LIKE 'insert%'
ORDER BY event_time DESC LIMIT 5;

 

 

 

mysql-slave1 서버에서 아래 스크립트를 사용하여, 제네럴로그를 살펴본다. argument컬럼이 BLOB 타입이어서, 문자형식으로 캐스팅하였다. 쿼리 결과를 살펴보면 INSERT 쿼리만 기록된 것을 확인할 있다.

mysql-slave1
#mysql-slave1
SELECT
                  event_time, user_host, thread_id, server_id, command_type, argument,
                  CAST(argument as char(100)) as 'cast_arg'
FROM mysql.general_log
WHERE argument LIKE 'select%'
                  or argument LIKE 'insert%'
ORDER BY event_time DESC LIMIT 5;

 

 

 

mysql-slave2 서버에서 아래 스크립트를 사용하여, 제네럴로그를 살펴본다. argument컬럼이 BLOB 타입이어서, 문자형식으로 캐스팅하였다. 쿼리 결과를 살펴보면 INSERT 쿼리만 기록된 것을 확인할 있다.

mysql-slave2
#mysql-slave2
SELECT
                  event_time, user_host, thread_id, server_id, command_type, argument,
                  CAST(argument as char(100)) as 'cast_arg'
FROM mysql.general_log
WHERE argument LIKE 'select%'
                  or argument LIKE 'insert%'
ORDER BY event_time DESC LIMIT 5;

 

 

 

지금까지 ProxySQL에서 쿼리 타입에 따른 룰을 지정하여, Write Read 분기하는 방법에 대해서 알아보았다. 실제 현업에 사용할 때에는 로그 기록에 따른 오버헤드가 발생할 있으므로 사용자 환경에 따라 제네럴로그 기록을 OFF 또는 적절히 조절할 있도록 한다. 대용량 트래픽 환경에서 Write Read 쿼리를 분기 분산함으로써 DB 서버의 오버헤드를 분산하여 유용하게 활용할 있으리라 생각한다.

 

 

2023-07-23 / Sungwook Kang / http://sungwookkang.com

 

MySQL, ProxySQL, MySQL Replication, MySQL HA, Replication, MySQL복제, 마스터 슬레이브, ProxySQL설치, MySQL복제설치, 쿼리룰설정

ProxySQL 설치 (MySQL 설치부터, 복제 구성, ProxySQL 설정까지 한번에)

 

l  Version : ProxySQL, MySQL 8.X

 

ProxySQL MySQL 포크된 데이터베이스(Percona Server MariaDB) 위한 고성능, 고가용성을 제공하는 프록시이다.

l  ProxySQL이란 무엇인가 : https://sungwookkang.com/1528

 

이번 포스트는 ProxySQL 구성하는 방법에 대해서 다뤄본다. 이번 실습에서 구성되는 ProxySQL 아키텍처는 아래 그림과 같다. 모든 클라이언트 연결은 ProxySQL 연결이 되고, ProxySQL에서는 쿼리 타입에 따라 Write Read 분산하여 요청한다. MySQL 구성은 Master에서 Slave1, Slave2 GTID 사용하여 복제를 구성한다. DB 클러스터에 보면 Hostgroup라는 것을 있는데, 이는 ProxySQL에서 Failover 감지하여 역할을 변경할 , 그룹단위로 이동할 있도록 MySQL 역할에 따라 그룹을 만들었다.

 

GTID
Global Transaction Identifier 약자로 MySQL 복제에서 서버의 트랜잭션을 구분하는 고유한 식별자이다. GTID 모든 트랜잭션과 1:1 관계이며, GTID 활용하면 복제본으로 장애 조치, 계층적 복제, 특정 시점으로 백업 복구하는 등의 작업을 쉽게 구현할 있으며, 오류 발생 빈도도 줄일 있다.

 

 

ProxySQL 구현하기 위해서는 MySQL 복제 환경이 필요하다. MySQL 설치부터 복제 구성, ProxySQL 구성까지 따라할 있도록 문서를 작성하였다.

 

[시스템 구성]

실습 환경을 만들기 위해서는 전체 4대의 서버가 필요 하다. 시스템 사양은 고사양일 필요는 없지만, 너무 낮은 사양의 경우 서비스가 정상적으로 실행되지 않을 있으므로 적절히 선택하도록 한다.

l  Virtual Box

l  CPU : 2 Core

l  Memory : 4 GB

Server Name IP OS Service Version
proxy-sql 172.30.1.49 Ubuntu 22.04.2 LTS ProxySQL version 2.4.2-0-g70336d4, codename Truls
mysql-master 172.30.1.97 Ubuntu 22.04.2 LTS mysql  Ver 8.0.33
mysql-slave1 172.30.1.10 Ubuntu 22.04.2 LTS mysql  Ver 8.0.33
mysql-slave2 172.30.1.13 Ubuntu 22.04.2 LTS mysql  Ver 8.0.33

 

OS 패키지 버전 정보를 업데이트를 진행한 다음 패키지 업그레이드를 진행한다. 그리고 실습을 원활히 있도록 방화벽은 중지하도록 한다. 실제 업무 환경에서는 보안 정책에 따라 방화벽 설정을 있도록 한다.

--package update and upgrade
sudo apt-get update
sudo apt-get upgrade
 
--disable firewall
sudo ufw disable

 

 

[MySQL 설치]

MySQL 설치를 진행한다. 편의상 패키지로 설치를 진행하였다. 실제 업무에서는 필요한 버전을 선택하여 설치할 있도록 한다.

mysql-master mysql-slave1 mysql-slave2
sudo apt-get install mysql-server sudo apt-get install mysql-server sudo apt-get install mysql-server

 

MySQL 설치가 완료되었으면 외부에서 mysql 접속할 있도록 my.cnf 수정해야 한다. 일반적으로 my.cnf파일은 아래와 같은 위치에 있지만, 사용자 환경에 따라 커스텀한 경로에 저장된 경우도 있다.

l   /etc/mysql/my.cnf

l   /etc/mysql/mysql.conf.d/mysqld.cnf

 

my.cnf 파일을 오픈하여, bind-address 부분을 주석 처리한다. 부분은 로컬 호스트(localhost, 127.0.0.1)에서 들어오는 접속을 바인딩한다는 뜻으로 해당 설정 때문에 외부에서 접근을 하지 못한다.

sudo vi /etc/mysql/my.cnf
sudo vi /etc/mysql/mysql.conf.d/mysqld.cnf

 

 

bind-address 대한 주석 처리가 완료되었으면 mysql 서비스를 재시작해서 변경 사항을 적용할 있도록 한다.

sudo service mysql restart

 

 

실습에서 사용할 mysql 사용자 계정을 생성한다.

sudo mysql

 

mysql >create user mysqluser@'%' identified by 'yourpassword' ;
mysql >grant all privileges on *.* to mysqluser@'%' with grant option;
mysql >flush privileges;

 

MySQL워크 벤치 등을 사용하여 외부에서 생성한 계정으로 접근이 되는지 확인한다.

 

[MySQL 복제 구성]

MySQL복제를 구성하기 위해서는 master서버와 Slave서버에 파라미터 설정을 진행해야 한다. 파라미터 설정에서 servier-id 값이 중복되지 않도록 주의한다. my.cnf 파일을 오픈하여 아래 내용을 추가한다.

mysql-master mysql-slave1 mysql-slave2
server-id=1
log-bin=binlog
gtid-mode=ON
enforce-gtid-consistency=ON
log_slave_updates=ON
server-id=2
log-bin=binlog
gtid-mode=ON
enforce-gtid-consistency=ON
log_slave_updates=ON
server-id=3
log-bin=binlog
gtid-mode=ON
enforce-gtid-consistency=ON
log_slave_updates=ON

 

 

파라메터 수정이 완료되었으면, my.cnf파일을 저장하고, 모든 서버의 mysql서비스를 재시작하여 gtid_mode ON인지 확인한다.

sudo service mysql restart

 

show variables like '%gtid_mode%'

 

 

mysql-master 접속하여 테스트용 데이터베이스를 생성한다.

mysql-master
create database testdb default character set utf8mb4;
show databases;

 

 

mysql-master에서 데이터베이스 백업을 진행한다.  mysqldump 명령을 사용하였고, 복제 구성을 위한 백업이므로 필요한 옵션을 추가하였다. 아래 스크립트에서 백업 경로는 적절하게 수정하여 사용할 있도록 한다.

mysql-master
mysqldump -u mysqluser -p -v --databases testdb --quick --single-transaction --routines --set-gtid-purged=ON --triggers --extended-insert --master-data=2 > /home/dev/db_backup/testdb.sql

 

백업이 완료되었으면 슬레이브를 구성할 서버에 백업 파일을 복사한다. 파일을 복사하는 방법은 다양하게 있으며 이번 실습에서는 scp명령을 사용하였다.

mysql-master
--copy mysql-master to myslq-slave1
sudo scp testdb.sql dev@172.30.1.10:/home/dev/db_backup
 
--copy mysql-master to mysql-slave2
sudo scp testdb.sql dev@172.30.1.13:/home/dev/db_backup

 

 

mysql-slave1, mysql-slave2 서버에서 데이터베이스를 복원한다. 아래 스크립트로 복원할 있다.

mysql-slave1 mysql-slave2
mysql -u mysqluser -p testdb < testdb.sql mysql -u mysqluser -p testdb < testdb.sql

 

복원 과정에서 아래와 같은 오류 메시지가 발생한다면, mysql 접속하여 reset master 명령을 실행하여 해결할 있다. 오류는 서버마다 uuid gtid 생성하는데 master 것을 가져와서 slave 반영하려 했기 때문에 발생한 것이다.

 

mysql> reset master;

 

복원이 정상적으로 되었는지 mysql-slave1, mysql-slave2 서버에 접속하여 확인한다. 그리고 슬레이브 서버에서 마스터 서버로 복제 연결을 진행한다.

mysql-slave1 mysql-slave2
change master to master_host = '172.30.1.97',
master_user='mysqluser', master_password=’password',
master_auto_position =1;
 
start slave;
change master to master_host = '172.30.1.97',
master_user='mysqluser', master_password=’password',
master_auto_position =1;
 
start slave;

 

아래 스크립트를 사용하여 정상적으로 복제가 연결되었지 확인한다.

mysql-slave1 mysql-slave2
show slave status; show slave status;

 

 

 

mysql-master 데이터를 입력하면 mysql-slave1, mysql-slave2 데이터 변경이 정상적으로 반영되는 것을 확인할 있다.

 

[ProxySQL 설치]

ProxySQL 깃헙 저장소에서 ProxySQL 파일을 다운로드한다. 아래 스크립트를 실행하면 다운로드 자동으로 설치가 진행된다.

sudo wget https://github.com/sysown/proxysql/releases/download/v2.4.2/proxysql_2.4.2-ubuntu20_amd64.deb
 
sudo dpkg -i proxysql_2.2.0-ubuntu20_amd64.deb

 

 

 

설치가 완료되었으면, 현재 설치되어 있는 ProxySQL 버전을 확인한다.

proxysql --version

 

 

 

ProxySQL 서비스를 실행 종료하기 위해서는 아래 스크립트를 사용한다.

--실행
sudo service proxysql start
--종료
sudo service proxysql stop

 

 

ProxySQL 서비스를 초기화는 아래 명령어를 사용할 있다.

sudo service proxysql-initial start

 

ProxySQL 서비스가 시작되었으면, 이제 ProxySQL 접속해서 여러가지 세팅을 진행한다. 우선 ProxySQL 접속하기 위해서는 MySQL Client 필요하다. 사용자 환경에 따라 MySQL 또는 MariaDB 클라이언트를 설치한다.

sudo apt install mysql-client-core-8.0     # version 8.0.33-0ubuntu0.22.04.2
sudo apt install mariadb-client-core-10.6  # version 1:10.6.12-0ubuntu0.22.04.1

 

 

ProxySQL 접속한다. 아래 스크립트를 proxy-sql 서버에서 실행한다.

mysql -uadmin -padmin -h 127.0.0.1 -P6032 --prompt='admin> '

 

 

ProxySQL 운영하기 위해 필요한 데이터베이스도 확인해볼 있다.

show databases;

 

 

 

ProxySQL에서 MySQL서버를 모니터링 있는 계정을 설정한다. 설정은 ProxySQL MySQL 접속할 있는 계정이어야 한다. 사용자 환경에 따라 username passwrd 변경하여 사용한다.

UPDATE global_variables SET variable_value = 'username' WHERE variable_name = 'mysql-monitor_username';
UPDATE global_variables SET variable_value = 'password' WHERE variable_name = 'mysql-monitor_password';

 

모니터링 계정이 추가 되었는지 확인한다.

SELECT * FROM global_variables WHERE variable_name LIKE 'mysql-monitor_%';

 

 

 

변경 사항 저장 즉시 적용을 위해 아래 스크립트를 실행한다.

LOAD MYSQL VARIABLES TO RUNTIME;
SAVE MYSQL VARIABLES TO DISK;

 

 

ProxySQL에서 연결할 MySQL 서버 정보를 추가한다. 현재는 구성된 모든 서버를 호스트그룹 1 구성하였다.

INSERT INTO mysql_servers (hostgroup_id, hostname, port) VALUES (1, '172.30.1.97', 3306);
INSERT INTO mysql_servers (hostgroup_id, hostname, port) VALUES (1, '172.30.1.10', 3306);
INSERT INTO mysql_servers (hostgroup_id, hostname, port) VALUES (1, '172.30.1.13', 3306);

 

추가된 MySQL 목록을 확인한다.

SELECT * FROM mysql_servers;

 

 

변경 사항 저장 즉시 적용을 위해 아래 스크립트를 실행한다. 위에 사용한 설정 저장 적용 스크립트와 명령이 다르므로 주의한다.

LOAD MYSQL SERVERS TO RUNTIME;
SAVE MYSQL SERVERS TO DISK;

 

 

아래 스크립트를 실행하면, 추가한 MySQL서버들에 대해서 연결 성공 여부 로그를 확인할 있다. 바로 실행하면 현재까지 연결된 적이 없기 때문에 로그가 남지 않는다. 하지만 연결 테스트를 진행 확인해보면 커넥션 로그가 남아있는 것을 확인할 있다.

SELECT * FROM monitor.mysql_server_connect_log ORDER BY time_start_us DESC LIMIT 10;

 

 

 

모니터링을 위해 ProxySQL MySQL사이의 로그도 확인할 있다.

SELECT * FROM monitor.mysql_server_ping_log ORDER BY time_start_us DESC LIMIT 10;

 

 

이제는 외부 클라이언트가 ProxySQL 접속할 계정 생성한다. 계정을 사용하여 외부 어플리케이션들이 ProxySQL 접속하게 된다.

INSERT INTO mysql_users (username, password, default_hostgroup) VALUES ('ubuntu', '123456', 1);

 

 

외부 접근용 계정을 확인한다.

select * from mysql_users;

 

 

변경 사항 저장 즉시 적용을 위해 아래 스크립트를 실행한다. 위에 사용한 설정 저장 적용 스크립트와 명령이 다르므로 주의한다.

LOAD MYSQL USERS TO RUNTIME;
SAVE MYSQL USERS TO DISK;

 

proxy-sql 서버에서 아래 명령으로 ProxySQL 접속하여, 연결 테스트 현재 그룹에 연결된 서버들에게 요청이 되는지 확인한다. 여러 호출해보면 등록된 MySQL 서버로 분산되어 호출되어 호스트 이름이 변경되어 호출되는 것을 확인할 잇다.

mysql -uubuntu -p123456 -h127.0.0.1 -P6033 -e "SELECT @@hostname";

 

Tip : MySQL 8 버전대에서는 패스워드 문제로 일부 연결 발생할 있다고 한다. 이런 경우 아래와 같은 명령을 사용할 있다.
 
mysql --default-auth=mysql_native_password -uubuntu -p123456 -h 127.0.0.1 -P6033 -e "SELECT @@hostname";

 

 

 

 

 

지금까지의 ProxySQL 서버의 설정을 파일로 백업할 경우 아래 명령어를 사용할 있다. 실습에서는 서버의 대수가 적고 룰도 간단해서 백업이 필요하지 않을 수도 있지만, 실제 업무에서 사용할 때에는 서버의 대수도 많고 동일한 환경을 유지하기 위해서 반드시 설정 백업을 있도록 한다.

--ProxySQL설정 백업
SELECT CONFIG INTO OUTFILE /tmp/backup.cfg;
SAVE CONFIG TO FILE  /tmp/backup.cfg;

 

백업된 파일 내용을 살펴보면 아래와 같은 내용들이 포함된 것을 확인할 있다.

--백업된 설정 내용 조회 (/etc/proxysql.cnf)
SELECT CONFIG FILE;

 

 

Tip. MySQL8 버전부터는 계정 비밀번호 정책이 변경되었기 때문에 아직 ProxySQL에서도 문제가 발생하곤 한다. 아래 링크를 참고하여 본인 서버에 발생하는 케이스를 해결하는데 도움이 있도록 한다.
l   ProxySQL-2 cannot connect to PXC using the user with a caching_sha2_password plugin. : https://github.com/sysown/proxysql/issues/2580
l   Access denied while connecting via proxysql to MySQL pxc : https://github.com/sysown/proxysql/issues/3672
l   Access denied after redeployed proxysql : https://github.com/sysown/proxysql/issues/2424
l   access proxysql 6033 using mysql client sometimes successsometimes failed : https://github.com/sysown/proxysql/issues/3185
l   Why ERROR 1045 (28000): Access denied in ProxySQL server? : https://devpress.csdn.net/mysqldb/63036be47e668234661985e8.html

 

 

 

2023-07-22 / Sungwook Kang / http://sungwookkang.com

 

MySQL, ProxySQL, MySQL Replication, MySQL HA, Replication, MySQL복제, 마스터 슬레이브, ProxySQL설치, MySQL복제설치

ProxySQL 이란 무엇인가

 

l  Version : ProxySQL

 

ProxySQL MySQL 포크된 데이터베이스(Percona Server MariaDB) 위한 고성능, 고가용성을 제공하는 프록시이다. 글을 쓰는 현재(2023 7) GPL 라이선스로 공개되어 있어 누구나 사용할 있다. ProxySQL 대한 자세한 정보는 아래 링크를 참고한다.

l  공식 사이트 주소 - https://www.proxysql.com/

l  ProxySQL 설치 사용 가이드 - https://github.com/sysown/proxysql/wiki

l  ProxySQL 도커 이미지 - https://hub.docker.com/r/proxysql/proxysql

 

[Proxy서버는 무엇일까]

프록시 서버는 리소스를 요청하는 클라이언트와 해당 리소스를 제공하는 서버 사이에 중개자 역할을 한다. 프록시 서버에 요청된 내용들은 캐시를 이용하여 저장하고, 캐시 정보를 요구하는 요청에 대해서는 원격 서버에 접속하여 데이터를 가져올 필요가 없다. 전송시간을 절약할 있다. 또한 불필요하게 외부와의 연결을 하지 않아도 된다는 장점과 외부의 트래픽을 줄이게 됨으로써 네트워크 병목 현상을 방지할 있다.

l  Proxy Server : https://en.wikipedia.org/wiki/Proxy_server

 

 

[ProxySQL 사용하는 이유는 무엇일까]

서비스 운영시 MySQL서버를 여러대로 구성해야하는 경우가 있다. (, Replication, Sharding ) 이때 어플리케이션 수가 증가할수록 MySQL 서버와 맺게 되는 커넥션수가 급격하게 늘어난다. 예를들어 MySQL 서버가 30, 어플리케이션 서버가 200대이고, 서버별로 커넥션을 10개씩 유지한다면 30 * 200 * 10 = 60000 커넥션이 발생한다. 이런 이슈를 피하기 위해 중간에 미들웨어 개념으로 프록시 역할을 해주는 것이 ProxySQL이다. ProxySQL 효율적인 커넥션 관리뿐만 아니라 라우팅 기능 여러 기능을 제공한다.

 

 

[ProxySQL 주요기능]

l  Connection Multiplexing : ProxySQL 멀티플렉싱은 여러 어플리케이션들이 동일한 데이터베이스에 대한 연결을 재사용할 있도록 하는 기능이다. MySQL "스레드 " 구현이 아닌 "연결당 스레드" 사용기 때문에, 커넥션수가 증가함에 따라 (유휴 상태에서도) 점차 성능이 저하된다. ProxySQL "스레드 " 사용하고 다중화를 통해 데이터베이스 커넥션을 할당하고 관리하는 리소스의 수를 줄여 성능을 크게 향상시킨다.

l  Query Routing : ProxySQL 쿼리 규칙을 정의하여 쓰기를 기본으로 라우팅하고, 읽기를 복제본에 분산할 있다. 매우 세분화된 기준으로 즉시 쿼리를 다시 작성한다.

l  Query Cache : ProxySQL 쿼리 캐싱은 요청 결과를 캐시하며, 동일한 쿼리가 실행되었을 캐시의 결과를 재사용하여 반환한다.

o   https://proxysql.com/documentation/Query-Cache/

l  Monitoring : ProxySQL 연결된 서버의 상태를 핑으로 모니터링 한다. 주기 설정 응답이 없을 재시도하며, 재시도 횟수 초과시, 응답 없는 서버로 판단하여 프록시 서버 목록에서 제거한다.

l  Scheduler : 정해진 시간에 스크립트를 실행해주는 기능을 담당한다.

 

[Recvoery 위한 orchestrator]

ProxySQL Recovery 기능을 제공하지는 않는다. 그래서 MySQL 서버 장애시DB 클러스터에서는 Slave DB (Read only) 운영되던 데이터베이스를 Master DB 승격을 시켜야 하는데, 기능을 제공하지는 않는다. 이러한 단점을 극복하기 위해 MySQL 고가용성 솔루션인 오케스트레이터(orchestrator) 함께 사용한다.

 

오케스트레이터는 Replication으로 구성된 DB 구조를 파악하고 스케줄러가 DB 설정을 변경할 있어 기존의Slave DB Master 승격시킬 있다. 그리고 ProxySQL 인지할 있도록 스케줄러가 ProxySQL 설정 파일을 업데이트 한다. 이러한 방식으로 Recovery 구성할 있다.

 

 

 

[참고자료]

l   공식 사이트 주소 - https://www.proxysql.com/

l   ProxySQL 설치 사용 가이드 - https://github.com/sysown/proxysql/wiki

l   ProxySQL 도커 이미지 - https://hub.docker.com/r/proxysql/proxysql

l   MySQL high availability & autofailover with ProxySQL & Orchestrator - Codemotion Milan 2018 : https://speakerdeck.com/thijsferyn/mysql-high-availability-and-autofailover-with-proxysql-and-orchestrator-codemotion-milan-2018

l   https://www.linkedin.com/pulse/iac-ha-db-architecture-aws-kuiyang-edwin-wang/

 

 

 

2023-07-20 / Sungwook Kang / http://sungwookkang.com

 

MySQL, ProxySQL, MySQL Replication, MySQL HA, Replication, MySQL복제, 마스터 슬레이브

SQL Server Failover Cluster 구성

 

l  Version : SQL Server 2019

 

SQL Server 고가용성 하나인 SQL Server Failover Cluster (장애조치 클러스터) 인스턴스를 구성하는 방법에 대해서 알아본다. SQL Server 장애조치 클러스터를 구성하기 위해서는 Windows Failover Cluster 먼저 구성되어 있어야 한다. 그리고 디스크 또한 공유 디스크를 사용이 필수이다. 이번 포스트에서는 Windows Failover Cluster 구성이 완료 되어 있다는 가정하에 SQL Server Failover Cluster 구성하는 방법에 대해서 설명한다.

 

이번 포스트에서 구성하려는 장애조치 클러스터의 구성은 아래 그림과 같다.  DB01 액티브 서버로 운영되고, DB02 패시브 서버로 운영되며 비상시 장애조치 되어 역할이 변경된다. SQL Server 운영에 필요한 설치 파일 사용자 데이터베이스 파일은 공유 디스크에 저장되어 운영 된다.

 

 

 

[Master 서버, 클러스터 설치]

DB1(Master) 서버에서 SQL Server 설치 파일을 실행한 다음 [설치]-[SQL Server 장애조치(Failover) 클러스터 새로 설치] 클릭 한다.

 

 

사용 조건 단계에서 라이선스 계약에 동의함을 선택하고 [다음] 클릭한다.

 

 

Microsoft 업데이트 단계에서는 업데이트를 체크하지 않고 [다음] 클릭한다. 업데이트를 클릭하게 되면 설치 과정에서 업데이트가 발생하여 설치 시간이 오래 걸릴 있으니, 업데이트는 모든 설치 이후에 별도로 진행 있도록 한다.

 

 

장애 조치(Failover) 클러스터 설치 규칙 단계에서는 클러스터 설치에 적합한 환경인지 등을 검사하게 된다. [다음] 클릭한다.

 

 

기능 선택 단계에서는 사용자에게 필요한 SQL Server 기능을 선택 한다. 설치할 기능을 선택하고 [다음] 클릭한다.

 

 

인스턴스 구성 단계에서는 SQL Server 클러스터에 사용할 네트워크 이름을 입력한다. 이름은 이후 다른 서버가 클러스터에 조인할 식별할 있는 이름이기에 의미 있는 이름으로 지정할 있도록 한다. 이름을 입력하였으면 [다음] 클릭한다.

 

 

클러스터 리소스 그룹 단계에서는 리소스 그룹에 포함할 인스턴스를 선택한다. 아래 그림에서는 기본 인스턴스로 생성하였기에 그룹 이름 또한 기본 인스턴스 이름으로 보여진다. 리소스 그룹을 선택하고 [다음] 클릭 한다.

 

클러스터 디스크 선택 단계에서는 SQL Server에서 사용할 공유 디스크를 선택한다. 단계에서 디스크 목록이 나타나지 않는다면 Windows Failover Cluster 구성할 공유 디스크에 대한 설정을 잘못된 것이므로 윈도우 클러스터부터 다시 확인 있도록 한다. 디스크  선택을 하고 [다음] 클릭한다.

 

클러스터 네트워크 구성 단계에서는 SQL Server Cluster 사용할 IP 입력한다. 여기에 입력한 IP 이후 사용자가 접속할 사용되는 Cluster IP이다. 클러스터 IP 접속을 해야 Failover 발생하였을 , 활성 SQL 서버로 자동으로 연결해 준다. 중복되지 않은 클러스터 IP입력을 하였다면 [다음] 클릭한다.

 

 

서버 구성 단계에서는 SQL Server 서비스에서 사용할 계정과 암호를 입력한다. 이때 도메인 계정을 사용할 있도록 한다. 계정과 이름을 입력하였으면 [다음] 클릭 한다.

 

 

데이터베이스 엔진 구성 단계에서는 SQL Server 접근 방법 SQL 관리에 필요한 sa 비밀번호를 입력한다.

 

 

데이터베이스 엔진 구성 단계에서 [데이터 디렉터리] 탭에서는 SQL Server 필요한 데이터가 위치할 디렉터리를 지정한다. 디렉터리 경로는 앞에서 추가한 클러스터 공유 디스크의 위치를 지정한다.

 

 

데이터베이스 엔진 구성 단계에서 [TempDB] 탭에서는 SQL Server TempDB 사용할 디렉터리 경로를 지정한다. 디스크는 로컬을 사용해도 되지만, 보통 클러스터 구성시 로컬 디스크는 많은 공간을 할당하지 않기 때문에 용량이 클러스터의 디스크로 지정하였다. 지금까지 구성이 완료되었으면 [다음] 클릭 한다.

 

 

설치 준비 단계에서는 지금까지 설정한 요소들을 정리해서 보여주며 [설치] 클릭하여 설치를 진행할 있도록 한다.

 

 

완료 단계에서는 정상적으로 설치가 완료된 것을 보여주며 [닫기] 클릭 한다.

 

 

설치가 완료된 다음, 앞에서 지정한 디렉터리 경로에 SQL Server 필요한 파일이 생성된 것을 확인할 있다.

 

 

[Passive서버, 클러스터 노드 추가]

지금까지 Master 서버에서 SQL 클러스터링에 대한 설치를 진행하였고, 이후 단계는 클러스터 노드에 추가할 SQL Server 설치한다. 이후 과정은 Passive 서버에서 진행하기 때문에 착오가 없도록 한다.

 

SQL Server 설치 파일을 실행하여 [설치] – [SQL Server 장애 조치(Failover) 클러스터에 노드 추가를 선택 한다.

 

 

이후 설치 과정은 이전과 동일한 부분이 있어 그림으로만 대체한다. 필요한 부분에서는 설명을 추가 한다.

 

 

 

앞에서 생성한 인스턴스 클러스터 그룹의 이름을 선택하면 클러스터 노드의 이름을 자동으로 불러와서 보여준다.

 

 

클러스터 IP또한 이미 클러스터 구성 입력한 정보를 그대로 보여준다.

 

 

인스턴스에서 사용할 계정과 암호를 입력한다. 도메인 계정으로 사용할 있도록 한다.

 

 

 

 

클러스터 노드에 추가가 완료된 다음 SQL Server 접속 테스트를 진행한다. 이때 노드의 로컬IP 아닌 SQL Server Cluster IP 입력하도록 한다. 로컬IP 접속할 경우 해당 노드의 인스턴스에 직접 로그인 하기 때문에 Failover 발생시 활성 서버로 자동으로 연결되지 않는다. 클러스터 IP 사용할 경우에는 활성 노드로 자동으로 연결해 준다.

 

 

서버 이름을 조회해 보면 로컬의 서버 이름이 아닌 클러스터 이름을 보여준다. 그리고 SQL Server 클러스터 상태를 조회해 보면 현재 구성되어 있는 모든 노드의 이름을 보여주며 어떤 노드가 활성 상태인지를 보여준다.

 

 

테스트를 위해 TestDB 생성해 보았는데, 클러스터를 구성할 지정했던 디렉터리 경로에 사용자 데이터베이스 파일이 생성되는 것을 확인할 있다.

 

 

SQL server 장애조치 클러스터를 구성하였을 , 하나의 서버에 장애가 나도 다른 서버가 역할을 대신할 있어 가용성을 높일 있다. 노드의 개수는 최대 4 까지 가능하다. 물론 가용성을 높이기 위한 기술로는 클러스터링 외에도 복제, 미러링, AlwaysOn 기술등이 있다. 사용자 환경을 고려하여 최적의 솔루션을 선택하여 가용성을 확보 있도록 한다.

 

 

2023-07-16/ Sungwook Kang / http://sungwookkang.com

 

 

 

SQL Server, MS SQL, SQL Failover Cluster, SQL 장애조치, SQL 클러스터링, 장애조치, SQL 고가용성, 페일오버 클러스터

[Kubernetes] vagrant 환경에서 Kubernetes 클러스터 구성하기

 

l  Kubernetes on vagrnat

 

vagrant에서 Kubernetes 클러스터를 구성하는 방법에 대해서 알아본다. 클러스터 구성환경은 virtualbox centos8 운영체제의 가상머신을 3 생성하고, 머신은 master, woker1, woker2 구성한다.

 

l  vagrant 활용한 개발 환경 구축하기 : https://sungwookkang.com/1523

l  vagrant 가상머신 생성하기 : https://sungwookkang.com/1524

 

호스트이름 IP 역할
k8s-master 192.168.10 Master node
k8s-worker1 192..168.11 Worker node
k8s-worker2 192.168.12 Worker node

 

l   Kubernetes Version : v1.27.3

l   Docker Version : 24.0.2, build cb74dfc

 

vagrnatfile 구성 Kubernetes 구성에 사용할 스크립트 파일은 아래 깃헙을 참고 한다.

l   https://github.com/sqlmvp/k8s-cluster-vagrant

 

 

vagrant up 완료되면 아래와 같이 클러스터가 생성되어 ready 상태로 동작되는 것을 확인할 있다.

 

 

2023-07-03 / Sungwook Kang / https://sungwookkang.com

 

 

vagrant, 베이그랜트, 쿠버네티스, Kubernetes,

[vagrant] vagrantfile 활용한 가상머신 N대를 한번에 생성하기

 

l  Vagrant

 

Vagrant(베이그랜트) Hashicorp(하시코프)에서 개발한 가상머신 관리를 자동화 도구로 루비 기반의 DSL 작성할 있으며, 가상머신 생성 관리, 환경 구축을 위한 프로비저닝까지 관리할 있다. 이번 포트스에서는 vagrant에서 가상머신을 생성할 참고하는 vagrantfile 대해서 알아본다.

 

l  vagrant 활용한 개발 환경 구축하기 : https://sungwookkang.com/1523

l  vagrant 가상머신 생성하기 : https://sungwookkang.com/1524

 

vagrantfile vagrant init 명령을 실행하면 생성되는 설정 파일이다. 물론 init 명령이 아닌 사용자가 수동으로 직접 파일을 생성하여 사용할 수도 있다. Vagrantfile 가상머신의 이미지 종류, IP할당, 공용 폴더 설정, NAT 설정 다양한 정보를 가지고 있다.  이렇게 생성된 파일은 vagrant up 명령을 실행할 로드되어 설정된 값으로 가상머신을 생성하게 된다.    

 

아래 코드는 vagrantfile 설정의 예시로 기초적인 명령어를 작성한 것이다. 예제에 포함된 설정 외에도 다양한 환경변수를 지원한다.

Vagrant.configure("2") do |config|
    config.vm.define "vm-name" do |cfg|
        cfg.vm.box = "generic/centos8"
        cfg.vm.hostname = "centos8"
        cfg.vm.network "private_network", ip: "192.168.1.10"
        cfg.vm.network "forwarded_port", guest: 22, host:19000, auto_correct: false, id "ssh"
        cfg.vm.synced_folder ".", "/vagrant", disabled: true
        cfg.vm.provider "virtualbox" do |vb|
            vb.name = "vm-name"
            vb.cpus = 2
            vb.memory = 2048
        end
    end
end

 

 

l  Vagrant.configure("2") do |config| : vagrant Version

l  config.vm.define "vm-name" do |cfg| : vagrant에서 정의한 가상머신 이름. Vagrant ssh에서 사용

l  cfg.vm.box = "generic/centos8" : vagrant box에서 다운로드 실행할 이미지 이름

l  cfg.vm.hostname = "centos8" : OS에서 설정될 호스트 서버 이름

l  cfg.vm.network "private_network", ip: "192.168.1.10" : 가상머신에 할당할 NAT 선택(public_network, private_netwrok), IP 입력하지 않을 경우 DHCP 동작.

l  cfg.vm.network "forwarded_port", guest: 22, host:19000, auto_correct: false, id "ssh" : 호스트의 19000 포트로 접속시 가상머신의 22 포트로 포워딩

l  cfg.vm.synced_folder ".", "/vagrant", disabled: true : 호스트와 가상머신의 공유 폴더 설정

l  cfg.vm.provider "virtualbox" do |vb| : virtualbox provider 지정

l  vb.name = "vm-name" : virtualbox에서 보여지는 가상머신 이름

l  vb.cpus = 2 : 가상머신에 할당될 CPU 코어

l  vb.memory = 2048 : 가상머신에 할당될 메모리 크기. 단위는 MB.

 

Vargrant up 명령으로 동시에 2 이상의 가상머신을 생성하려면 vagrantfile 파일에 생성하려는 서버 설정을 모두 입력하여 사용한다. 아래 예제는 동시에 3대의 가상머신을 생성한다.

Vagrant.configure("2") do |config|
    #vm1
    config.vm.define "vm-1" do |cfg|
        cfg.vm.box = "generic/centos8"
        cfg.vm.hostname = "vm1-centos8"
        cfg.vm.provider "virtualbox" do |vb|
            vb.name = "vm-1"
            vb.cpus = 2
            vb.memory = 2048
        end
    end
 
    #vm2
    config.vm.define "vm-2" do |cfg|
        cfg.vm.box = "generic/centos8"
        cfg.vm.hostname = "vm2-centos8"
        cfg.vm.provider "virtualbox" do |vb|
            vb.name = "vm-2"
            vb.cpus = 2
            vb.memory = 2048
        end
    end
 
    #vm3
    config.vm.define "vm-3" do |cfg|
        cfg.vm.box = "generic/centos8"
        cfg.vm.hostname = "vm3-centos8"
        cfg.vm.provider "virtualbox" do |vb|
            vb.name = "vm-3"
            vb.cpus = 2
            vb.memory = 2048
        end
    end
end
 

 

Vagrant up 명령으로 가상머신이 생성할 있으며, vagrantfile 설정대로 3대의 가상머신이 생성되는 것을 확인할 있다.

 

Virtualbox에서도 3대의 가상머신이 정상적으로 생성된 것을 확인할 있다.

 

 

개발환경을 구성할 이와 같이 스크립트로 생성할 있도록 구성하고 관리하면 매번 환경을 세팅할 때마다 투입되는 시간 리소스 절약할 있다. 그리고 가장 중요한 것은 동일한 환경을 다시 구성할 있기 때문에 매번 구성때마다 환경 바뀜으로 인한 여러가지 장애상황을 예방할 있다.

 

Vagrantfile 대한 자세한 옵션은 공식 문서를 참고 있도록 한다.

l   Vagrantfile : https://developer.hashicorp.com/vagrant/docs/vagrantfile

 

 

[참고자료]

l   Vagrantfile : https://developer.hashicorp.com/vagrant/docs/vagrantfile

 

 

 

2023-07-02 / Sungwook Kang / https://sungwookkang.com

 

 

Vagrant, 베이그랜트, 개발환경구성, 가상머신, vagrantfile, 베이그랜트 설정, 가상머신생성, virtualbox

[vagrant] vagrant 가상머신 생성하기

 

l  Vagrant

 

Vagrant(베이그랜트) Hashicorp(하시코프)에서 개발한 가상머신 관리를 자동화 도구로 루비 기반의 DSL 작성할 있으며, 가상머신 생성 관리, 환경 구축을 위한 프로비저닝까지 관리할 있다.

 

l  vagrant 활용한 개발 환경 구축하기 : https://sungwookkang.com/1523

 

이번 포트스에서는 vagrant 가상머신을 생성하는 방법을 설명한다. Vagrant 사용자가 수작업으로 진행하는 작업을 설정 파일을 통해서 자동으로 생성 관리를 도와주는 도구이지 vagrant 자체가 가상머신의 역할을 하는 것은 아니다. 따라서 Vagrant 사용하여 가상머신을 생성하기 위해서는 Virtualbox Hyper-V, parallels같은 가상머신 툴이 설치가 되어 있어야 한다. 가상머신 설치에 대한 내용은 이미 다른 정보가 많기 때문에 여기에서 다루지 않는다.

 

Vagrant 가상머신을 만들기 위해서는 사용할 box 추가해야 한다. Box 가상머신을 생성할 OS 대한 이미지와 OS 포함될 다양한 소프트웨어들을 포함한 패키지이다. 우선 box 추가하기 전에 어떤 이미지들이 제공되는지 box 사용할 주소를 확인하기 위해 아래 사이트에 접속하여 목록을 확인할 있다

l  HashiCorp 공식 box : https://app.vagrantup.com/boxes/search

 

 

 

이번 포스트에서는 Centos 설치하기 때문에 Centos 검색하여 Centos 8  정보를 확인한다. Box추가에 사용할 파라메터 이름을 확인할 있다.

 

Vagrant box 등록하는 방법은 box add 라는 명령을 사용한다. 위에서 확인한 경로를 사용하여 Centos8 box 등록한다. 등록과정에서 어떤 플랫폼의 box 사용할 것인지 선택하는 단계가 있으며 각자의 플랫폼에 맞는 박스 타입을 선택하면 된다. 이번 포스트에서는 virtualbox 사용하였다. 박스를 등록하면 가상머신 생성에 필요한 이미지를 다운로드 받는다.

vagrant box add generic/centos8

 

 

현재 등록되어 있는 박스의 목록을 확인하기 위해서는 box list 명령을 사용한다.

vagrant box list

 

 

등록된 박스 삭제는 box remove 명령을 사용한다.

vagrant box remove generic/centos8

 

 

가상머신을 생성할 디렉터리로 이동하여 가상머신 설정 파일을 생성한다, init 명령을 사용하며, 이때 파라메터 값으로 박스 이름을 입력한다. 이니셜 작업이 완성되면 Vagrantfile이라는 파일이 생성된 것을 확인할 있다.

vagrant init generic/centos8

 

 

설정파일을 살펴보면 현재 박스의 이미지 정보를 확인할 있다. 아래는 주석을 제외한 내용이다.

Vagrant.configure(“2”) do |config|
config.vm.box = “generic/centos8”

 

 

 

가상머신을 생성하기 위해서는 up 명령을 사용한다. 명령을 실행하면 다운로드 받은 이미지를 사용하여 가상머신이 생성된다.

vagrant up

 

 

 

Virtualbox에서도 가상머신이 생성되는 것을 확인할 있다.

 

생성한 가상머신에 접속하기 위해서는  ssh 명령을 사용하여 접속 한다.

vagrant ssh

 

 

Vagrant 생성한 가상머신을 중지하려면 halt 명령을 사용한다.

Vagrant halt

 

Vagrant 생성한 가상머신을 삭제하려면 destroy 명령을 사용한다. 가상머신을 삭제하려면 선행작업으로 가상머신을 중지해야 한다.

Vagrant destroy

 

 

지금까지 vagrant 활용하여 가상머신을 생성하는 방법에 대해서 알아보았다. 현재는 기본설정으로 가상머신을 생성하였지만, 각자 개발환경을 커스텀 환경으로 구성하기 위해서는 vagrantfile 수정하여 사용할 있다. 환경설정 파일에 대한 수정은 다른 포스트에서 다룰 예정이다.

 

2023-07-01 / Sungwook Kang / https://sungwookkang.com

 

 

Vagrant, 베이그랜트, 개발환경구성, 가상머신

[vagrant] vagrant 활용한 개발 환경 구축하기

 

l  Vagrant  with mac brew install

 

Vagrant(베이그랜트) Hashicorp(하시코프)에서 개발한 가상머신 관리를 자동화 도구로 루비 기반의 DSL 작성할 있으며, 가상머신 생성 관리, 환경 구축을 위한 프로비저닝까지 관리할 있다. 또한 가상 환경에 대한 설정을 관리할 있어 동일한 환경을 구성할 있다. 이번 포스트에서는 MAC 환경에서 vagrant 설치하는 방법에 대해서 알아본다.

 

[Homebrew 설치하기]

Homebrew vagrant 설치하는 방법은 매우 간단하다. Homebrew 명령어 하나로 쉽게 설치 삭제가 가능하다. 설치 과정에서 현재 사용자의 암호를 입력해야 한다.

brew install vagrant

 

 

정상적으로 설치가 왼료되었으면, --version 옵션을 사용하여 설치된 vagrant 버전을 확인할 있다. vagrant 설치된 디렉터리 위치를 확인하려면 whitch 명령을 사용한다.

vagrant –version
which vagrant

 

 

Homebrew 설치한 vagrant 삭제는 아래 명령어를 사용하면 된다.

brew uninstall vagrant

 

 

[Vagrant 공식사이트에서 다운로드]

Hashicorp 공식 사이트에서 vagrant 다운로드 받아 설치 있다.

l  https://www.vagrantup.com/

 

플랫폼에 맞는 버전을 다운로드 받아 설치하여 사용한다.

 

 

 

2023-06-30 / Sungwook Kang / https://sungwookkang.com

 

 

Vagrant, 베이그랜트, 개발환경구성, 가상머신

[Prometheus] Prometheus Thanos 아키텍처 살펴보기

 

l  Prometheous with Thanos

 

Thanos(타노스) CNCF(https://www.cncf.io/) 인큐베이팅 프로젝트로, 프로메테우스의 확장성과 내구성을 향상시키기 위한 오픈소스 프로젝트이다.

l  Prometheus 확장 내구성을 위한 다양한 구성 방법 : https://sqlmvp.tistory.com/1521

 

Thanos Prometheus 2.0 스토리지 형식을 활용하여 빠른 쿼리 대기 시간을 유지하면서 모든 개체 스토리지에 메트릭 데이터를 효율적으로 저장한다. 또한 운영중인 프로메테우스 서버의 데이터를 통합 저장 외부 저장소에 데이터를 저장할 있기 때문에 보관 기간에 제한이 없고, 단일 쿼리로 전체 프로메테우스 서버의 데이터를 쿼리 있다. 장점을 크게 정리하면 아래와 같이 정리할 있다.

l  Long-term Storage : 원격 스토리지에 데이터를 안정적으로 저장하여 장기적인 데이터 보존을 가능

l  Global Query : 여러 원격 스토리지에서 데이터를 통합하여 조회할 있는 Global Query 기능을 제공하여 분산된 데이터에 대해 단일 쿼리를 실행할 있어 데이터 분석과 모니터링에 유용

l  HA(고가용성) : 원격 스토리지에 데이터를 복제하여 프로메테우스 서버 하나가 장애가 발생하더라도 데이터의 고가용성을 보장

 

타노스는 Sidecar, Query Gateway, Store Gateway, Compactor, Ruler, Receiver라는 6개의 컴포넌트로 이루어져 있다.  

 

l   Thanos Sidecar

ü  Prometheus 함께 하나의 POD 배포되어 기존 프로메테우스 서버와 통합

ü  Prometheus 데이터를 Object Storage 버킷에 백업하고 다른 Thanos 구성 요소가 gRPC API 통해 Sidecar 연결된 Prometheus 인스턴스에 액세스

ü  2시간마다 프로메테우스 메트릭을 객체 스토리지로 보냄

ü  사이드카는 Prometheus 끝점을 사용. --web.enable-lifecycle 플래그로 활성화

l   Thanos Query Gateway

ü  PromQL 처리하는 부분으로 필요한 Prometheus sidecar 연결

ü  질의를 Store (Store API), Sidecar등으로 전달하고 수집

ü  타노스의 전역 쿼리 계층(Global query layer) 사용하여 모든 프로메테우스 인스턴스에 대해 PromQL 사용하여 한번에 조회가능

ü  쿼리 구성 요소는 상태 비저장이며 수평 확장이 가능하며 여러 복제본과 함께 배포 가능

ü  사이드카에 연결되면 주어진 PromQL 쿼리를 위해 어떤 프로메테우스 서버에 접속해야 하는지 자동으로 감지

ü  단일 Thanos 쿼리 엔드 포인트에서 여러 메트릭 백엔드를 집계하고 중복 제거하는 기능을 제공

l   Thanos Store Gateway

ü  Store 같은 개념이며, API Gateway 역할을 하며 오브젝트 스토리지에 접근하는 모든 작업은 Store API 사용

ü  Query, Receive, Ruler 등에 존재

ü  사이드카와 동일한 gRPC 데이터 API 구성되어 있지만 개체 저장소 버킷에서 찾을 있는 데이터로 백업

ü  스토어 게이트웨이는 오브젝트 스토리지 데이터에 대한 기본 정보를 캐싱 하기위해 소량의 디스크 공간을 차지 (타노스 쿼리 저장소 역할)

l   Thanos Compactor

ü  오브젝트 스토리지에 저장된 블록 데이터를 압축하여 저장공간 최적화 작업 진행

ü  개체 저장소를 간단히 스캔하고 필요한 경우 압축을 처리

ü  동시에 쿼리 속도를 높이기 위해 다운 샘플링된 데이터 복세본을 만드는 역할 수행

ü  주기적 배치 작업으로 실행하거나 데이터를 빨리 압축하기 위해 상시 실행 상태로 있음

ü  데이터 처리를 위해 100GB ~ 300GB 로컬 디스크 공간을 제공하는 것이 좋음  

ü  동시성이 보장되지 않으므로 전체 클러스터에서 싱글톤 형식으로 배포하고 버킷에서 데이터를 수동으로 수정할 실행하면 안됨

l   Thanos Ruler

ü  타노스 사이드카가 적용된 프로메테우스의 보존기간이 충분하지 않거나 전체 보기가 필요한 알림 또는 규칙 구성

ü  Thanos 쿼리 구성 요소에 연결하고 Prometheus Alert Record 규칙을 평가

ü  Prometheus Alert Manager 사용하여 Alert 트리거 있음

l   Thanos Receiver

ü  프로메테우스 서버에서 remote_write 통해 메트릭 데이터 수신할 사용

ü  기본 2시간 단위로 TSDB 블록을 만들어 오브젝트 스토리지에 저장

 

 

아키텍처를 살펴보고 요악하면 다음과 같은 활용을 구상해 있다.

l   다수의 프로메테우스 서버를 Global Query view기능을 통해 하나의 인터페이스로 조회 활용

l   Global Query view, 메트릭 duplication 기능으로 프로메테우스 서버가 장애나더라도 서비스 단절이나 데이터 손실 방지

l   외부 저장소를 활용할 있으므로 데이터 크기에 따른 스토리지 성능 하락에 대비할 있고, 메트릭 데이터를 영구 보관할 있으므로 다양하게 활용 가능



 

[참고자료]

l   Thanos공식 문서 : https://thanos.io/v0.6/thanos/getting-started.md/

l   Multi-Cluster Monitoring with Thanos : https://particule.io/en/blog/thanos-monitoring/

 

 

 

2023-06-29 / Sungwook Kang / https://sungwookkang.com

 

 

프로메테우스, Prometheus, 모니터링 시스템, Grafana, 그라파나, DevOps, 데브옵스, Kubernetes, 쿠버네티스, 타노스, Thanos, CNCF

[Prometheus] Prometheus 확장 내구성을 위한 다양한 구성 방법들

 

l  Prometheous with Thanos

 

Prometheus(프로메테우스) 모니터링 시스템은 오픈 소스 기반의 모니터링 시스템으로 Kubernetes(쿠버네티스) 활성화 함께 많이 사용되고 있다.  프로메테우스는 구조가 간단하며, 운영이 쉽고 강력한 쿼리 기능을 가지고 있다. 간단한 텍스트 형식으로 메트릭 데이터를 쉽게 익스포트 있으며, key-value 형식의 데이터 모델을 사용한다. 수집된 데이터는 Grafana(그라파나) 통해 시각화를 제공한다.

 

l  Prometheus 구조 개념 : https://sqlmvp.tistory.com/1520

 

프로메테우스의 가장 약점은 확장성과 가용성이다. 프로메테우스는 클러스터가 지원되지 않는 독립형 서비스로, 프로메테우스 서버 장애시 메트릭을 수집할 없다는 것이다. 프로메테우스 서버의 장애시간 또는 재설정 등으로 서버 또는 서비스가 재시작 동안 타켓에 대한 모니터링을 없다면 이는 서비스를 운영하는데 매우 리스크이다.  이러한 문제를 해결하기 위해 여러가지 프로메테우스 서버 구성에 대한 아키텍처를 생각해 있다.

 

[프로메테우스N 구성으로 타켓 서버 중복 모니터링]

대이상의 프로메테우스 서버를 구성하여, 프로메테우스 서버에서 타겟 서버를 교차해서 메트릭을 수집하는 방식이다.

 

이러한 방식으로 구성할 경우 관리 해야하는 프로메테우스 서버도 증가하지만, 모니터링 대상이 되는 타겟 서버 입장에서도 여러 프로메테우스 서버로부터 요청되는 메트릭 데이터를 수집 전달하기 위해 오버헤드가 발생한다. 또한 프로메테우스로 수집된 데이터를 분석할 때에도, 특정 시점에 장애가 번갈아 발생시, 데이터가 한쪽에만 있게 되므로 중앙에서 한번에 분석하기 불편한 단점이 있다.

 

 

[프로메테우스 Federation 구성]

프로메테우스 서버를 여러 구성하고, 프로메테우스 서버가 다른 프로메테우스 서버로 요청하여 데이터를 수집할 있다.

l  Hierarchical Federation 구성은 프로메테우스 서버 사이에 계층을 두고 Tree 형태로 Federation 구성하는 방법이다. 부모 프로메테우스는 자식 프로메테우스들의 통합 메트릭 제공 통합 메트릭을 기반으로 알람을 제공하는 용도로 사용할 있다.

l  Cross-service Federation 구성은 동일 레벨의 프로메테우스 서버사이를 Federation으로 구성하는 방법이다.

 

 

 

Federation으로 구성할 경우, 프로메테우스 서버는 타겟 서버로부터 일정 주기로 데이터를 수집하고 저장하고, 부모(중앙) 프로메테우스 서버는 프로메테우스 서버로부터 저장된 데이터를 별도의 주기로 수집할 있어, 데이터양이 많을 , 평균값이나 해상도 등을 조정할 있다. 예를들면 프로메테우스 서버는 10 단위로 수집하고, 중앙 프로메테우스는 1 단위로 하위 프로메테우스 서버로 요청하여 평균값 등을 이용할 있다. 하지만 프로메테우스 서버 장애 데이터 유실, 데이터 증가로 인한 중앙 프로메테우스 서버의 오버헤드 증가 문제가 있으므로 일정 규모 이상에서는 적용하기 힘든 부분이 있다.

 

 

[프로메테우스 Thanos 구성]

Thanos 프로메테우스의 확장성과 내구성을 향상 시키기 위한 오픈소스 프로젝트로, 프로메테우스의 메트릭 데이터를 분산된 원격 스토리지에 저장하고 조회할 있는 기능을 제공한다. 아래 그림에서 서드파티 스토리지로 데이터를 저장하기 위한 Adapter 역할이 Thanos 기능이다.

l   Thanos 사용하여 구성 경우 아래와 같은 장점이 있다.

l   Long-term Storage: 원격 스토리지에 데이터를 안정적으로 저장하여 장기적인 데이터 보존을 가능

l   Global Query: 여러 원격 스토리지에서 데이터를 통합하여 조회할 있는 Global Query 기능을 제공하여 분산된 데이터에 대해 단일 쿼리를 실행할 있어 데이터 분석과 모니터링에 유용

l   HA(고가용성): 원격 스토리지에 데이터를 복제하여 프로메테우스 서버 하나가 장애가 발생하더라도 데이터의 고가용성을 보장

 

프로메테우스 Thanos 구성으로 데이터를 수집하여 S3 저장하는 구성하는 구조를 만든다면 아래와 같은 형식으로 아키텍처를 디자인 있다.

1.          Prometheus Thanos 사이드카를 활성화

2.          Sidecar 대화할 있는 기능이 있는 Thanos Querier 배포

3.          Thanos Sidecar S3 버킷에 Prometheus 메트릭을 업로드할 있는지 확인

4.          Thanos Store 배포하여 장기 스토리지( 경우 S3 버킷) 저장된 메트릭 데이터를 검색

5.          데이터 압축 다운 샘플링을 위해 Thanos Compactor 설정

 

 

다양한 구성으로 프로메테우스의 단점인 확장 내구성을 보완하는 방법에 대해서 살펴보았다. 여러 방식이 있겠지만 현재 대규모 서비스에서는 Thanos 구성이 가장 많이 사용되는 하다. Thanos 아키텍처 자세한 내용은 다른 포스트에서 다뤄볼 예정이다. 모니터링을 구성하는데 있어서 정답은 없다. 항상 우리가 가진 리소스 환경에서 가장 최선의 방법을 찾는 것이 중요할 하다.

 

참고자료 :

l   https://wikitech.wikimedia.org/wiki/File:Prometheus_federation.png

l   https://prometheus.io/docs/prometheus/latest/federation/

l   https://www.robustperception.io/federation-what-is-it-good-for/

l   https://aws.amazon.com/blogs/opensource/improving-ha-and-long-term-storage-for-prometheus-using-thanos-on-eks-with-s3/

l   https://thanos.io/v0.6/thanos/getting-started.md/

l   https://particule.io/en/blog/thanos-monitoring/

 

 

 

2023-06-28 / Sungwook Kang / https://sungwookkang.com

 

 

프로메테우스, Prometheus, 모니터링 시스템, Grafana, 그라파나, DevOps, 데브옵스, Kubernetes, 쿠버네티스

[Prometheus] Prometheus 구조 개념

 

l  Prometheous

 

Prometheus(프로메테우스) 모니터링 시스템은 오픈 소스 기반의 모니터링 시스템으로 Kubernetes(쿠버네티스) 활성화 함께 많이 사용되고 있다. 물론 쿠버네티스 환경 외에도 일반적인 온프레미스 환경에서도 사용이 가능하여 많은 인기를 끌고 있다.  현재 CNCF(Cloud Native Computing Foundation) 소속되어 있다.

 

프로메테우스는 구조가 간단하며, 운영이 쉽고 강력한 쿼리 기능을 가지고 있다. 간단한 텍스트 형식으로 메트릭 데이터를 쉽게 익스포트 있으며, key-value 형식의 데이터 모델을 사용한다. 수집된 데이터는 Grafana(그라파나) 통해 시각화를 제공한다.

 

프로메테우스는 순전히 숫자로 시계열을 기록하는 적합하다. 기계 중심 모니터링과 고도로 동적인 서비스 지향 아키텍처 모니터링 모두에 적합하다. 프로메테우스는 중단 중에 신속하게 문제를 진단할 있도록 하는 시스템으로서 안정성을 위해 설계되어있으며, 프로메테우스 서버는 독립형으로 동작하며, 네트워크 스토리지 또는 기타 원격 서비스에 의존하지 않는다.

 

대부분의 모니터링 시스템은 타켓 서버(모니터링 대상 서버) 에이전트를 설치하여 중앙의 모니터링 수집 서버로 push(푸시) 하는 방식인데, 프로메테우스는 pull() 방식을 사용하여 데이터를 수집한다. 모니터링 대상 서버에 exporter(익스포터)라는 에이전트가 실행되어 있으면, 주기적으로 에이전트에 접속하여 데이터를 가져오는 방식이다.

 

l  Jobs / Exporter : 프로메테우스가 모니터링 데이터를 가져갈 있도록 타겟 서버에 설치되는 에이전트 이다. 서버 상태를 나타내는 Node exporter, DB 상태를 나타내는 SQL Exporter 다양한 커스텀 익스포터들이 개발되어 사용되고 있다. 익스포터 자체는 특별한 기능을 수행하지 않는다. 프로메테우스의 요청이 있을 시점에 메트릭을 수집하여 http get 방식으로 리턴한다. 히스토리를 저장하지 않기 때문에 시점의 값만 있다.

l  Pushgateway : Pushgateway는보안상의 이유로 프로메테우스가 직접 익스포터에 연결 없을 , Proxy Forwarding 사용하여 메트릭 데이터를 수집할 있도록 해주는 서비스이다. Application pushgateway 메트릭 데이터를 푸쉬하면, 프로메테우스 서버가 pushgateway 접근해 메트릭 데이터를 하는 방식으로 동작한다.

l  Alertmanager: Alertmanagr 메트릭에 대한 특정 룰을 설정하고 규칙을 위반하는 사항에 대해 알람을 전송하는 역할을 한다. 예를들면 “CPU 사용률이 50% 이상일때 알람을 보낸다.” 라고 룰을 설정하면, 수집된 CPU 메트릭의 값이 50 이상일때 알람을 발송한다.

l  Service discovery : 프로메테우스는 기본적으로 방식을 사용하여 모니터링을 하기 때문에 모니터링 대상 서버의 목록을 유지하고 있어야 한다. 쿠버네티스 환경처럼 오토스케일이 발생할 경우, 타겟 서버의 IP 가변적이어서 수집할 서버의 목록을 확인할 없는 경우가 많다. 이런 경우 모니터링 대상 목록을 관리하기 위해 서비스 디스커버리를 사용하여 유지한다.

l  Retrieval : 익스포터로 부터 주기적으로 메트릭을 수집하는 모듈이며, 서비스 디스커버리 시스템으로 부터 모니터링 대상 목록을 받아오는 역할도 수행하는 컴포넌트이다.

l  HDD/SDD : 수집된 데이터는 프로메테우스 서버의 로컬 메모리와 디스크에 저장된다. 단순하고 사용이 쉬운 방면, 별도의 데이터베이스가 없으므로 확장이 불가능하다.

l  Data visualization : 저장된 메트릭은 PromQL 쿼리 언어를 사용하여 조회가 가능하다. 또한 외부 API 프로메테우스 웹콘솔을 사용하여 visualization 구성할 있다.

 

프로메테우스 서버는 독립적인 구조로 운영되기 때문에, 많은 수의 모니터링 서버에서 대량의 메트릭을 수집할 프로메테우스 서버의 시스템 리소스가 부족할 경우 확장이 불가능한 구조로 되어 있다. 또한 프로메테우스 서버가 다운되거나 설정 변경으로 인한 재시작시 메트릭이 저장되지 않고 유실되는 문제가 있다. 이러한 문제를 수정하기 위해 프로메테우스 서버를 다양한 형태로 구성 운영하기 위한 노하우가 필요 하다. 부분은 다른 포스트에서 다루어 본다.

 

 

 

참고자료 :

https://prometheus.io/docs/introduction/overview/

 

 

2023-06-28 / Sungwook Kang / https://sungwookkang.com

 

 

프로메테우스, Prometheus, 모니터링 시스템, Grafana, 그라파나, DevOps, 데브옵스, Kubernetes, 쿠버네티스

[스마트팜] Arduino IDE 설치 세팅 (with ESP32 보드)  

 

스마트팜을 제어하기 위해 사용된 아두이노 IoT 시스템을 개발하기 위한 환경 세팅에 대해서 알아본다. 필자의 스마트팜에 사용된 환경은 Arduino IDE ESP32 보드를 사용하였으므로 이번 포스트에서는 IDE 설치 보드에 대한 드라이버 설치까지의 과정을 다룬다.

(다른 보드를 사용한다면 드라이버만 다를 설치 방법은 동일하다.)

 

Arduino IDE 다운받기 위해서 아래 주소로 접속하여 OS 맞는 설치 버전을 선택한다.

l   https://www.arduino.cc/en/software

 

 

 

필자의 경우 Windows 11환경에서 설치를 진행하였으며, 설치 스크린샷 또한 Windows 환경에서 캡처한 것이다. OS 맞는 설치 파일을 클릭하면 다운로드 페이지로 이동되는데, 이때 다운로드만 하려면 “JUST DOWNLOAD” 선택하고, 기부 다운로드 하려면 “CONTRIBUTE & DOWNLOAD” 선택한다.

 

 

설치 파일을 다운로드 하고, 실행하면 설치 과정이 진행된다. 사용권 계약에서 동의함 선택한다.

 

 

설치 옵션에서, 필요한 사용자를 선택 다음을 클릭한다. 필자의 경우 누구나 IDE 실행할 있도록, 모든 사용자 옵션을 선택하였다.

 

 

다시 한번 사용권 계약 단계에서 동의함 선택한다.

 

 

사용자 환경에 따라 설치 위치를 선택한다. 필자는 기본 경로 그대로 사용하였다.

 

 

설치가 진행된다.

 

 

설치 과정에서 추가로 필요한 소프트웨어 팝업이 나타나면 설치를 진행한다. 사용자 상태에 따라 해당 설치 과정이 나타나지 않을 있는데, 해당 단계가 나타나지 않으면 포스트 하단에 USB 드라이버 추가 설치 과정이 있으니 참고할 있도록 한다.

 

 

설치가 완료되면 아래와 같은 화면이 나타나며, 마침을 클릭하면 Arduino IDE 실행된다.

 

 

Arduino IDE 실행될 , 아래와 같이 Windows 보안 경고가 나타나면 액세스 허용 선택한다.

 

아래 그림처럼 Arduino IDE 실행된 것을 확인할 있다.

 

 

지금까지는 Arduino IDE 툴만 설치된 상태이다. ESP32보드를 연결하려 해당 보드에 대한 드라이버를 설치해야 한다. [파일] – [환경설정] 클릭한다.

 

 

추가적인 보드 매니저 URLs에서 우측의 버튼을 클릭한다.

 

 

팝업이 나타나면 아래 URL 입력하고, 확인을 클릭한다.

l   https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_dev_index.json

 

 

속성 창에서 확인을 클릭하면 해당 변경사항이 적용된다.

 

 

[Tool] – [Board] – [Board Manager] 선택 한다.

 

 

검색창에서 “ESP32” 입력하면 설치할 있는 패키지가 검색되며, 필요한 버전을 선택하여 설치한다. 필자의 경우 최신 버전을 선택하여 설치하였다. Output창에서 설치 과정을 확인할 있다.

 

 

패키지 인스톨이 완료되었으면, [Too] – [Board] – [esp32] – [ESP32 Dev Module] 선택한다. 사용자의 보드에 따라 적절한 디바이스를 선택하면 된다.

 

 

모듈이 선택되고 나면, [Tool] 메뉴에서 선택된 모듈에 대한 정보를 확인할 있다.

 

 

 

USB 드라이버 설치 :

Arduino IDE 툴에서 Port 선택이 안되는 경우에는 시스템에서 USB 드라이버 설치가 정상적으로 설치되지 않았을 가능성이 크다. 윈도우에서는 장치관리자에서 아래와 같이 확인할 있다.

 

 

아래 사이트에서 OS 적합한 드라이버를 다운로드한다.

l   https://www.silabs.com/developers/usb-to-uart-bridge-vcp-drivers?tab=downloads

 

 

다운로드 받은 경로로 드라이버 업데이트를 진행한 다음, 정상적으로 설치가 되면 아래와 같이 포트 번호를 확인할 있다.

 

 

지금까지 설치과정으로 IDE 설치 드라이버 설치가 완료된 상태로, 이제 사용자에게 필요한 프로그램을 작성하고 보드에 업로드 있는 환경이 준비완료 되었다.

 

2023-06-10 / Sungwook Kang / http://sungwookkang.com

 

 

스마트팜, Agricultural technology, Agritech, foodtech, 식물 공장, 에어로팜, 분무수경, 수경재배, 아두이노, ESP32, Arduino

 

[스마트팜] 팜랩에 구성된 스마트팜(에어로팜) 훑어보기

 

팜랩(이라 쓰고, 방구석 팜이라 읽는다.) 구성된 시스템에 대한 전체적인 구조를 살펴본다. 이번 포스트는 현재 구성되어 있는 팜의 컨셉 전체적인 모습을 간략히 설명하고, 자세한 제작 과정은 다른 포스팅에서 하나씩 제작 과정을 다뤄 예정이다.

 

참고로 글쓴이의 경우 농사를 경험 해본적이 없고, 친인척, 지인 통틀어 농사와 관련된 사람이 없기 때문에 순수하게 데이터(매뉴얼) 관점에서 재배를 도전하는 중이며, 프로젝트의 컨셉이 데이터로만 농사를 지을 있을까?” 라는 것을 미리 알려둔다. 그래서 모든 부분을 데이터로 관리하고, 최대한 자동화 하여 사람의 손은 최소한으로 투입하는 것을 목적으로 하고 있다.

 

현재 구성되어 있는 팜은 에어로팜으로 분무수경이라고도 한다. 그대로 분무 방식으로 식물을 키우는 것이다. 수경재배는 대부분의 사람들이 알고 있는데, 수경재배는 물에서 식물을 키우지만, 분무는 직접 뿌리에 물을 분사하여 키우는 방식이다. 여려 재배 방식마다 장단점이 있는데, 이러한 부분은 다른 포스팅에서 다뤄본다.

 

아래 사진은 현재 운영중인 나의 1 스마트팜이다. 제작은 빠르게 만들어서 시작을 해본다(?) 라는 컨셉이어서 전선 여러가지가 많이 정리되지 않은 상태이다. 아무래도 팜에는 물이 사용되기 때문에 전기 부분은 매우 조심해야 부분이다. 그래서 현재 2개의 랙을 추가하면서 전기 배선 정리 안전을 위해 전원부를 상단에 배치하는 등의 약간 업그레이드를 하고 있다.

 

팜을 제작할 , 최대한 작업의 손을 타기 위해 규격품을 사용하려고 노력했고, 결과 () 사이즈는 일반 공사 현장(?)에서 사용되는 표준 스펙으로 제작 되었다. 팜의 크기는 가로 200cm X 세로 90cm X 높이 200cm 제작되었다. 대부분의 자재들은 동네 철물점, 다이소 (정말 역할 했음), 온라인 쇼핑몰을 통해서 준비하였다.

 

베드는 스티로폼을 사용하였고, 방수를 위해 PVC 패널을 내부에 장착했다. 분무를 위해 PVC파이프에 노즐을 장착하였다. 현재 상추 뿌리가 많이 자란 상태이며, 건강한 상추는 아래 사진과 같이 새하얀 뿌리를 가지고 있다. 초반에 우여곡절이 많아 뿌리가 검게 상추들도 보인다.

 

 

실내이기 때문에 빛을 보강하기 위해 인공광원으로는 적청색 LED 주광색 LED 사용하였다. LED 발열이 있기 때문에 방열판 역할을 있는 지지대를 사용하였다. 현재 룩스는 15000lx 확보했지만, 태양빛을 따라 가기엔 역부족이다. 하지만 룩스를 올리려면 많은 조명이 필요한데, 전기세 걱정도 있지만 발열로 인한 온도 부분도 문제가 되기 때문에 추가 냉각장치 등을 고려하면 여러 시스템이 필요하게 되어 비용이 급상승한다.

 

공기중 온습도, 수온, 펌프 컨트롤등의 각종 센서 컨트롤러는 아두이노  ESP32 보드를 사용하였다. 보드의 특징은 WiFi Bluetooth 모듈이 장착되어 있어, 별도의 WiFi 모듈을 장착하지 않고도 인터넷에 연결할 있다. 아두이노에서 중앙서버와 통신하며 데이터 전송 컨트롤에 대한 정보를 수신한다. 시스템별로 별도의 아두이노가 장착되어 운영되고 있다.

 

 

에어로팜(분무수경) 방식이기 때문에, 분무를 분사하기 위해서는 어느정도 높은 압력이 필요하다. 현재 일반 가정집 환경에서 랩을 구성하였기 때문에 압력이 높으면서 최대한 소음이 적은 제품을 선별하였다. 또한 국내에는 적절한 것을 찾지 못하여, 캠핑카에 사용되는 펌프를 아마존에서 주문했다. 미국에서 배송되어 배송 기간이 2주이상 소요되었는데, 국내에도 찾아보면 적당한 펌프가 있으리라 생각된다. 아무리 저소음이어도 일반적으로 생활하기에는 소음으로 인해 별도 공간을 분리할 밖에 없다. 상대적으로 조용한것이며 절대적인 소음으로는 직접 겪어보면 옆집에 민폐가 발생할 수도 있다. 사진처럼 방음 박스를 만들고 차음재, 흡읍재 사용했음에도 불구하고, 펌프 진동 소음이 일상 생활하기에는 많이 거슬린다. (그래서 결국 식물에 방을 양도하고 워크 스페이스를 다른 방으로 옴겼다.)

 

양액 탱크이며, 현재 관수 시설이 되어 있지 않아 양액 보충 농도 조절은 수동으로 하고 있다. 부분도 자동화를 하고 싶은 마음은 있지만 일반 가정집의 방에 구성하였기에 관수 시설을 설치하기에는 여러 어려움이 있다. (심지어 현재 글을 쓰는 시점에는 인테리어를 새로 리뉴얼한지 1 조금 지난 시점이어서 벽지나 기타 방에 있던 무언가에 어떤 문제가 생기면 뒷말은 생략한다.)

중앙 서버 데이터 저장을 위한 데이터베이스는 스펙이 필요하지 않기에 사용하지 않는 랩탑을 사용하였으며, Python Fast API 서버를 만들고, DB SQL Server 무료버전을 사용하였다. 모니터링을 위한 대시보드는 그라파나(Grafana) 오픈소스를 사용하여 제작하였으며 실시간 모니터링을 하고 있다. 웹브라이저로 접근이 가능하기 때문에 외부에서도 모니터링 있다.

 

아직 준비 되지 않은 부분은 이상현상이 발생하였을 , 사용자에게 알람을 푸시해 주는 기능과, 냉각 보온에 대한 자동화 부분이 준비 되지 않은 터라 부분은 향후 개선할 예정이다.

 

글을 보고 집에서 스마트팜을 구성하려는 사람이 있을꺼라 생각하는데, 실제로 취미로 즐기기엔 예상보다 많은 비용과 시간이 필요하다. 팜을 만들기 위한 자재비도 자재비지만, 냉각을 위한 에어컨, 히터등도 구비해야하기에 사실상 비용 부분으로 인해 접근이 쉽지 않은 부분이 있다. 또한 모든 자재를 구입해서 DIY 하였기에 노동의 시간도 많이 필요하였다.

 

 

이번 포스트에서는 전체적인 구성에 대하서 살펴보았으며, 다른 포스트에서 팜의 제작과정을 다뤄 보도록 한다.

 

2023-03-23 / Sungwook Kang / http://sungwookkang.com

 

 

스마트팜, Agricultural technology, Agritech, foodtech, 식물 공장, 에어로팜, 분무수경, 수경재배

 

[스마트팜] 나는 농업(스마트팜) 관심을 가지게 되었나?

 

후진국이 공업 발전을 통해 중진국이 수는 있으나 농업 발전 없이는 선진국이 없다
-  사이먼 쿠즈네츠 (노벨 경제학상 수상, 1971) -

 

한국은 불과 세대 전까지만 해도 농업이 주류였다. 그러나 산업화 과정을 겪으면서 많은 사람들이 도시로 몰렸고, 결과 농업에 대한 관심 인구가 급격하게 줄기 시작했다. 그리고 언제부턴가 농업은 사양 산업으로 인식되었다. 이러한 현상은 비단 우리나라 뿐만 아니라 전세계적으로 산업화 과정에서 발생하는 자연스러운 현상이었다.

산업화의 발달과 함께 의식주 위생, 공중보건, 의료 서비스 등이 발전하면서 과거에 비해 질병으로 인한 사망자 감소와 함께 평균 수명 증가로 인해 인구 또한 지속적으로 증가할 것이라고 예상하고 있다. 유엔의 발표에 따르면 2018 기준 세계 인구는 75억명으로 2050년에는 100 명에 달할 것으로 예상하고 있다.

출처 : https://www.hani.co.kr/arti/science/future/1067089.html

 

하지만 자연 환경 파괴 지속적인 기후변화로 인해 식량 생산량은 오히려 감소하고, 저소득층은 극빈층으로 전락할 (2016 식량농업 상황 보고서, 국제연합식량농업기구(FAO))이라는 연구 결과가 나오기도 했다. 향후 세계적으로 식량 안보의 위협을 경고하고 있다.

l   20162025 OECDFAO 농업 전망 : https://www.oecd-ilibrary.org/sites/3b0157bb-ko/index.html?itemId=/content/component/3b0157bb-ko

 

통계청 자료(통계청, 한국의 SDGs 이행보고서 2022) 따르면, 세계 7 곡물 수입국인 한국의 곡물 자급률은 2020 기준 20.2%이다. 쌀을 제외한 나머지 곡물의 자급률은 두류가 7.5%, 옥수수 0.7%, 0.5% 등으로 매우 심각한 수준이다.

 

 

미국의 경우 곡물자급률은 120.1%, 캐나다는 192%, 중국은 91.1%이다. 아래 그림은 2018 세계 곡물 자급률에 대한 자료이다.

출처 : https://www.nongmin.com/323642

 

l   한국의 SDGs 이행보고서 (사회, 경제, 환경 전반에 걸친 한국의 지속가능발전 이행현황을 유엔 SDGs 지표에 근거하여 분석한 보고서) : https://kostat.go.kr/board.es?mid=a90107000000&bid=12317

 

, 주로 식량을 수입하는 한국의 입장에서는 주요 곡물 생산국의 상황(기후 변화, 전쟁 ) 따라 경제적인 물가 영향은 물론이며, 식량이 무기화 되었을 가장 타격을 입게 되는 나라 하나인 것이다.

 

 

지금까지의 글을 통해서 기후변화에 따른 식량 위에게 대해서 심각하게 다루었는데, 이러한 위기를 벗어나기 위해 내가 무엇인가 대단한 일을 하겠다는 것은 아니다. 다만 나라도 이렇게 관심을 가지고 있다 보면 누군가 이러한 문제게 관심을 가지고, 그렇게 점점 확장이 되다 보면 무언가 변화가 있지 않을까 해서이다.

그렇다면 농업에서도 스마트팜에 관심을 가진것일까? 사실 농업의 중요성은 어릴 때부터 관심이 많은 분야였다. 하지만 도시에서 태어나서 도시에서 자란 나는 농사를 접할 기회가 없고 (친인척도 농사를 짓는분은 없엇음) 이미 산업화를 거쳐 정보화 시대를 살고 있는 세대이며, 가지고 있는 기술 또한 IT 이다 보니 내가 가지고 있는 기술을 농업에 활용할 있는 방법이 없을까 고민하다가 도심속에서도 생산이 가능한 스마트팜에 관심을 가지게 되었다. 또한 대부분 도시에서 자란 나의 세대들은 시공간 제약으로 인해 최대한 도시 환경에서 활용할 있는 것을 찾다보니 스마트팜에 이르렀다.

 

그래서 나는 나만의 작은 프로젝트를 진행해 보기로 했다. 생활공간의 일부를 할당하여 작은 스마트팜 연구실을 만들었다. 그리고 나는 테크의 관점에서 농업에 접근하기로 했다. , 인공적인 환경에서 데이터로 식물을 키울 있는가에 대한 실험을 하기로 하였다. 이미 많은 기업들이 스마트팜을 운영하고 있고, 여러 사례 자료가 있지만 일반인들까지 범용적으로 적용할 있는 환경을 고민하고 표준화 하여 누구나 쉽게 접근을 있도록 하는 것이 목표이다. 집에서 스마트팜을 만드는 과정 식물을 키우는 운영 과정을 하나의 일기처럼 공유해볼 생각이다. 아래 사진은 나의 스마트팜(분무수경 방식)에서 상추가 자라고 있는 모습이다.

 

 

2023-03-18 / Sungwook Kang / http://sungwookkang.com

 

 

스마트팜, Agricultural technology, Agritech, foodtech, 식물 공장, 에어로팜, 분무수경, 수경재배

[AWS] AWS Redshift 실행된 쿼리 Slow query 확인

 

l  Version : AWS Redshift, Redshift Serverless

 

AWS Redshift에서 특정 시간이상 실행된 쿼리 또는 사용자에 의한 취소 쿼리 목록 실행시간, 실행된 쿼리 등을 확인하는 방법에 대해서 알아본다.

 

아래 스크립트는 3 이상 실행된 쿼리 목록을 확인하여, WHERE 부분을 수정하여 사용자에 필요한 시간으로 변경하여 사용할 있다. 조회 결과는 오래 수행된 쿼리의 내림 차순으로 표시되며, S3 spectrum 사용할 경우 외부 테이블에 대한 사용 정보도 함께 나태낸다. 쿼리 결과에서 elapsed_time 전체 쿼리가 수행에 걸린 시간을 나타내므로 해당 시간이 클수록 느린 쿼리라고 판단할 있다.

select
        a.query_id,
        a.database_name,
        a.query_type,
        a.start_time,
        a.end_time,
        (a.elapsed_time * 1.0) / 1000 / 1000 as elapsed_time_sec,
        (a.execution_time * 1.0) / 1000 / 1000 as execution_time_sec,
        a.returned_rows,
        a.returned_bytes,
        a.query_text,
        b.source_type, -- Spectrum : S3, 연합쿼리 : PG
        b.duration as external_query_duration,
        b.total_partitions as s3_partition,
        b.qualified_partitions as s3_scan_partiton,
        b.scanned_files as s3_scan_file,
        b.returned_rows as s3_returned_rows,
        b.returned_bytes as s3_returned_bytes,
        b.file_format as s3_file_formant,
        b.file_location as s3_file_location,
        b.external_query_text as external_query_text,
        a.result_cache_hit,
        (a.queue_time * 1.0) / 1000 /1000  as queue_time_sec,
        a.status,
        a.error_message,
        a.user_id,
        a.transaction_id,
        a.session_id
from SYS_QUERY_HISTORY as a
        left outer join SYS_EXTERNAL_QUERY_DETAIL as b on a.query_id = b.query_id
where (a.elapsed_time * 1.0) / 1000 / 1000 > 3 -- 마이크로세컨을 세컨으로 계산하도록 변경. 숫자 변경하여 사용
        and a.status in ('success', 'canceled') -- 사용자 쿼리가 성공 또는 사용자에 의한 취소 쿼리만 조회
/* 사용 가능 status value
planning, queued, running, returning, failed, canceled, success
*/
        and a.start_time >= '2023-01-11 01:00' -- UTC 시간
        and a.end_time <= '2023-01-11 23:00' -- UTC 시간
order by elapsed_time desc

 

[참고 자료]

l  쿼리 계획 : https://docs.aws.amazon.com/ko_kr/redshift/latest/dg/c-the-query-plan.html

l  쿼리 요약 분석 : https://docs.aws.amazon.com/ko_kr/redshift/latest/dg/c-analyzing-the-query-summary.html

l  쿼리 계획 분석 : https://docs.aws.amazon.com/ko_kr/redshift/latest/dg/c-analyzing-the-query-plan.html

l  쿼리 히스토리 : https://docs.aws.amazon.com/ko_kr/redshift/latest/dg/SYS_QUERY_HISTORY.html

l  외부 쿼리 상세 보기 : https://docs.aws.amazon.com/ko_kr/redshift/latest/dg/SYS_EXTERNAL_QUERY_DETAIL.html

l  쿼리 세부 정보 : https://docs.aws.amazon.com/ko_kr/redshift/latest/dg/SYS_QUERY_DETAIL.html

l  서버리스 사용량 확인 : https://docs.aws.amazon.com/ko_kr/redshift/latest/dg/SYS_SERVERLESS_USAGE.html

 

 

 

2023-02-19 / Sungwook Kang / http://sungwookkang.com

 

 

AWS, Redshift, Serverless, SYS_QUERY_HISTORY, SlowQuery, 슬로우 쿼리 확인

[AWS] AWS Redshift Serverless 사용량을 확인하여 빌링비용 예상하기

 

l  Version : AWS Redshift Serverless

 

AWS Redshift Serverless 사용한 RPU (Redshift Serverless 리소스 단위로 RPU 라는 것을 사용한다.) 만큼의 비용이 발생하는 구조이다. 그렇다면 사용자가 쿼리를 실행하였을 , 얼마만큼의 RCU 사용하였는지 확인하여 예상 빌링 비용을 산출하는 방법에 대해서 알아본다.

 

AWS Redshift Serverless 환경에서 쿼리를 실행을 완료한 다음, SYS_SERVERLESS_USAGE 라는 시스템 테이블을 확인하면, 서버가 실행된 시간과 사용된 리소스 사용량을 확인할 있다.

select * from sys_serverless_usage

 

 

이름 데이터 형식 설명
start_time timestamp 시작 시간
end_time timestamp 완료된 시간
compute_seconds double precision 시간 동안 사용된 누적 컴퓨팅 단위(RPU) 이며, 유휴 시간이 포함되어 있음.
compute_capacity double precision 시간 동안 할당된 평균 컴퓨팅 단위(RPU)
data_storage integer 시간 동안 사용된 평균 데이터 스토리지 공간(MB) 으로 사용된 데이터 스토리지는 데이터가 데이터베이스에서 로드되거나 삭제될 동적으로 변경 있음.
cross_region_transferred_data integer 시간 동안 리전간 데이터 공유를 위해 전송된 누적 데이터(byte) .

 

아래 스크립트는 1 사용량에 따른 비용을 계산하는 예제이다. SYS_SERVERLESS_USAGE 시스템 테이블을 쿼리하여 사용량을 추적할 있으며, 쿼리가 처리된 기간의 근사값을 계산할 있다. 현재 서비스 중인 리전의 RPU 가격을 확인하여 대입하면 된다. 아래 스크립트에서는 서울 리전의 RPU 가격을 대입한 결과 이다.

Select
  trunc(start_time) "Day",
  sum(compute_seconds)/60/60 as sum_compute_seconds,
  (sum(compute_seconds)/60/60) * 0.438 as price -- <Price for 1 RPU>
from sys_serverless_usage
group by trunc(start_time)
order by 1

 

 

Redshift Serverless 사용한 만큼 비용이 발생하는 구조이지만, 쿼리가 실패 하였을 경우에는 비용이 발생하지 않는다. 하지만 사용자 요청에 의해 취소되는 작업에 대해서는 취소될 까지 사용된 리소스에 대해서는 비용이 발생한다. 따라서, 실행중인 쿼리를 캔슬하거나 쿼리 타임아웃으로 인해 쿼리가 취소 되지 않도록 시간을 적절히 조절하여 의도하지 않은 불필요한 비용이 발생하지 않도록 한다.

 

Redshift에서 S3 저장된 데이터를 직접 수행할 있도록 하는 Amazon Redshift Spectrum 사용할 경우, 스캔한 바이트 수에 대해 비용이 부과되며 10MB 기준으로 반올림하여 처리 된다. DDL문에 대해서는 파티셔닝 관리와 실패한 쿼리에 대해서는 비용이 부과되지 않는다.

 

AWS S3에서는 Amazon Redshift Serverless 외부 데이터 쿼리는 별도로 청구되지 않으며, Amazon Redshift 서버리스에 대한 청구 금액(RPU) 포함되어 있다.

 

 

[참고자료]

l  https://docs.aws.amazon.com/ko_kr/redshift/latest/dg/SYS_SERVERLESS_USAGE.html

l  https://aws.amazon.com/ko/redshift/pricing/

 

 

 

2023-01-09 / Sungwook Kang / http://sungwookkang.com

 

 

AWS, Redshift, Serverless, SYS_SERVERLESS_USAGE

SQL Server DELAYED_DURABILITY 옵션으로 트랜잭션 로그 쓰기 성능 개선 하기

 

l  Version : SQL Server

 

SQL Server 데이터베이스에는 모든 트랜잭션과 트랜잭션에 의해 적용된 데이터베이스 수정 내용을 기록하는 트랜잭션 로그가 있다. 트랜잭션 로그는 데이터베이스의 매우 중요한 요소로 시스템 오류가 발생한 경우 데이터베이스를 일관된 상태로 다시 전환하려면 로그가 필요하다.

l  트랜잭션 로그 아키텍처 : https://learn.microsoft.com/en-us/sql/relational-databases/sql-server-transaction-log-architecture-and-management-guide?view=sql-server-ver16

 

데이터베이스에 대량의 쓰기 작업이 발생하면 트랜잭션 로그에는 변경사항을 기록하기 위해 오버헤드가 발생하면서 로그 쓰기 작업(Write Log) 지연되는 경우가 발생한다. 로그 모니터링을 통하여 Write Log 지연이 발생할 경우 DELAYED_DURABILITY 옵션을 사용하여 해당 문제를 개선할 있다. 옵션을 사용할 경우 트랜잭션 로그의 커밋을 기다리지 않기 때문에 워크로드의 대기 시간이 줄어들어 성능 개선은 있지만 트랜잭션 데이터를 소실할 있기 때문에 주의해서 사용해야 한다. 이번 포스트에서는 DELAYED_DURABILITY 옵션에 대한 특징을 살펴보고, 어떠한 경우에 사용할 있는지 살펴본다.

 

SQL Server 트랜잭션 로그 파일에 데이터를 저장해야 트랜잭션 로그 파일이 저장된 디스크에 직접 데이터를 기록하지 않는다. 대신 모든 데이터는 인메모리 구조인 로그 캐시(로그 버퍼, 또는 로그 블록 이라고 불리기도 한다.) 직렬로 기록된다. 또한 SQL Server OS ACID 원칙을 준수해야 하므로 전체 로그 캐시를 디스크 하위 시스템에 저장하거나 필요한 경우 롤백 되는 트랜잭션 로그 파일로 플러시 한다. 로그 캐시의 크기는 512B ~ 64KB이다.

 

로그 캐시는 특정 조건에서 디스크로 플러시 된다.

l  트랜잭션이 커밋될

l  로그 캐시가 가득 차서 60KB 도달했을

l  Sys.sp_flush_log 실행될

l  CHECKPOINT 프로세스가 완료 되었을

 

SQL Server 로그 캐시가 트랜잭션 로그 파일로 플러시 되기 시작하는 순간 WRITELOG 대기 유형에 등록되고 로그 캐시가 메모리에서 디스크 드라이브의 파일로 데이터 플러시를 완료 때까지 해당 시간이 누적된다. 누적시간이 낮을수록 트랜잭션 로그파일의 쓰기 대기 시간이 낮아 진다.

 

SQL Server에서는 기본적으로 동기 트랜잭션 커밋을 사용하기 때문에 트랜잭션에 대한 로그 레코드가 디스크에 기록된 후에만 커밋을 성공으로 보고하고 클라이언트에 컨트롤을 반환한다. 따라서 이러한 커밋이 느릴수록 클라이언트에서는 느린 응답을 받을 수밖에 없다. 동기 커밋은 아래와 같은 완전 내구성이 있는 환경의 경우 필수적으로 사용해야한다.

l  시스템에서 데이터 손실을 허용할 없는 경우

l  병목 현상의 원인이 트랜잭션 로그 쓰기 대기 시간이 아닌 경우

 

DELAYED_DURABILITY 옵션을 활성화 경우, 비동기 트랜잭션 커밋을 사용하기 때문에 트랜잭션에 대한 로그 레코드가 디스크에 기록되기 전에 커밋 성공으로 클라이언트에 컨트롤을 반환하기 때문에 클라이언트에서는 빠른 응답을 얻을 있다. 또한 동시 트랜잭션의 로그 I/O 경합 가능성이 낮아지고, 청크 구성으로 디스크에 플러시하여 경합을 줄이고 처리 속도를 높일 있다. 비동기 커밋의 경우 아래와 같은 환경에서 사용할 있다.

l  약간의 데이터 손실을 허용하는 경우

l  트랜잭션 로그 쓰기 중에 병목 현상이 발생하는 경우

l  작업의 경합률이 높은 경우

 

DELAYED_DURABILITY 옵션은 데이터베이스 수준에서 트랜잭션 내구성 수준을 제어할 있다. 아래 스크립트는 DELAYED_DURABILITY 옵션을 데이터베이스 수준에서 변경한다.

ALTER DATABASE ... SET DELAYED_DURABILITY = { DISABLED | ALLOWED | FORCED }

 

l  DISABLED : 기본값으로 커밋 수준 설정 (DELAYED_DURABILITY={ON|OFF}) 상관없이 데이터베이스 커밋된 모든 트랜잭션이 완전 내구성을 가진다. 저장 프로시저를 변경하고 다시 컴파일할 필요가 없다. 지연된 내구성으로 인해 데이터가 위험에 노출되지 않는다.

l  ALLOWED : 트랜잭션의 내구성이 트랜잭션 수준에서 결정된다. 커밋 수준 설정 (DELAYED_DURABILITY={ON|OFF}) 의해 결정된다.

l  FORCED : 데이터베이스에 커밋되는 모든 트랜잭션이 지연된 내구성을 가진다. 설정은 지연된 트랜잭션 내구성이 데이터베이스에 유용하고 어플리케이션 코드를 변경하지 않으려는 경우에 유용하다.

 

 

아래 스크립트는 커밋 수준을 설정한다.

DELAYED_DURABILITY = { OFF | ON }

 

l  OFF : 기본값으로 DELAYED_DURABILITY = FORCED 데이터베이스 옵션을 적용하여 커밋이 비동기적이고 지연된 내구성을 갖는 경우를 제외하고 트랜잭션은 완전 내구성을 가진다.

l  ON : DELAYED_DURABILITY = FORCED 데이터베이스 옵션을 적용하여 커밋이 동기적으로 완전 내구성있는 경우를 제외하고 트랜잭션은 지연된 내구성을 가진다.

 

아래 스크립트는 저장 프로시저에 커밋 수준을 적용한 예시이다.

CREATE PROCEDURE [<procedureName>] /* parameters go here */
WITH NATIVE_COMPILATION, SCHEMABINDING, EXECUTE AS OWNER   
AS BEGIN ATOMIC WITH    
(   
    DELAYED_DURABILITY = ON,   
    TRANSACTION ISOLATION LEVEL = SNAPSHOT,   
    LANGUAGE = N'English'   
)   
/* procedure body goes here */
END

 

 

지연된 트랜잭션 내구성을 강제로 적용할 있도록 COMMIT 구문으로도 확장할 있는데, 데이터베이스 수준에서 DELAYED_DURABILITY DISABLED 또는 FORCED 경우 COMMIT 옵션은 무시된다.

COMMIT [ { TRAN | TRANSACTION } ] [ transaction_name | @tran_name_variable ] ] [ WITH ( DELAYED_DURABILITY = { OFF | ON } ) ]

 

l  OFF : 기본값으로 DELAYED_DURABILITY = FORCED 데이터베이스 옵션을 적용하여 CIMMIT 비동기 적으로 지연된 내구성을 갖는 경우를 제외하고 COMMIT 트랜잭션은 완전 내구성을 가진다.

l  ON : DELAYED_DURABILITY = DISABLED 데이터베이스 옵션을 적용하여 COMMIT 동기적이고 완전 내구성 있는 경우를 제외하고 COMMIT 트랜잭션은 지연된 내구성을 가진다.

 

 

지연된 내구성을 사용할 경우 특정 상황에서 데이터를 손실 가능성이 있기 때문에 반드시 해당 비즈니스의 목적과 데이터베이스 성능 등을 고려하여 사용 여부를 결정할 있도록 한다.

 

[참고자료]

l  Control Transaction Durability : https://learn.microsoft.com/en-us/sql/relational-databases/logs/control-transaction-durability?view=sql-server-ver16

l  Measure Delayed Durability impact in SQL Server 2016 and later : https://www.mssqltips.com/sqlservertip/6355/measure-delayed-durability-impact-in-sql-server-2016-and-later/

l  Get SQL Server Delayed Durability Advantages Without Configuration Changes : https://www.mssqltips.com/sqlservertip/6324/get-sql-server-delayed-durability-advantages-without-configuration-changes/

l  How to handle the SQL Server WRITELOG wait type : https://www.sqlshack.com/how-to-handle-the-sql-server-writelog-wait-type/

l  Improve SQL Server transaction log performance with Delayed Durability : https://www.sqlshack.com/improve-sql-server-transaction-log-performance-with-delayed-durability/

l  The Transaction Log (SQL Server) : https://learn.microsoft.com/en-us/sql/relational-databases/logs/the-transaction-log-sql-server?view=sql-server-ver16

l  SQL Server Transaction Log Architecture and Management Guide : https://learn.microsoft.com/en-us/sql/relational-databases/sql-server-transaction-log-architecture-and-management-guide?view=sql-server-ver16

 

 

 

2022-10-30/ Sungwook Kang / http://sungwookkang.com

 

 

 

SQL Server, MS SQL, DELAYED_DURABILITY, 트랜잭션 로그 비동기 커밋, WAL, Write Log

SQL Server 에서 AWS S3 직접 백업하기

 

l  Version : SQL Server 2022

 

SQL Server 2022부터는 데이터 플랫폼에 통합 오브젝트 스토리지를 도입하여 Azure Storage외에도 AWS S3 호환 오브젝트 스토리지도 사용할 있다. , SQL Server에서 AWS S3 직접 백업을 있게 되었다.

기존 SQL Server 2019 경우 Microsoft Azure 저장소만 가능 하였다. SQL Server 2022 부터 도입된 S3 REST API SQL Server에서 AWS S3 직접 백업, 복원을 있어, 백업 이동에 따른 프로세스 단축 대용량 백업을 진행할 경우에도 로컬 공간이 부족하여도 백업을 진행할 있게 되었다.

 

지원되는 백업 종류

l  전체 백업

l  차등 백업

l  트랜잭션 로그 백업

l  복사 전용 백업 (COPY ONLY)

 

지원되지 않는 백업 종류

l  스냅샷 백업 (FILE_SNAPSHOT)

l  미러 백업 (MIRROR)

 

AWS S3버킷으로 백업 복원을 수행 하기위해서는 아래 정보가 필요 하다.

l  S3 버킷이름

l  S3 URI

l  S3 URL

l  IAM 액세스 ID

l  IAM 액세스

 

AWS IAM(Idnetity Access Management) 정책은 사용자의 권한 또는 특정 서비스에 대해 수행할 있는 역할을 정의한다. SQL Server 2022에서 S3 버킷으로 직접 데이터베이스 백업을 수행하려면 ListBucket PutObject 권한이 필요하다.

l  ListBucket : ListBucket 액세스는 요청의 인증된 발신자가 소유한 모든 버킷 목록을 반환한다.

l  PutObject : PutObject 액세스를 통해 버킷에 객체를 작성하고 추가할 있다.

 

SQL Server에서 AWS S3 백업을 하기 위해 우선 자격증명을 만들어야 한다. 아래는 자격증명을 만드는 스크립트이다.

CREATE CREDENTIAL   [s3://<endpoint>:<port>/<bucket>]
WITH   
        IDENTITY    = 'S3 Access Key',
        SECRET      = '<AccessKeyID>:<SecretKeyID>';

 

l  [s3://<endpoint>:<port>/<bucket>] : 자격 증명 이름에는 S3 버킷 이름이 포함되어야 한다. S3:// 시작하고 접두사 HTTPS:// 제거한 S3 버킷 URL 따른다.

l  IDENTITY : S3 Access Key 값으로, 자격 증명에서 S3 커넥터를 사용하고 있음을 나타낸다.

l  SECRET : 접근키 ID 비밀 키를 콜론으로 구분하여 입력한다. 콜론 기호는 구분자 역할을 한다.  

 

 

 

백업 명령은 기존에 사용하던 백업문과 거의 동일하다. 다만 백업 위치가 DISK 아닌 URL 사용한다.

BACKUP DATABASE [DatabaseName] TO URL = 'CredentialName\Backupfilename.bak'

 

 

백업 완료 S3 확인해보면 백업파일이 생성된 것을 확인할 있다.

 

아래 스크립트는 백업하려는 데이터베이스를 여러 스트라이프된 백업 파일로 오브젝트 스토리지 엔드포인트를 사용하여 백업을 수행한다.

BACKUP DATABASE <db_name>
TO      URL = 's3://<endpoint>:<port>/<bucket>/<database>_01.bak'
,       URL = 's3://<endpoint>:<port>/<bucket>/<database>_02.bak'
,       URL = 's3://<endpoint>:<port>/<bucket>/<database>_03.bak'
--
,       URL = 's3://<endpoint>:<port>/<bucket>/<database>_64.bak'
WITH    FORMAT -- overwrite
,       STATS               = 10
,       COMPRESSION;

 

 

 

아래 스크립트는 오브젝트 스토리지 엔드포인트 위치에서 데이터베이스 복원을 수행한다.

RESTORE DATABASE <db_name>
FROM    URL = 's3://<endpoint>:<port>/<bucket>/<database>_01.bak'
,       URL = 's3://<endpoint>:<port>/<bucket>/<database>_02.bak'
,       URL = 's3://<endpoint>:<port>/<bucket>/<database>_03.bak'
--
,       URL = 's3://<endpoint>:<port>/<bucket>/<database>_64.bak'
WITH    REPLACE -- overwrite
,       STATS = 10;

 

 

데이터를 저장하려면 S3 호환 오브젝트 스토리지 공급자는 파트(Part) 불리는 여러 블록으로 파일을 분할해야 한다. 파일은 최대 10,000개의 파트로 분할 있으며, 파트의 크기는 5MB ~ 20MB이다. 범위는 매개변수 MAXTRANSFERSIZE 통해 T-SQL BACKUP 명령으로 제어할 있다. MAXTRANSFERSIZE 기본값은 10MB 이므로 파트의 기본 크기는 10MB이다.  , 단일 백업 파일의 크기는 MAXTRANSFERSIZE 기본값으로 설정되어 있을 경우 100,000MB이다. 백업 스트라이프가 100,000MB 초과할 경우 아래와 같은 오류 메시지를 반환한다.

Msg 3202, Level 16, State 1, Line 161
Write on 's3://<endpoint>:<port>/<bucket>/<path>/<db_name>.bak' failed: 87(The parameter is incorrect.)
Msg 3013, Level 16, State 1, Line 161
BACKUP DATABASE is terminating abnormally.

 

단일 백업 파일의 크기가 100,000MB 보다 파일을 백업 해야 경우 최대 64개의 URL 스트라이프 백업을 지원한다. , 가능한 최대 백업 파일 크기는 10,000part * MAXTRANSFERSIZE * URL이다. 압축 백업을 사용할 경우 백업 파일 사이즈가 현저히 많이 줄어들기 때문에 백업 압축 옵션을 적극 활용할 있도록 한다.

아래 예제는 MAXTRANSFERSIZE 사용하여 20MB으로 설정하고, 백업 압축 암호화한다.

CREATE MASTER KEY ENCRYPTION BY PASSWORD = <password>;
GO
 
CREATE CERTIFICATE AdventureWorks2019Cert
    WITH SUBJECT = 'AdventureWorks2019 Backup Certificate';
GO
-- Backup database
BACKUP DATABASE AdventureWorks2019
TO URL = 's3://<endpoint>:<port>/<bucket>/AdventureWorks2019_Encrypt.bak'
WITH FORMAT, MAXTRANSFERSIZE = 20971520, COMPRESSION,
ENCRYPTION (ALGORITHM = AES_256, SERVER CERTIFICATE = AdventureWorks2019Cert)
GO

 

백업 복원 엔진에서 URL 길이는 259바이트로 제한되어 있기 때문에 s3:// 제외하고 사용자의 경로 길이(호스트 이름 + 개체키) 259 - 5 = 254글자까지 입력할 있다. 만약 URL 길이를 초과할 경우 아래와 같은 오류가 반환된다.

SQL Server has a maximum limit of 259 characters for a backup device name. The BACKUP TO URL consumes 36 characters for the required elements used to specify the URL - 'https://.blob.core.windows.net//.bak', leaving 223 characters for account, container, and blob names put together'

 

S3 스토리지는 SQL 호스트와 S3 서버간의 시간 차이가 15분을 초과할 마다 연결을 거부하고 “InvalidSignatureException”오류를 SQL Server 보낸다. SQL Server에서는 아래와 같은 오류로 반환된다.

Msg 3201, Level 16, State 1, Line 28
Cannot open backup device '<path>'. Operating system error 5(Access is denied.).
Msg 3013, Level 16, State 1, Line 28
BACKUP DATABASE is terminating abnormally.

 

 

[참고자료]

l  SQL Server backup to URL for S3-compatible object storage : https://learn.microsoft.com/en-us/sql/relational-databases/backup-restore/sql-server-backup-to-url-s3-compatible-object-storage?view=sql-server-ver16

l  SQL Server back up to URL for S3-compatible object storage best practices and troubleshooting : https://learn.microsoft.com/ko-kr/sql/relational-databases/backup-restore/sql-server-backup-to-url-s3-compatible-object-storage-best-practices-and-troubleshooting?view=sql-server-ver16

l  https://www.mssqltips.com/sqlservertip/7301/sql-server-2022-backup-restore-aws-s3-storage/

l  https://www.mssqltips.com/sqlservertip/7302/backup-sql-server-2022-database-aws-s3-storage/

 

 

 

2022-10-28/ Sungwook Kang / http://sungwookkang.com

 

 

 

SQL Server, MS SQL, AWS S3 backup, S3 백업, 클라우드 백업, cloud backup

[AWS Aurora] Aurora PostgreSQL Auto Vacuum 이해하기

 

l  Version : AWS Aurora PostgreSQL

 

PostgreSQL 오픈소스 관계형 데이터베이스로 AWS PostgreSQL 오픈소스 데이터베이스를 완전 관리형 데이터베이스 서비스로 제공한다.

l  Amazon Aurora : https://aws.amazon.com/ko/rds/aurora/

 

많은 사용자들이 PostgreSQL(이하 PG) 사용할 Vacuum 동작으로 인해 예상하지 못한 성능 하락 문제를 겪고 있는데 Vacuum 수행되었을 발생하는 문제는 무엇이 있는지, 그리고 이러한 문제를 최소화하기 위한 전략이 무엇이 있는지에 대해서 알아본다.

 

[Vacuum 하는 것일까]

Vacuum 일반 적으로 진공 청소기라는 뜻으로, 의미와 동일하게 PG에서 이상 사용되지 않는 데이터를 정리해주는 역할을 한다. 쉽게 예를 들면 디스크 조각모음과 같다.

 

 PG MVCC (Multi Version Concurrency Control, 다중 버전 동시성 제어) 지원하기 때문에 데이터의 삭제, 수정이 발생하면 이상 사용하지 않는 여러 버전의 데이터가 존재한다. 만약 Vacuum 진행하지 않으면 이러한 데이터가 지속적으로 쌓여 실제 테이블 데이터 자체는 적은데 테이블의 공간을 차지하여 테이블이 지속적으로 커지는 문제가 발생한다. 그러면 당연히 불필요하거나 부적절한 인덱스가 증가하여 조회속도가 느려지고, I/O 오버헤드가 증가한다. 또한 트랜잭션 ID 겹침이나, 다중 트랜잭션 ID 겹침 상황으로 오래된 자료가 손실될 수도 있으며 이러한 현상이 지속되면 트랜잭션 ID 재활용하지 못해서 최악의 상황에는 데이터베이스가 멈추는 상황까지 발생할 있다. 이러한 여러 이유로 Vacuum 작업은 이유에 맞게 다양한 주기로, 다양한 대상으로 진행된다.

 

MVCC :
동시접근을 허용하는 데이터베이스에서 동시성을 제어하기 위해 사용하는 방법. , MVCC 모델에서 데이터에 접근하는 사용자는 접근한 시점에서의 데이터베이스의 Snapshot 읽는데, snapshot 데이터에 대한 변경이 완료될 (트랜잭션이 commit )까지 만들어진 변경사항은 다른 데이터베이스 사용자가 없다. 이러한 개념에 의해 사용자가 데이터를 업데이트하면 이전의 데이터를 덮어 씌우는게 아니라 새로운 버전의 데이터를 생성한다. 대신 이전 버전의 데이터와 비교해서 변경된 내용을 기록한다. 이렇게해서 하나의 데이터에 대해 여러 버전의 데이터가 존재하게 되고, 사용자는 마지막 버전의 데이터를 읽게 된다.

 

 

[Vacuum 하는 ]

Vacuum 실행되면 사용되지 않는 Dead Tuple (이하 데드 튜플) FSM(Free Space Map) 반환한다. 데드 튜플은 Vacuum 작업을 통해 FSM 반환되기 전까지는 자리에 새로운 데이터를 저장할 없다. 예를 들어 10 row 가지고 있는 테이블에 update 10만개를 했다면 10만개의 데드 튜플이 생기고, 다시 10만개의 업데이트를 했다면 Vacuum 실행되지 않은 상태에서는 다시 10만개의 데드 튜플이 발생한다. . 해당 테이블은 실제 데이터 10만개와, 20만개의 데드 튜플이 존재하게 된다. 이때 Vacuum 실행하면 20만개의 데드 튜플 공간을 FSM 반환하게 되며 다음 업데이트부터는 해당 공간을 재활용할 있다. 하지만 Vacuum 실행한다고 해서 이미 늘어난 테이블의 크기는 줄어들지는 않으며 해당 공간이 재활용되어 사용되므로 테이블 크기가 이상 늘어나지는 않는다. Vacuum 실행되므로써 FSM 공간반환 뿐만 아니라, 인덱스 전용 검색 성능을 향상하는데 참고하는 자료 지도 (VM, Visivility Map)정보를 갱신한다. 또한 삭제된 데이터뿐만 아니라 남아 있는 데이터에 대해서도 Frozen XID(XID 2) 변경해 주어 앞으로 XID wrap around 발생하더라도 트랜잭션 ID 겹침을 방지할 있다.

 

PG에서는 트랜잭션 ID 크기가 32bit 정수형 크기이며 하나의 서버에서 해당 크기를 넘기면 트랜잭션 ID 겹치는 현상이 발생한다.

 

 

[Vacuum 실행]

Vacuum 작업은 기본적으로 디스크 I/O 오버헤드를 유발한다. 때문에 동시에 작업하고 있는 다른 세션의 성능을 떨어뜨릴 있다. Vacuum 작업에 대한 비용은 아래 링크를 참고한다.

l  Cost-based Vacuum Delay : https://www.postgresql.kr/docs/9.4/runtime-config-resource.html#RUNTIME-CONFIG-RESOURCE-VACUUM-COST

Vacuum 수동 또는 자동으로 실행될 있다. 그리고 Vacuum 실행 옵션에 따른 특징이 있다. 수동으로 실행할 경우 아래와 같은 명령으로 실행할 있다.

-- DB 전체 full vacuum
vacuum full analyze;
 
-- DB 전체 간단하게 실행
vacuum verbose analyze;
 
-- 특정 테이블만 간단하게 실행
vacuum analyze [테이블 ];
 
-- 특정 테이블만 full vacuum
vacuum full [테이블 ];

 

l  Vacuum : 데드 튜플을 FSM 반환하는 작업을 하며, 운영 환경에서도 DML (SELECT, INSERT, UPDATE, DELETE) 실행되고 있어도 동시에 사용할 있다.  하지만 DDL (ALTER TABLE) 명령은 Vacuum 작업이 실행되는 동안에는 사용할 없다.

l  Vacuum FULL : VACUUM FULL 작업은 해당 테이블의 사용할 있는 자료들만을 모아서 파일에 저장하는 방식을 이용하기 때문에 운영체제 입장에서 디스크 여유 공간을 확보할 있다. 작업 결과로 해당 테이블에 대해서 최적의 물리적 크기로 테이블이 만들어진다. 하지만 작업 테이블에 대한 베타적 잠금(Exclusive Lock) 지정하여 실행되기 때문에 어떠한 작업도 없다. (운영중인 데이터베이스에서는 사용 금지) 그리고 일반 VACUUM 작업에 비해 시간이 오래 걸린다. 또한 작업이 완료되기 전까지 작업을 있는 여유 공간이 있어야 작업을 있다.

l  Vacuum Analyze : 통계 메타데이터를 업데이트하므로 쿼리 옵티마이저가 정확한 쿼리 계획을 생성할 있어 Vacuum 명령어 실행 같이 실행하는 것이 좋다.

 

Autovacuum(자동) 내부 알고리즘으로 필요에 따라 Vacuum 자동으로 처리해 주는 것으로 수동처럼 명령어로 테이블을 정리하는 것이 아닌 테이블 혹은 DB 단위의 설정을 통해서 vacuum 진행된다. 이때 설정된 값에 따라서 데드 튜플의 증가를 얼마나 제어할지가 정해지기 때문에 Autovacuum 사용할 때에는 현재 운영중인 서버의 최적화 값을 파악하고 있어야 한다.

 

일반적인 Vacuum 전략은 주기적인 표준 Vacuum 작업을 진행하여 지속적으로 빈공간을 확보하여 디스크가 어느정도 커지지만 이상 커지지 않게 하여 최대한 Vacuum FULL 작업을 방지하는 것이다. Autovacuum 데몬이 이러한 전략으로 작업을 한다. , autovacuum 기능을 사용하되 Vacuum FULL 작업을 하지 않는 것을 기본 정책으로 설정하면 된다. 기본적으로 실시간(주기적) Vacuum(FULL Vacuum아님)실시하며, autovacuum_freeze_max_age 도달하면 강제로 Vacuum 작업을 실시하게 된다.

 

정확한 데이터베이스 사용량을 파악하지 않은 상태에서 autovacuum 기능을 끄는 것은 현명하지 않은 방법일 있다.

 

아래 쿼리는 튜플에 대한 정보를 확인한다.

SELECT
    n.nspname AS schema_name,
    c.relname AS table_name,
    pg_stat_get_live_tuples(c.oid) + pg_stat_get_dead_tuples(c.oid) as total_tuple,
    pg_stat_get_live_tuples(c.oid) AS live_tuple,
    pg_stat_get_dead_tuples(c.oid) AS dead_tupple,
    round(100*pg_stat_get_live_tuples(c.oid) / (pg_stat_get_live_tuples(c.oid) + pg_stat_get_dead_tuples(c.oid)),2) as live_tuple_rate,
    round(100*pg_stat_get_dead_tuples(c.oid) / (pg_stat_get_live_tuples(c.oid) + pg_stat_get_dead_tuples(c.oid)),2) as dead_tuple_rate,
    pg_size_pretty(pg_total_relation_size(c.oid)) as total_relation_size,
    pg_size_pretty(pg_relation_size(c.oid)) as relation_size
FROM pg_class AS c
JOIN pg_catalog.pg_namespace AS n ON n.oid = c.relnamespace
WHERE pg_stat_get_live_tuples(c.oid) > 0
AND c.relname NOT LIKE 'pg_%'
ORDER BY dead_tupple DESC;

 

아래 쿼리는 Vacuum 통계 정보를 확인한다.

SELECT * FROM pg_stat_all_tables ORDER BY schemaname, relname;

 

Vacuum FULL 실행시 pg_class relfilenode 값이 변경된다. 아래 쿼리는 relfilenode 물리적인 파일 위치를 확인한다.

SELECT oid, pg_relation_filepath(oid), relname, relfilenode FROM pg_class LIMIT 10;

 

아래 쿼리는 현재 실행중인 Vacuum세션 정보를 확인할 있다.

SELECT
 datname,
 usename,
 pid,
 CURRENT_TIMESTAMP - xact_start AS xact_runtime,
 query
FROM
 pg_stat_activity
WHERE
 upper(query)
 LIKE '%VACUUM%'
ORDER BY
 xact_start;

 

[Autovacuum 데몬 워크플로우]

Autovacuum 데몬은 Autovacuum 실행기와 Autovacuum 작업자의 가지 다른 종류의 프로세스로 설계되어있다.

 

Autovacuum 실행기는 Autovacuum 매개변수가 on으로 설정될 postmaster 시작하는 기본 실행 프로세스이다. postmaster PostgreSQL 시스템에 대한 요청에 대한 처리 메커니즘 역할을 한다. 모든 프론트 엔드 프로그램은 시작 메시지를 postmaster에게 보내고 postmaster 메시지의 정보를 사용하여 백엔드 프로세스를 시작한다. Autovacuum 실행기 프로세스는 테이블에서 Vacuum 작업을 실행하기 위해 Autovacuum 작업자 프로세스를 시작할 적절한 시간을 결정한다.

Autovacuum 작업자는 테이블에서 vacuum 작업을 실행하는 실제 작업자 프로세스이다. 실행 프로그램에서 예약한 대로 데이터베이스에 연결하고 카탈로그 테이블을 읽고 Vacuum 작업을 실행할 테이블을 선택한다.

Autovacuum 시작 프로그램 프로세스는 데이터베이스의 테이블을 계속 모니터링하고 테이블이 Autovacuum 임계값에 도달한 Vacuum 작업에 적합한 테이블을 선택합니다. 임계값은 아래와 같은 매개변수를 기반으로 한다.

l  autovacuum_vacuum_threshold, autovacuum_analyze_threshold : 매개변수는 각각 autovacuum autoanalyzer 대해 예약할 테이블의 최소 업데이트 또는 삭제 수를 결정한다. 기본값은 50이다.

l  autovacuum_vacuum_scale_factor, autovacuum_analyze_scale_factor : 매개변수는 각각 autovacuum autoanalyzer 대해 예약할 테이블에 대해 변경이 필요한 테이블의 백분율을 결정한다. autovacuum_vacuum_scale_factor 기본값은 0.2(20%)이고 autovacuum_analyze_scale_factor 0.1(10%)이다. 테이블의 수가 너무 많지 않은 경우 기본 값을 사용해도 되지만, 많은 수의 행이 있는 테이블의 경우에는 빈번한 Vacuum 발생할 있어 적절한 값으로 조절하는 것이 좋다. 데이터베이스 내에서 테이블이 일부 존재하는 경우 구성 파일보다 테이블 수준에서 이러한 매개변수를 설정하는 것이 좋다.

 

임계값 계산은 아래 공식을 사용할 있다.

vacuum threshold = vacuum base threshold + vacuum scale factor * number of live tuples

 

l  Vacuum base threshold – autovacuum_vacuum_threshold

l  Vacuum scale factor – autovacuum_vacuum_scale_factor

l  Number of live tuples – The value of n_live_tup from pg_stat_all_tables view

 

Autovacuum 실행기는 자체적으로 Autovacuum 작업자 프로세스를 시작할 없으며 postmaster 프로세스에 의해 수행된다. 런처는 Autovacuum 공유 메모리 영역에 데이터베이스에 대한 정보를 저장하고 공유 메모리에 플래그를 설정하고 postmaster에게 신호를 보낸다. postmaster Autovacuum 작업자 프로세스를 시작한다. 새로운 작업자 프로세스는 공유 메모리에서 정보를 읽고 필요한 데이터베이스에 연결하고 Vacuum 작업을 완료한다.

postmaster 작업자 프로세스 시작에 실패하면 공유 메모리에 플래그를 설정하고 런처 프로세스에 신호를 보낸다. postmaster 신호를 읽고 실행기는 postmaster에게 신호를 전송하여 작업자 프로세스 시작을 다시 시도한다. (postmaster 작업자 프로세스를 시작하지 못하는 것은 로드 메모리 압력이 높거나 이미 실행 중인 프로세스가 너무 많기 때문일 있다).

Autovacuum 작업자 프로세스가 Vacuum 작업으로 완료되면 런처에 신호를 보낸다. 런처가 작업자로부터 신호를 받으면 런처가 깨어나Vacuum 테이블 목록이 공유 메모리에 너무 많으면 다른 작업자를 시작하려고 시도한다. 이는 다른 작업자가 해당 테이블에 대한 Vacuum 잠금을 기다리는데 차단되는 것을 방지하기 위한 것이다. 또한 다른 작업자가 방금 정리를 완료하여 공유 메모리에 이상 기록되지 않은 테이블을 Vacuum하지 않도록 테이블을 Vacuum하기 직전에 pgstats 테이블의 데이터를 다시 로드한다.

PostgreSQL 일반적인 오해는 Autovacuum 프로세스가 I/O 증가시킨다는 것이다. 따라서 많은 사람들이 Autovacuum 프로세스를 완전히 끄도록 선택한다. 이러한 행동은 데이터베이스 운영 초기 단계에서는 효과적인 솔루션처럼 보일 있지만 데이터베이스 크기가 증가하기 시작하면 데드 튜플이 차지하는 공간이 빠르게 증가하고, 테이블 디스크 공간 증가와 함께 데이터베이스 속도가 느려지기 때문에 권장하지 않는다.

 

 

[Autovacuum 장점]

통계 업데이트

PostgreSQL ANALYZE 데몬은 테이블의 통계를 수집하고 계산한다. 쿼리 플래너는 이러한 통계를 사용하여 쿼리 계획을 실행한다. 정보는 ANALYZE 데몬에 의해 계산 수집되며 이러한 통계를 사용하여 카탈로그 테이블에 저장된다. 그런 다음 쿼리 플래너는 데이터를 가져오기 위한 쿼리 계획을 만든다. 비슷한 시나리오에서 Autovacuum off 설정되어 있으면 ANALYZE 데몬이 통계를 수집하고 계산하지 않는다. 쿼리 플래너에는 테이블에 대한 정보가 없으므로 잘못된 쿼리 계획을 작성하게 되어 비용 효율적이지 않다.

 

트랜잭션 warparound 방지

앞서 설명한 것처럼 PostgreSQL 트랜잭션 ID 트랜잭션에 숫자를 할당한다. 트랜잭션 ID 숫자이기 때문에 허용되는 최대값 최소값과 같은 제한이 있다. PostgreSQL 트랜잭션 ID 대한 명확한 숫자로 4바이트 정수를 사용한다. , 4바이트로 생성할 있는 최대 트랜잭션 ID 2^32으로 (~ 4294967296) 40 개의 트랜잭션 ID 사용할 있다. 그러나 PostgreSQL 트랜잭션 ID 1에서 2^31( ~ 2147483648)에서 회전시켜 4바이트 정수로 트랜잭션을 무제한으로 처리할 있다. PostgreSQL 트랜잭션 ID 2147483648 도달하면 트랜잭션 ID 1에서 2 변경하여 2^31까지 할당 트랜잭션을 관리하고, 이후 추가 할당 트랜잭션을 트랜잭션 ID 1 할당하여 사용하는데 이렇게 트랜잭션 ID 교체하는 작업을 warparound라고 한다.

Autovacuum 페이지의 행을 방문하여 트랜잭션 ID 고정한다. 데이터베이스 트랜잭션 ID 수명이 autovacuum_freeze_max_age 도달할 때마다 PostgreSQL Autovacuum 프로세스를 즉시 시작하여 전체 데이터베이스에서 freeze작업을 수행한다.

 

 

[Autovacuum 모니터링]

Autovacuum 효과적으로 작동하는지 확인하려면 데드 튜플, 디스크 사용량, autovacuum 또는 ANALYZE 마지막으로 실행된 시간을 정기적으로 모니터링해야 한다.

 

Dead Tuple

PostgreSQL pg_stat_user_tables 뷰를 제공하는데, 뷰는 테이블(relname) 테이블에 있는 데드 로우(n_dead_tup) 대한 정보를 제공한다. 테이블, 특히 자주 업데이트되는 테이블의 데드 수를 모니터링하면 Autovacuum 프로세스가 주기적으로 제거하여 디스크 공간을 나은 성능을 위해 재사용할 있는지 확인하는 도움이 된다. 아래 쿼리를 사용하여 데드 튜플의 수와 테이블에서 마지막 Autovacuum 실행된 시간을 확인할 있다.

SELECT
relname AS TableName
,n_live_tup AS LiveTuples
,n_dead_tup AS DeadTuples
,last_autovacuum AS Autovacuum
,last_autoanalyze AS Autoanalyze
FROM pg_stat_user_tables;

 

Table Disk Usage

테이블이 사용하는 디스크 공간의 양을 추적하면 시간 경과에 따른 쿼리 성능의 변화를 분석할 있기 때문에 중요하다. 또한 Vacuum 관련된 문제를 감지하는 도움이 있다. 예를 들어 최근에 많은 데이터를 테이블에 추가했는데 테이블의 디스크 사용량이 예기치 않게 증가한 경우 해당 테이블에 vacuuming 문제가 있을 있다.

Vacuuming 오래된 행을 재사용 가능한 것으로 표시하는 도움이 되므로 VACUUM 정기적으로 실행되지 않으면 새로 추가된 데이터는 데드 튜플이 차지하는 디스크 공간을 재사용하는 대신 추가 디스크 공간을 사용한다.

 

Last autovacuum and autoanalyzer

pg_stat_user_tables 보기는 autovacuum 데몬이 테이블에서 마지막으로 실행된 시간에 대한 정보를 제공한다. autovacuum autoanalyze 사용하여 autovacuum 데몬이 효율적으로 작동하는지 추적할 있다. 아래 쿼리는 테이블에서 실행되는 last_autovacuum last_autoanalyze 대한 세부 정보를 제공한다.

SELECT relname, last_autovacuum,last_autoanalyze FROM pg_stat_user_tables;

 

Enabling log_autovacuum_min_duration

log_autovacuum_min_duration 매개변수는 Autovacuum 프로세스가 실행한 모든 작업을 기록하는 도움이 된다. Autovacuum 지정된 시간(밀리초) 동안 실행하거나 임계값 테이블 저장 매개변수를 초과하면 작업이 기록된다. 매개변수를 150밀리초로 설정하면 150밀리초 이상 실행되는 모든 Autovacuum 프로세스가 기록된다. 또한 매개변수가 -1 이외의 값으로 설정되면 충돌하는 잠금으로 인해 Autovacuum 작업을 건너뛸 경우 메시지가 기록된다. 또한 Autovacuum 프로세스의 느린 속도에 대한 자세한 정보를 제공할 있다.

 

Enabling an Amazon CloudWatch alarm

트랜잭션 warparound 대한 Amazon CloudWatch 경보를 설정할 있습니다. 자세한 내용은 아래 링크를 참고한다.

l  Implement an Early Warning System for Transaction ID Wraparound in Amazon RDS for PostgreSQL : https://aws.amazon.com/ko/blogs/database/implement-an-early-warning-system-for-transaction-id-wraparound-in-amazon-rds-for-postgresql/

또한 CloudWatch 지표를 사용하여 전체 시스템 리소스 사용량을 모니터링하고 Autovacuum 세션이 동시에 실행될 허용 가능한 범위 내에 있는지 확인할 있다.

 

 

[일반적으로 자주 겪는 Autovacuum 문제]

Autovacuum parameter tuning

Autovacuum 정기적으로 테이블의 Vacuum 프로세스를 트리거하지 않거나 효율적으로 수행되지 않는 경우 Autovacuum 매개변수 조정을 고려해야 한다. Autovacuum 프로세스는 테이블에서 VACUUM ANALYZE 명령을 자동으로 실행해야 하는 시기를 결정하기 위해 여러 구성 설정에 따라 달라진다. 아래 쿼리는 조정할 있는 Autovacuum 매개변수 목록을 제공합니다.

select category, name,setting,unit,source,min_val,max_val from pg_settings where category = 'Autovacuum' ;

 

 

Settings​​열에는 현재 구성된 값이 표시된다. boot_val열에는 기본 매개변수를 변경하지 않을 사용하는 PostgreSQL에서 설정한 Autovacuum 매개변수의 기본값이 표시된다. 이러한 Autovacuum 매개변수를 조정하면 Autovacuum 프로세스가 테이블에서 자주 효율적으로 작동한다. Autovacuum 조정에 대한 자세한 내용은 아래 링크를 참고한다.

l  A Case Study of Tuning Autovacuum in Amazon RDS for PostgreSQL : https://aws.amazon.com/ko/blogs/database/a-case-study-of-tuning-autovacuum-in-amazon-rds-for-postgresql/

 

Autovacuum skipped due to lock conflicts

테이블에서 Vacuum 실행하려면 Autovacuum 프로세스가 SHARE UPDATE EXCLUSIVE 잠금을 획득해야 하는데, 이는 트랜잭션이 동시에 SHARE UPDATE EXCLUSIVE 잠금을 보유할 없기 때문에 다른 잠금과 충돌한다. 이는 SHARE, SHARE ROW EXCLUSIVE, EXCLUSIVE ACCESS EXCLUSIVE 같은 다른 잠금 모드에서도 동일하다.

SHARE UPDATE EXCLUSIVE 잠금은 SELECT, UPDATE, INSERT 또는 DELETE 차단하지 않으며 아래 잠금이 있는 트랜잭션만 차단한다.

l  SHARE UPDATE EXCLUSIVE – Acquired by VACUUM (without FULL), ANALYZE, CREATE INDEX CONCURRENTLY, REINDEX CONCURRENTLY, CREATE STATISTICS, and certain ALTER INDEX and ALTER TABLE variants.

l  SHARE – Acquired by CREATE INDEX (without CONCURRENTLY).

l  SHARE ROW EXCLUSIVE – Acquired by CREATE TRIGGER and some forms of ALTER TABLE.

l  EXCLUSIVE – Acquired by REFRESH MATERIALIZED VIEW CONCURRENTLY.

l  ACCESS EXCLUSIVE – Acquired by DROP TABLE, TRUNCATE, REINDEX, CLUSTER, VACUUM FULL, and REFRESH MATERIALIZED VIEW (without CONCURRENTLY) commands. Many forms of ALTER INDEX and ALTER TABLE also acquire a lock at this level.

따라서 트랜잭션이 테이블에 대한 이러한 잠금 하나를 유지하라는 요청과 함께 제공되고 Autovacuum 데몬이 이미 해당 테이블 하나에서 Vacuum 작업을 실행 중인 경우, 다른 트랜잭션이 잠금을 취할 있도록 Vacuum 작업을 즉시 취소한다. 유사하게, 트랜잭션이 이미 테이블에 대한 ACCESS EXCLUSIVE 잠금을 보유하고 있는 경우 Autovacuum 해당 테이블을 Vacuuming에서 건너뛴다. Autovacuum 프로세스는 다음 반복에서 Vacuum 작업을 실행하기 위해 건너뛴 테이블을 유지한다.

 

Autovacuum action skipped due long-running transactions

PostgreSQL MVCC 개념을 기반으로 하기 때문에 하나 이상의 트랜잭션이 오래된 버전의 데이터에 액세스하는 경우 Autovacuum 프로세스는 데드 튜플을 정리하지 않는다. 데이터가 삭제되거나 업데이트되기 전에 생성된 데이터의 스냅샷에서 트랜잭션이 작업 중인 경우 Autovacuum 해당 데드 튜플을 건너뛰고 해당 데드 튜플은 다음 반복에서 Vacuum 된다. 이런 케이스는 일반적으로 데이터베이스의 장기 실행 트랜잭션에서 발생한다. 데이터베이스에서 장기 실행 트랜잭션을 찾으려면 아래 쿼리를 실행한다. 예제 쿼리는 5분이상 실행되고 있는 쿼리를 나타낸다.

SELECT now()-query_start as Running_Since, pid, datname, usename, application_name, client_addr , left(query,60) FROM pg_stat_activity WHERE state in ('active','idle in transaction') AND (now() - query_start) > interval '5 minutes';

 

Autovacuum 데드 튜플을 건너뛰게 있으므로 모니터링의 일부로 트랜잭션 세션의 유휴 상태(idle in transaction) 포함하는 것이 좋다.

 

 

[Autovacuum 모범 사례]

Allocating memory for autovacuum

maintenance_work_mem 파라미터는 Autovacuum 성능에 영향을 미치는 중요한 파라미터이다. Autovacuum 프로세스가 데이터베이스의 테이블을 스캔하는 사용할 메모리 양을 결정하고 Vacuum 필요한 ID 보유한다.

매개변수를 낮게 설정하면 Vacuum 프로세스가 테이블을 여러 스캔하여 Vacuum 작업을 완료하므로 데이터베이스 성능에 부정적인 영향을 미친다.

작은 테이블이 많은 경우 autovacuum_max_workers 많이 할당하고 maintenance_work_mem 적게 할당한다. 테이블(100GB 이상) 있는 경우 많은 메모리와 적은 수의 작업자 프로세스를 할당한다. 가장 테이블에서 성공하려면 충분한 메모리가 할당되어야 한다. autovacuum_max_workers 할당한 메모리를 사용할 있다. 따라서 작업자 프로세스와 메모리의 조합이 할당하려는 메모리와 동일한지 확인해야 한다.

 

인스턴스의 경우 maintenance_work_mem 1GB 이상으로 설정하면 많은 수의 데드 튜플이 있는 테이블을 Vacuuming하는 성능이 크게 향상된다. 그러나 Vacuum 메모리 사용을 1GB 제한하는 것이 좋다. 패스에서 1 7,900 개의 데드 튜플을 처리하기에 충분하다. 그보다 많은 데드 튜플이 있는 테이블을 Vacuuming하려면 테이블 인덱스를 여러 통과해야 하므로 Vacuum 훨씬 오래 걸릴 있다. maintenance_work_mem 바이트를 6으로 나누어 단일 패스에서 Vacuum 처리할 있는 데드 튜플 수를 계산할 있다.

autovacuum_work_mem 또는 maintenance_work_mem 매개변수를 설정하면 Autovacuum 작업자 프로세스가 사용해야 하는 최대 메모리 크기가 설정된다. 기본적으로 autovacuum_work_mem -1 설정되며 이는 Autovacuum 작업자 프로세스에 대한 메모리 할당이 maintenance_work_mem 설정을 사용해야 함을 나타낸다.

 

Amazon RDS 파라미터의 기본값은 아래와 같이 계산된 KB 적용되어 있다.

GREATEST({DBInstanceClassMemory/63963136*1024},65536).

 

자세한 내용은 아래 링크를 참고한다.

l  Common DBA tasks for Amazon RDS for PostgreSQL : https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.html#Appendix.PostgreSQL.CommonDBATasks.Autovacuum.WorkMemory

l  A Case Study of Tuning Autovacuum in Amazon RDS for PostgreSQL : https://aws.amazon.com/ko/blogs/database/a-case-study-of-tuning-autovacuum-in-amazon-rds-for-postgresql/

 

Reducing the chances of transaction ID wraparound

일부 사용 사례에서는 조정된 Autovacuum 설정도 트랜잭션 ID warparound 방지할 만큼 공격적이지 않다. 문제를 해결하기 위해 Amazon RDS에는 autovacuum 파라미터 값을 자동으로 조정하는 메커니즘이 있다. 적응형 Autovacuum 파라미터 조정이 활성화된 경우 Amazon RDS CloudWatch 지표 MaximumUsedTransactionIDs 750,000,000 또는 autovacuum_freeze_max_age 값에 도달할 Autovacuum 파라미터 조정을 시작한다.

Amazon RDS 테이블이 계속해서 트랜잭션 ID warparound 향하는 경향이 있을 Autovacuum 대한 매개변수를 계속 조정한다. 조정은 warparound 피하기 위해 Autovacuum 많은 리소스를 할당한다. Amazon RDS 다음과 같은 Autovacuum 관련 파라미터를 업데이트한다.

l  autovacuum_vacuum_cost_delay autovacuum 프로세스가 제한을 초과할 대기하는 지정된 시간(밀리초)이다. 기본값은 20밀리초이다.

l  autovacuum_vacuum_cost_limit Autovacuum 프로세스를 휴면 상태로 만드는 누적 비용으로 기본값은 200이다.

l  autovacuum_work_mem Autovacuum 작업자 프로세스에서 사용하는 최대 메모리 양이다. 기본값은 -1 maintenance_work_mem 값을 사용해야 함을 나타낸다.

l  autovacuum_naptime 주어진 데이터베이스에서 Autovacuum 실행 사이의 최소 지연을 지정한다. 라운드에서 데몬은 데이터베이스를 검사하고 해당 데이터베이스의 테이블에 대해 필요에 따라 VACUUM ANALYZE 명령을 실행한다. 지연은 단위로 측정되며 기본값은 1분이다. 매개변수는 postgresql.conf 파일이나 서버 명령줄에서만 설정할 있다.

 

Amazon RDS 기존 값이 충분히 공격적이지 않은 경우에만 이러한 파라미터를 수정한다. 이러한 파라미터는 DB 인스턴스의 메모리에서 수정되며 파라미터 그룹에서는 변경되지 않는다. Amazon RDS 이러한 Autovacuum 파라미터를 수정할 때마다 Amazon RDS API 통해 AWS Management 콘솔에서 있는 영향을 받는 DB 인스턴스에 대한 이벤트를 생성한다. MaximumUsedTransactionIDs CloudWatch 지표가 임계값 아래로 반환되면 Amazon RDS 메모리의 Autovacuum 관련 파라미터를 파라미터 그룹에 지정된 값으로 재설정한다.

 

Setting autovacuum at table level

글로벌 Autovacuum 설정을 기반으로 증가하는 PostgreSQL 환경에서 테이블은 효과적으로 Vacuum되지 않고 작은 테이블은 자주 Vacuum되는 것을 있다. 이러한 시나리오를 피하기 위해 다음 단계에 따라 테이블 수준에서 Autovacuum 매개변수를 설정할 있다.

1.        데이터베이스에서 테이블을 나열한다.

2.        많은 수의 변경 사항이 발생한 테이블을 나열한다.

3.        어떤 테이블에 'n_dead_tup' 수가 많은지 확인한다.

4.        테이블이 마지막으로 자동 분석 자동 진공 처리된 시간을 확인한다.

5.        테이블 수준에서 Autovacuum Autoanalyze 매개변수를 변경한다.

 

 

[참고자료]

l  Amazon Aurora : https://aws.amazon.com/ko/rds/aurora/

l  정기적인 Vacuum 작업 : https://www.postgresql.kr/docs/9.4/routine-vacuuming.html

l  MVCC : https://en.wikipedia.org/wiki/Multiversion_concurrency_control

l  Free Space Map(FSM) : https://www.postgresql.org/docs/current/storage-fsm.html

l  Visibility Map (VM) : https://www.postgresql.org/docs/current/storage-vm.html

l  Understanding autovacuum in Amazon RDS for PostgreSQL environments : https://aws.amazon.com/ko/blogs/database/understanding-autovacuum-in-amazon-rds-for-postgresql-environments/

l  AWS RDS for PostgreSQL Vacuum Tuning : https://catalog.us-east-1.prod.workshops.aws/workshops/2a5fc82d-2b5f-4105-83c2-91a1b4d7abfe/en-US/3-intermediate/vacuum-tuning

l  Visibility Map Problems : https://wiki.postgresql.org/wiki/Visibility_Map_Problems

l  Cost-based Vacuum Delay : https://www.postgresql.kr/docs/9.4/runtime-config-resource.html#RUNTIME-CONFIG-RESOURCE-VACUUM-COST

l  Automatic Vacuuming : https://www.postgresql.org/docs/current/runtime-config-autovacuum.html

l  Implement an Early Warning System for Transaction ID Wraparound in Amazon RDS for PostgreSQL : https://aws.amazon.com/ko/blogs/database/implement-an-early-warning-system-for-transaction-id-wraparound-in-amazon-rds-for-postgresql/

l  A Case Study of Tuning Autovacuum in Amazon RDS for PostgreSQL : https://aws.amazon.com/ko/blogs/database/a-case-study-of-tuning-autovacuum-in-amazon-rds-for-postgresql/

l  Common DBA tasks for Amazon RDS for PostgreSQL : https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.html#Appendix.PostgreSQL.CommonDBATasks.Autovacuum.WorkMemory

 

 

 

 

2022-10-26 / Sungwook Kang / http://sungwookkang.com

 

 

AWS, Aurora, PostgreSQL, Autovacuunm, Vacuum

[AWS Aurora] Aurora Parallel Query 활성화 방법 특징

 

l  Version : AWS Aurora

 

Amazon Aurora MySQL 병렬 쿼리는 데이터 집약적인 쿼리 처리에 수반되는 I/O 컴퓨팅의 일부를 병렬화 하는 최적화 작업이다. 병렬화되는 작업은 스토리지로부터 검색, 추출, 어떤 행이 WHERE JOIN절의 조건과 일치하는지 판단한다. 데이터 집약적인 작업은 Aurora 분산 스토리지 계층의 여러 노드에 위임(푸시다운)되고 병렬 쿼리가 없으면 쿼리가 스캔한 모든 데이터를 Aurora MySQL 클러스터(헤드노드)내의 단일 노드로 가져오고 거기에서 모든 쿼리 처리를 수행한다. 병렬 쿼리 기능을 설정하면 Aurora MySQL 엔진이 힌트 또는 테이블 속성과 같은 SQL 변경 필요 없이 쿼리에 따라 자동으로 병렬화 여부를 판단한다.

 

데이터베이스를 생성할 [Engine Version]에서 [Hide filters] 확장하여 parallel query 기능을 활성화할 있다.

 

기본적으로, 병렬 쿼리를 사용하지 않을 경우 Aurora 쿼리에 대한 처리는 원시 데이터를 Aurora 클러스터 단일 노드(헤드 노드) 전송한다. 그런 다음 Aurora 해당 단일 노드의 단일 스레드에서 해당 쿼리에 대해 추가되는 모든 처리를 수행한다. 병렬 쿼리를 사용할 경우, 이러한 I/O 집약적이고 CPU 집약적인 작업의 대부분이 스토리지 계층의 노드로 위임된다. 행은 이미 필터링되고 값은 이미 추출되어 전송된 상태로, 결과 집합의 간소화된 행만 다시 헤드 노드로 전송된다. 성능 혜택은 네트워크 트래픽의 감소, 헤드 노드에서 CPU 사용량의 감소, 스토리지 노드 전체에서 I/O 병렬화로부터 비롯된다. 병렬 I/O, 필터링 프로젝션의 양은 쿼리를 실행하는 Aurora 클러스터의 DB 인스턴스 수와 무관하다.

 

 

아래는 위에서 설명한 병렬 쿼리 사용의 장점을 목록으로 정리한 것이다.

l  여러 스토리 노드에 걸친 물리적 읽기 요청을 병렬화 하여 I/O 성능 개선

l  네트워크 트래픽 감소 : Aurora 전체 데이터 페이지를 스토리지 노드로부터 헤드 노드로 전송한 다음 후에 불필요한 행과 열을 필터링 하지 않고 결과 집합에 필요한 값만 포함된 간소화된 튜플을 전송한다.

l  푸시 다운, 필터링 WHERE 절에 대한 프로젝션으로 인한 헤드 노드에 대한 CPU 사용량 감소.

l  버퍼 풀에서의 메모리 압력 감소 : 병렬 쿼리에 의해 처리된 페이지는 버퍼풀에 추가되지 않으므로 데이터 집약적인 스캔 버퍼 풀에서 자주 사용되는 데이터가 제거될 가능성이 감소.

l  기존 데이터에 대한 장기 실행 분석 쿼리 수행이 유용해진 덕분에 추출, 변환, 로드(ETL) 파이프라인에서 데이터 중복의 잠재적 감소.

 

*주의*
Aurora MySQL 병렬 쿼리의 아키텍처는 다른 데이터베이스 시스템에서 이름이 유사한 기능의 아키텍처와 다르다. Aurora MySQL 병렬 쿼리는 SMP(Symmetric Multi Processing) 포함하지 않아, 데이터베이스의 CPU 용량에 의존하지 않는다. 병렬 처리는 쿼리 조정자 역할을 하는 Aurora MySQL 서버와는 독립적인 스토리지 계층에서 일어난다.

 

Aurora MySQL에서 병렬 쿼리를 사용하기 위해서는 가지 사전 조건 제한 사항이 있다. 해당 내용은 버전에 따라 지원되는 내용이 다르고, 향후 버전 업데이트에 따라 변경될 가능성이 크기 때문에 자세한 내용은 아래 링크의 내용을 직접 참고한다.

l  Amazon Parallel Query  : https://docs.aws.amazon.com/ko_kr/AmazonRDS/latest/AuroraUserGuide/aurora-mysql-parallel-query.html

 

Aurora MySQL 3 버전 부터는 해시조인(Hash Join) 기본적으로 설정되어 있다. optimizer_switch 구성 설정의 block_nested_loop 플래그를 사용하여 설정을 비활성화 있다. Aurora MySQL 3버전에서는 Aurora_disable_hash_join 옵션은 사용되지 않는다.

 

Aurora MySQL 1.23 또는 2.09 이상 버전에서는 병렬 쿼리 해시 조인 설정이 기본적으로 해제되어 있다. 부분을 활성화하기 위해서는 클러스터 구성 파라메터 aurora_disable_hash_join=OFF 설정한다.

 

버전 1.23 이전의 Aurora MySQL 5.6 호환 클러스터의 경우 해시 조인은 병렬 쿼리 클러스터에서 항상 사용할 있다. 경우 해시 조인 기능에 대해 어떤 작업도 수행할 필요가 없다. 이러한 클러스터를 버전 1 또는 버전 2 상위 릴리스로 업그레이드하는 경우 해시 조인도 설정해야 한다.

 

병렬 쿼리를 사용하려면 테이블 속성이 ROW_FORMAT=Compact 또는 ROW_FORMAT=Dynammic 설정을 사용해야하기 때문에 INNODB_FILE_FORMAT 구성 옵션에 대한 변경 사항이 있는지 확인해야한다. 옵션을 변경할 때에는 항상 변경 전후에 대한 성능 문제가 발생할 있으므로 반드시 워크로드 테스트를 진행할 있도록 한다.

 

앞에서도 언급하였지만 병렬 쿼리를 이용하기 위해 어떤 특별한 조치를 수행할 필요는 없다. 필수적 요구사항을 충족한 후에는 쿼리 옵티마이저가 특정 쿼리에 대하여 병렬 쿼리를 사용할지 여부를 자동으로 결정하기 때문이다. 쿼리가 실행될 병렬 쿼리로 실행되었는지 유무는 EXPLAIN 명령을 실행하여 실행계획을 통해 확인할 있다.

아래 예시는 해시 조인이 설정되어 있지만 병렬 쿼리가 해제되어 있어 병렬 쿼리가 아닌 해시 조인으로 실행계획이 표시되었다.

 

병렬 쿼리가 설정된 후에는 해시 조인 실행 parallel query 라고 표시된 것을 확인할 있다.

 

Aurora MySQL 클러스터가 병렬 쿼리를 실행할 버퍼풀을 사용하지 않기 때문에 VolumeReadIOPS 값이 증가할 있다. 따라서 쿼리는 빠르기 실행되지만 이렇게 최적화된 프로세싱은 읽기 작업 관련 비용을 증가시킬 있다. 병렬 쿼리 모니터링에 대한 카운터는 아래 링크에서 병렬 쿼리 모니터링섹션을 참고할 있도록 한다. 카운터는 DB 인스턴스 수준에서 추적된다. 서로 다른 엔드포인트로 연결된 경우 DB 인스턴스가 자체의 고유한 병렬 쿼리 집합을 실행하기 때문에 사로 다른 지표가 표시될 수도 있다. 또한 리더 엔드포인트가 세션마다 서로 다른 DB 인스턴스에 연결된 경우에도 서로 다른 지표가 표시될 수도 있다.

l  Amazon Parallel Query  : https://docs.aws.amazon.com/ko_kr/AmazonRDS/latest/AuroraUserGuide/aurora-mysql-parallel-query.html

 

병렬 쿼리는 InnoDB 테이블에만 적용된다. Aurora MySQL에서는 임시 테이블 사용시, 임시 저장소로 MyISAM 사용하기 때문에 임시 테이블을 포함하는 내부 쿼리 단계에서는 병렬쿼리를 사용하지 않는다. 그리고 실행 계획으로는 Using temporary라고 표시된다.

(MySQL 8.0 부터는 임시 테이블이 디스크에 저장될 InnoDB 스토리지를 사용하도록 개선되어 있다.)

 

 

[참고자료]

l  Amazon Parallel Query  : https://docs.aws.amazon.com/ko_kr/AmazonRDS/latest/AuroraUserGuide/aurora-mysql-parallel-query.html

l  https://aws.amazon.com/blogs/aws/new-parallel-query-for-amazon-aurora/

 

 

2022-07-25 / Sungwook Kang / http://sungwookkang.com

 

 

AWS, Aurora, Aurora Parallel Query, 오로라 병렬처리, 병렬 쿼리, Aurora Optimize, 오로라 최적화

+ Recent posts