본문 바로가기

MySQL, MariaDB

MariaDB - Architecture 이해

MariaDB 아키텍처 이해

1. 스토리지 엔진 
2. 데이터베이스 
| +- 2-1. SYSTEM 데이터베이스 
| +- 2-2. DEFAULT 데이터베이스 
3. binary log 
4. plugin 
5. thread pool 
6. 구성 
| +- 6-1. 동적 및 정적 변수 
| +- 6-2. 범위 
| +- 6-3. syntax 
| +- 6-4. 설정파일들 
| +- 6-5. startup관련 파라메터로 시스템 변수 세팅 
| +- 6-6. 디버깅 설정 
7. 상태 변수 


MariaDB 아키텍처는 SQL Server와 같은 기존 DBMS 아키텍처와 부분적으로 다릅니다.

그럼 어떻게 다른지 알아볼까요? 우린 MariaDB DBA가 알아야 할 주요 구성 요소를 살펴볼 것입니다.
MariaDB 철학과 특정 디자인 선택을 이해하는 데 도움이 될 수 있기 때문에 역사도 논할 것입니다.

모든 기술분야가 그렇듯이 아키텍쳐의 이해는 필요합니다.
그렇기에 이번에는 가장 중요한 구성 요소인 아키텍쳐에 대한 학습을 하도록 하겠습니다.


MariaDB Architecture

* Storage Engine
MariaDB는 2008년에 MySQL 소스로부터 탄생하였습니다. 따라서 MariaDB의 역사는 MySQL로부터 시작됩니다.
연도로 보자면 MySQL은 90년대 초에 세상에 모습을 드러냈죠.

초창기에는 기존 경쟁 벤더사들과 비교했을 때 MySQL은 가볍고 설치가 간단하고 배우기 쉬웠습니다.
기능이 매우 제한적이지만 특정 공통 작업에서는 빠르기도 했고 오픈소스였기 때문에 간단한 웹 사이트들에 많이들 사용되었었죠.

웹은 빠르게 발전했으며 MySQL도 마찬가지였습니다.
당시 지원되지 않는 기능들은 커뮤니티에 필요했었고, 오픈소스라는 점이 이 점에서 많은 도움이 되었습니다.

MySQL은 아마도 pluggable storage engine architecture를 지원하는 최초의 데이터베이스 시스템일 것입니다.
이는 기본적으로 MySQL이 테이블 생성, 테이블 읽기, 적절한 인덱스 및 캐시 구축에 대해 모르게 될 수 있다는 의미가 됩니다.
MySQL은 이 모든 작업들을 스토리지 엔진이라는 특수한 플러그인 유형으로 위임했습니다.

타사에서 개발한 첫번째 플러그인 중 하나는 InnoDB였습니다.
InnoDB에는 두가지 주요 기능인 트랜잭션 및 외래키 기능이 있죠.

MariaDB가 스토리지 엔진에 row를 쓰거나 읽기를 요청하면 스토리지 엔진은 이론적으로 모든 작업을 수행할 수 있습니다.
이로 인해 BLACKHOLE(Linux를 예로들자면 /dev/null 파일처럼 작동하거나 데이터를 수용하지만 저장하지 않는, 항상 빈 결과를 반환하는 스토리지 엔진)이나 CONNECT(여러 다른 형식으로 작성된 파일을 읽고 쓸 수 있음, 원격 DBMS 또는 기타 특수 데이터 소스로 연결할 수 있는)와 같은 매우 흥미로운 스토리지 엔진들이 제작되었습니다.

오늘날 InnoDB는 기본 MariaDB 스토리지 엔진이며 대부분의 사용 사례에 가장 적합한 선택입니다.
물론, 특정요구사항이 있을 경우에는 다른 스토리지 엔진을 사용하는 것이 바람직합니다.

테이블을 생성할 때 스토리지 엔진을 지정하거나 기본 엔진을 사용합니다.
기존 테이블을 다른 스토리지 엔진으로 변환할 수도 있습니다.
MariaDB가 실행되는 동안에 다른 스토리지 엔진을 설치할 수도 있습니다.

동일한 트랜잭션에서 (일부 엔진이 트랜잭션이 아닌 경우에도) 다른 스토리지 엔진이 있는 테이블을 완벽하게 사용할 수 있습니다.
동일한 쿼리에서 다른 엔진을 사용할 수도 있습니다. (예: JOIN 및 하위쿼리)

default_storage_engine 변수를 변경하여 기본 스토리지 엔진을 변경할 수 있습니다.
default_tmp_storage_engine을 설정하여 임시테이블에 다른 기본값을 지정할 수 있습니다.
MariaDB는 내부적으로 생성된 임시테이블에 Aria를 사용하여 쿼리의 중간결과를 저장합니다.


데이터베이스

MariaDB는 스키마 개념을 지원하지 않습니다. 
MariaDB SQL에서 스키마와 스키마는 데이터베이스와 데이터베이스의 동의어입니다.
사용자가 MariaDB에 연결하면 특정 데이터베이스에 연결되지 않습니다. 대신 권한이 있는 모든 테이블에 액세스할 수 있습니다.

그러나, 아래와 같이 기본 데이터베이스의 개념이 있습니다.

데이터베이스는 테이블 및 뷰와 같은 데이터베이스 개체의 컨테이너입니다. 데이터베이스는 다음 용도로 사용됩니다.

- 데이터베이스는 네임 스페이스입니다. 
- 데이터베이스는 객체를 분리하는 논리적 컨테이너입니다. 
- 데이터베이스에는 기본 문자세트와 데이터 정렬이 있으며 테이블에 의해 상속됩니다. 
- 전체 데이터베이스에 권한을 할당하여 권한 유지 관리를 간소화할 수 있습니다. 
- 실제 데이터 파일은 자신이 속한 데이터베이스와 이름이 같은 디렉토리에 저장됩니다. 


시스템 데이터베이스

MariaDB에는 다음과 같은 시스템 데이터베이스가 있습니다.

- mysql : 내부용이며 직접 읽거나 쓰면 안됩니다. 
- information_schema : SQL Server의 performance_schema와 비슷하지만 데이터베이스입니다. 
해당 테이블에는 다른 모든 데이터베이스에 대한 정보가 있습니다. 
- performance_schema : MariaDB 런타임에 대한 정보를 포함합니다. 기본적으로 비활성화되어 있습니다. 
이를 활성화하려면 performance_schema 시스템 변수를 1로 설정하고 MariaDB를 재시작해야 합니다. 


기본 데이터베이스

사용자가 MariaDB에 연결하면 선택적으로 기본 데이터베이스를 지정할 수 있습니다.

기본 데이터베이스를 지정하면 데이터베이스의 이름을 지정하지 않고 테이블을 언급할 수 있습니다.
기본 데이터베이스를 지정하지 않으면 테이블 이름을 작성할 때 데이터베이스 명시를 해야만 합니다.

예를 들어 다음 두가지 케이스는 동일합니다.

SELECT * FROM my_database.my_table; 

-- 다음과 같습니다. 
USE my_database; 
SELECT * FROM my_table ; 


기본 데이터베이스가 지정된 경우에도 완전한 이름을 지정하여 다른 데이터베이스의 테이블에 액세스할 수 있습니다.

-- 이 쿼리는 my_database.my_table을 your_database.your_table에 조인합니다. 
USE my_database; 
SELECT m.* 
  FROM my_table m 
  JOIN your_database.your_table y 
    ON m.xyz = y.xyz; 


MariaDB에는 현재 데이터베이스를 확인할 수 있는 커맨드가 있습니다.

SELECT DATABASE(); 


Stored procedure 및 트리거는 세션 또는 호출형 procedure에서 기본 데이터베이스를 상속하지 않습니다.
이와 관련하여 기본 데이터베이스를 사용하면 프로시저가 포함된 데이터베이스입니다.


The Binary Log

binary log 예시

다른 스토리지 엔진을 사용하여 다른 테이블을 구축할 수 있습니다. 
모든 엔진이 트랜잭션이 가능한 것은 아니며, 엔진이 서로 다르면 다른 방식으로 트랜잭션 로그를 구현한다는 점을 유의해야 합니다.
이러한 이유로 MariaDB는 동등한 SQL Server 트랜잭션 복제를 사용하여 마스터에서 슬레이브로 데이터를 복제할 수 없습니다.

대신, 데이터에 적용되는 변경사항을 기록하는 글로벌 메커니즘이 필요합니다.
이 메커니즘은 binary log이며 종종 binlog로 축약해서 표현하기도 합니다.

binary log는 두가지 형식으로 쓸 수 있습니다.

- STATEMENT 방식은 데이터를 수정하는 SQL문을 기록합니다. 
- ROW 방식은 수정된 행(일반적으로 기본 키임)과 추가되거나 수정된 새 값에 대한 참조를 binary format으로 기록합니다. 


대부분의 경우 슬레이브가 SQL문을 재실행해야 하고 특정 명령문이 슬레이브에서 다른 결과를 만들 수 있기 때문에 STATEMENT방식은 느려집니다. (ORDER BY 없이 사용자가 LIMIT하는 쿼리 또는 CURRENT_TIMESTAMP() 함수에 대한 생각)
그러나 예외가 있으며 어쨋든 DDL문은 항상 binary log가 넘치지 않도록 metadata_lock_info STATEMENT로 기록됩니다.
따라서 binary log에는 ROW 및 STATEMENT 항목이 모두 포함될 수 있습니다.
슬레이브에서 다른 결과를 생성할 수 있는 경우를 제외하고 binlog_format= MIXED를 설정하여 STATEMENT로 변경사항을 기록할 수도 있습니다.

binary log format에 대해 알아볼까요?

binary log가 사용되는 경우

- 마스터에서 활성화된 경우에 복제할 때 
- 해당 슬레이브에서 활성화된 경우 슬레이브를 마스터로 승격할 때 
- 증분 백업할 때 
- 과거 특정 시점의 데이터 확인할 때 ( 플래시백) 
- 문제를 야기한 데이터 변경( human error, 응용 프로그램 버그, SQL Injection)을 제외하고 백업을 복원하고 binary log를 다시 적용합니다. 
- binary log는 Apache Kafka와 같은 기술로 스트리밍하여 CDC(Data Changes)를 캡쳐하는데 사용가능합니다. 

서버에서 이러한 기능을 사용하지 않으려는 경우에는, 성능을 약간 향상시키기 위해 binary log를 비활성화할 수도 있습니다.

binary log는 MariaDB와 함께 제공되는 mysqlbinlog 유틸리티를 사용하여 검사할 수 있습니다.
참고로, binary log를 활성화/비활성화하려면 MariaDB 재기동이 필요합니다.


Plugins

 

mariadb plugins


스토리지 엔진은 특별한 유형의 plugin입니다.
각각의 스토리지 엔진은 다른 부분도 존재하구요.
예를 들어 plugins는 인증방법, 새로운 기능, SQL 구문, 함수, 정보테이블 등을 추가할 수 있습니다.

plugins는 일부 서버변수와 일부 상태변수를 추가할 수 있습니다.
서버변수를 사용하여 플러그인을 구성하고 상태변수를 사용하여 활동 및 상태를 모니터할 수 있습니다.
이러한 변수는 일반적으로 플러그인 이름을 접두사로 사용합니다.
예를 들어 InnoDB에는 버퍼 풀의 크기를 구성하기 위해 innodb_buffer_pool_size라는 서버 변수와 버퍼 풀에서 읽은 메모리 페이지 수를 나타내는 Innodb_pages_read라는 상태변수가 있습니다.

많은 플러그인이 default로 설치되거나 사용 가능하지만 기본적으로 설치되지 않는 경우도 존재합니다.
그럴 경우에는 plugin을 설치하거나 SQL문 등으로 실시간으로 제거할 수도 있습니다. - INSTALL PLUGIN, UNINSTALL PLUGIN;
3rd party 플러그인은 간단히 plugin_dir에 복사해서 설치에 사용할 수 있습니다.

plugins마다 성숙도 수준이 다를 수 있습니다. plugin_maturity 시스템 변수를 설정하여 제품으로 쓸 준비가 안된 plugins의 설치를 막을 수도 있습니다.
MariaDB와 함께 배포되는 plugins의 경우 성숙도 수준은 reporting, bug fixed에 따라 MariaDB팀에 의해서 결정됩니다.

일부plugins는 다른 회사에서 개발했습니다. 일부 타사 plugins조차도 mariadb.org에서 제공되는 MariaDB 공식 배포판에 포함되어 있습니다.
MariaDB와 함께 배포된 모든 Plugins은 MariaDB회사, MariaDB Foundation에서 관리합니다.

MariaDB에서는 모든 인증 방법(기본 방법 포함)이 인증 plugins에 의해 제공됩니다. 사용자는 특정 인증 plugins를 사용해야 구현 가능합니다.
이것은 우리에게 큰 유연성과 통제력을 제공합니다.

매우 유용한 다른 플러그인으로는 리소스 및 테이블 사용량에 대한 통계가 포함된 userstat 및 메타데이터 lock에 대한 정보를 제공하는 METADATA_LOCK_INFO가 있습니다.


스레드 풀

https://www.slideshare.net/ssuser74309b/04-20140721-other-features 참조


MariaDB는 스레드 풀을 지원합니다. UNIX와 WINDOWS에서 각각 다르게 작동하구요.
Windows에서는 기본적으로 사용되며 MSSQL Server와 매우 유사하게 구현됩니다. Windows 고유의 CreateThreadpool API를 사용합니다.

스레드 풀을 사용하지 않으면 MariaDB는 기존 방식으로 연결 처리를 합니다.
각 클라이언트 연결에 dedicated thread를 사용하는 것으로 구성됩니다. 새로운 스레드를 만들면 CPU Time 측면에서 비용이 발생됩니다.
이 비용을 줄이기 위해 클라이언트 연결이 끊어진 후 쓰레드는 thread Cache에서 특정시간 동안 보존될 수 있습니다.

어떤 connection method를 사용하든 MariaDB에는 최대 동시 연결수가 있으며 실시간으로 변경할 수 있습니다.
limit에 도달하면 더 많은 클라이언트가 connection을 시도하면 오류가 발생합니다. 이렇게 하면 MariaDB가 모든 서버 리소스를 사용하지 못하고 중지되거나 중단되지 않습니다.

 



환경설정

MariaDB에는 많은 server system 변수들이 있고, 세팅할 수 있습니다. 이들은 다음과 같이 분류할 수 있습니다.

- Dynamic 또는 static 
- Global, session 또는 both 

server system 변수를 사용자 정의 변수(ex. 프로시저의 변수)와 혼동해서는 안됩니다. 사용자 정의 변수는 MariaDB 구성에 사용되지 않습니다.

DYNAMIC 변수와 STATIC 변수

Dynamic 변수는 실시간으로 SET SQL문을 사용하여 변경할 수 있습니다.
Static 변수는 시작시 결정되는 값들이며 재시작하지 않으면 변경할 수 없습니다.


SCOPE 

Global System 변수는 MariaDB의 일반적인 동작에 영향을 주는 변수입니다.
예를 들어 innodb_buffer_pool_size는 InnoDB 버퍼 풀의 크기를 결정합니다.
InnoDB 버퍼 풀은 어떤 사용자가 이를 사용했는지에 관계없이 읽기/쓰기 작업에 사용됩니다.

session 시스템 변수는 현재 connection의 MariaDB 동작에 영향을 주는 변수입니다.
변경하면 다른 연결된 사용자 또는 현재 사용자의 향후 연결에는 영향을 미치지 않습니다.

global 및 session scope 모두에 변수를 사용할 수 있습니다.
이 경우 세션 값은 현재 connection에 영향을 줍니다. 사용자가 연결하면 현재 global 값이 session scope에 복사됩니다.
이후에 global 값을 변경해도 기존 연결은 변경되지 않습니다.

global 변수와 일부 session 변수는 SUPER 권한이 있는 사용자(일반적으로 ROOT)만 수정할 수 있습니다.

SYNTAX
system 변수의 값을 보려면 아래를 참고합니다.

- global 변수 : 
SELECT @@global.변수이름;
ex) SELECT @@GLOBAL.innodb_buffer_pool_size;

- 세션 변수 : 
SELECT @@session.변수이름;
ex) SELECT @@SESSION.optimizer_switch;

여러 변수를 얻는 데 주로 유용한 긴 구문은 LIKE연산자 가 사용하는 동일한 패턴 구문을 사용합니다 .

-- 이름이 'innodb'로 시작하는 global 변수 :
SHOW GLOBAL VARIABLES LIKE 'innodb%';

-- 이름이 'innodb'로 시작하는 session 변수 : 
SHOW SESSION VARIABLES LIKE 'innodb%';

-- 간단하게 이렇게 사용하기도 합니다.
SELECT @@환경변수이름;

dynamic 변수의 global 또는 session 값을 변경하려면 다음을 수행합니다.

 

-- global 변수 적용예시
SET GLOBAL max_error_count=256;

-- session 변수 적용예시
SET max_error_count=128;

 

이런 식으로 global 변수를 수정하면 mariadb를 재시작할 때 값이 손실됩니다. 

이러한 이유 때문에 환경설정 파일의 값도 변경해서 관리하는 것을 가이드합니다.

 


환경설정 파일

MariaDB는 여러 환경설정 파일을 사용할 수 있습니다. 환경설정 파일은 사용자 디렉토리를 포함하여 여러 위치에서 검색될 수 있으며 존재한다면 모두 읽고 사용됩니다. 

위치는 운영 체제에 따라 다릅니다.

Linux에서는 기본적으로 환경설정 파일이 my.cnf입니다. Windows에서는 기본적으로 환경설정 파일을 my.ini 또는 my.cnf로 호출 할 수 있습니다만 my.ini가 더 일반적입니다.

변수가 다른 파일에서 여러 번 언급되면 마지막에 읽은 항목이 다른 항목을 덮어 씁니다. 마찬가지로 변수가 단일 파일에서 여러 번 언급되면 마지막으로 읽은 항목이 다른 파일을 덮어 씁니다.

각 환경설정 파일의 내용은 옵션 그룹으로 구성됩니다. MariaDB Server와 Client Program은 다른 그룹을 읽습니다. 

읽기 그룹도 MariaDB 버전에 따라 다릅니다.

가장 일반적으로 [server] 또는 [mysqld]그룹은 모든 서버 구성을 포함하는 데 사용됩니다. 

[client-server]그룹은 변수를 여러 번 반복하지 않도록 하기 위해, 서버와 클라이언트에서 공유하는 옵션을 사용할 수 있습니다. (사용할 포트처럼)

Startup 파라메터들과 관련된 시스템 변수 설정

시스템 변수는 값을 구성 파일에 쓰지 않고 서버 시작시 설정할 수 있습니다. 값을 변경하거나 MariaDB를 다시 시작할 때까지 값을 한 번 설정하려는 경우에 유용합니다. 이러한 방식의 설정은 환경설정 파일에 세팅한 값보다 우선합니다.

일반적인 규칙은 모든 전역 변수의 인수로 전달 될 수 있다는 것인데, 

mysqld로 변수이름 앞에 --를 붙이고 변수이름 자체에 있는 _는 -로 대체하면 사용이 가능합니다.

 

예를 들어, startup시에 bind_address 변수를 사용하려면 다음을 수행하십시오.

mysqld --bind-address=127.0.0.1

 

환경설정 디버깅

변수를 잘못 입력하면 MariaDB가 시작되지 않을 수 있습니다. 사용 중인 MariaDB 버전에 존재하지 않는 변수를 설정할 수 없습니다. 만약 잘못된 변수를 지정할 경우 오류가 error log에 기록 됩니다.

command line으로 변수를 전달할 수 있을 뿐 아니라 여러 구성 파일과 구성 그룹이 있으면 유연성을 많이 가져갈 수 있지만 때로는 혼란스러울 수 있습니다. 

 

어떤 값들을 사용할지 모르겠다면 다음을 실행하면 도움이 됩니다.

mysqld --print-defaults

상태 변수

MariaDB 상태 변수 및 일부 시스템 테이블을 사용하면 외부 도구로 서버를 모니터링하고 시간이 지남에 따라 변경되는 방식에 대한 그래프를 작성할 수 있습니다.

뿐만 아니라 사용자가 서버 내부에서 발생한 상황을 검사 할 수 있습니다. 사용자가 상태 변수 를 수정할 수 없습니다. 

 

상태변수 값은 MariaDB 작동 방식을 나타내며 범위는 다음과 같습니다.

  • Global 은 값이 MariaDB 활동에 관한 것임을 의미합니다.
  • Session- 값은 현재 세션에서 발생하는 활동을 측정합니다.

위의 두 범위에 많은 상태 변수가 있구요. 예를 들어 global 수준의 Cpu_time 은 MariaDB 프로세스에서 CPU를 사용한 시간 (모든 사용자 세션 및 모든 백그라운드 스레드 포함)을 나타냅니다. 세션 수준의 Cpu time은 현재 세션에서 CPU를 사용한 시간을 나타냅니다.

플러그인에 의해 생성 된 상태 변수는 일반적으로 플러그인 이름을 접두사로 사용합니다. (ex, innodb_buffer_pool_size)

 

SHOW STATUS문은 특정 패턴과 일치하는 상태 변수의 값을 출력합니다.

-- Show all InnoDB global status variables
SHOW GLOBAL STATUS LIKE 'innodb%';
-- Show all InnoDB session status variables
SHOW SESSION STATUS LIKE 'innodb%';
SHOW STATUS LIKE 'innodb%';
-- Show global variables that contain the "size" substring:
SHOW GLOBAL STATUS LIKE '%size%';


일부 상태 변수 값은 FLUSH STATUS를 실행해서 reset할 수 있습니다.

아래와 같이 사용하면 가능합니다. :

DELIMITER ||
BEGIN NOT ATOMIC
SET @i = 0;
WHILE @i < 60 DO
    SHOW GLOBAL STATUS LIKE 'Com_select';
    FLUSH STATUS;
    DO SLEEP(1);
    SET @i = @i + 1;
END WHILE;
END ||