MySQL 설정 파일과 동적 변수: my.cnf, SET PERSIST, parameter group의 운영 기준
MySQL 설정 파일, 동적 시스템 변수, SET PERSIST, Aurora parameter group을 운영 관점에서 비교하고 안전한 변경 절차를 정리한다.
1. 왜 설정 관리가 운영 안정성의 핵심인가
MySQL 운영에서 설정 변경은 단순히 my.cnf 한 줄을 고치는 작업이 아니다. 하나의 시스템 변수는 메모리 사용량, redo log 기록 방식, 쿼리 실행 계획, 연결 수용량, 복제 지연, 장애 복구 시간까지 바꿀 수 있다. 특히 운영 환경에서는 “지금 적용되는가”, “재시작 후에도 유지되는가”, “인스턴스 단위인가 클러스터 단위인가”, “롤백이 가능한가”를 명확히 구분해야 한다.
MySQL 설정은 크게 세 층으로 이해하는 것이 좋다.
- 정적 설정 파일 계층:
my.cnf,mysqld.cnf처럼 프로세스 시작 시 읽히는 파일 기반 설정이다. - 런타임 시스템 변수 계층:
SET GLOBAL,SET SESSION으로 동작 중인 서버에 적용되는 변수다. - 영속 런타임 설정 계층: MySQL 8.0의
SET PERSIST가 기록하는mysqld-auto.cnf, 또는 Amazon Aurora MySQL의 parameter group처럼 재시작 이후에도 유지되는 관리 계층이다.
이 세 계층이 섞이면 운영 사고가 발생하기 쉽다. 예를 들어 장애 대응 중 SET GLOBAL max_connections = 2000을 적용해 연결 고갈은 해소했지만, 재시작 후 값이 원래대로 돌아가 다시 장애가 반복될 수 있다. 반대로 my.cnf에만 값을 수정하고 재시작하지 않아 실제 운영 서버에는 아무 변화가 없는데, 변경이 끝났다고 오해할 수도 있다. Aurora에서는 OS 파일을 직접 수정하는 방식이 아니라 parameter group을 통해 설정하므로, 일반 MySQL 운영 절차를 그대로 적용하면 변경 반영 범위와 재부팅 필요 여부를 잘못 판단할 수 있다.
이 글은 MySQL 설정의 내부 적용 경로를 먼저 정리한 뒤, Community MySQL과 Aurora MySQL에서 안전하게 설정을 변경하고 검증하는 기준을 설명한다.
2. MySQL 시스템 변수의 기본 구조
MySQL 서버는 시작 시 설정 파일, 명령행 옵션, 컴파일 기본값, persisted 설정을 조합해 시스템 변수 값을 만든다. 시스템 변수는 크게 다음 기준으로 분류한다.
| 구분 | 의미 | 예시 | 운영상 의미 |
|---|---|---|---|
| Global 변수 | 서버 전체에 적용되는 값 | max_connections, innodb_buffer_pool_size |
신규 세션 또는 서버 동작 전체에 영향 |
| Session 변수 | 개별 연결 세션에 적용되는 값 | sql_mode, transaction_isolation |
애플리케이션 연결별 동작 차이 가능 |
| Dynamic 변수 | 서버 재시작 없이 변경 가능한 값 | max_connections, long_query_time |
즉시 변경 가능하지만 영속성 별도 확인 필요 |
| Static 변수 | 시작 시에만 적용 가능한 값 | 일부 InnoDB/파일 경로 관련 변수 | 변경 후 재시작 필요 |
| Persisted 변수 | SET PERSIST로 파일에 저장된 값 |
max_connections 등 지원 변수 |
재시작 후 유지되지만 설정 파일과 충돌 가능 |
동적 변수라고 해서 항상 안전하게 바꿀 수 있는 것은 아니다. innodb_buffer_pool_size는 MySQL 5.7 이후 동적 변경이 가능하지만, 큰 폭으로 변경하면 메모리 재배치와 내부 chunk 조정이 발생한다. max_connections는 즉시 증가시킬 수 있지만 각 연결의 thread stack, per-session buffer, 임시 테이블 사용량까지 고려하지 않으면 메모리 압박을 키울 수 있다. optimizer_switch나 sql_mode처럼 쿼리 동작 자체를 바꾸는 변수는 값 변경 후 애플리케이션 호환성 검증이 필요하다.
시스템 변수 확인의 기본은 SHOW VARIABLES보다 performance_schema와 함께 보는 것이다. SHOW VARIABLES는 빠르게 확인하기 좋지만, 출처와 적용 범위를 세밀하게 분석하기에는 한계가 있다.
-- 현재 전역 시스템 변수 확인
SHOW GLOBAL VARIABLES LIKE 'max_connections';
-- 현재 세션 변수 확인
SHOW SESSION VARIABLES LIKE 'sql_mode';
-- MySQL 8.0에서 persisted 변수 확인
SELECT variable_name, variable_value
FROM performance_schema.persisted_variables
ORDER BY variable_name;
-- 시스템 변수와 설정 출처를 함께 확인할 때 유용한 뷰
SELECT variable_name, variable_source, set_time, set_user, set_host
FROM performance_schema.variables_info
WHERE variable_name IN ('max_connections', 'innodb_buffer_pool_size', 'sql_mode');
실행 결과(MySQL 8.0.46):
+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| max_connections | 30 |
+-----------------+-------+
+---------------+-----------------------------------------------------------------------------------------------------------------------+
| Variable_name | Value |
+---------------+-----------------------------------------------------------------------------------------------------------------------+
| sql_mode | ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION |
+---------------+-----------------------------------------------------------------------------------------------------------------------+
+-------------------------+-----------------+----------+----------+----------+
| variable_name | variable_source | set_time | set_user | set_host |
+-------------------------+-----------------+----------+----------+----------+
| innodb_buffer_pool_size | COMMAND_LINE | NULL | NULL | NULL |
| max_connections | COMMAND_LINE | NULL | NULL | NULL |
| sql_mode | COMPILED | NULL | NULL | NULL |
+-------------------------+-----------------+----------+----------+----------+
performance_schema.variables_info는 MySQL 버전과 설정에 따라 표시되는 컬럼이 다를 수 있으므로, 운영 스크립트에서는 먼저 DESCRIBE performance_schema.variables_info로 컬럼을 확인한 뒤 사용하는 편이 안전하다.
3. 설정 파일: my.cnf와 시작 시 적용 경로
일반 MySQL 서버에서 my.cnf 또는 배포판별 설정 파일은 가장 전통적인 설정 관리 방식이다. Linux 패키지 설치 환경에서는 /etc/my.cnf, /etc/mysql/my.cnf, /etc/mysql/mysql.conf.d/mysqld.cnf 등 여러 위치가 사용될 수 있다. MySQL은 컴파일 옵션과 실행 경로에 따라 여러 설정 파일을 순서대로 읽으며, 뒤에서 읽은 값이 앞의 값을 덮어쓸 수 있다.
운영자는 먼저 실제 서버가 어느 설정 파일을 읽는지 확인해야 한다.
mysqld --verbose --help 2>/dev/null | grep -A1 'Default options'
# systemd 서비스가 어떤 옵션으로 mysqld를 실행하는지 확인
systemctl cat mysql
systemctl cat mysqld
# 실행 중인 mysqld 프로세스의 인자 확인
ps -eo pid,args | grep '[m]ysqld'
설정 파일은 보통 다음과 같은 그룹으로 구성된다.
[mysqld]
max_connections = 500
innodb_buffer_pool_size = 8G
slow_query_log = ON
long_query_time = 1
[client]
default-character-set = utf8mb4
중요한 점은 [mysqld]와 [client]는 적용 대상이 다르다는 것이다. mysql CLI 접속 옵션을 [client]에 적어도 서버 변수는 바뀌지 않는다. 반대로 서버 전용 옵션을 클라이언트 그룹에 넣으면 아무 효과가 없거나 클라이언트 실행 오류를 만들 수 있다.
설정 파일 방식의 장점은 명시성과 재현성이다. 서버가 재시작되어도 값이 유지되고, configuration management 도구나 Git으로 변경 이력을 관리하기 좋다. 단점은 즉시 적용되지 않는 경우가 많고, 변경이 누적되면서 실제 런타임 값과 파일 값이 달라질 수 있다는 점이다.
운영에서는 설정 파일 수정 후 반드시 두 가지를 분리해 검증해야 한다.
- 문법 검증: 오타나 지원하지 않는 옵션 때문에 mysqld가 재시작에 실패하지 않는지 확인한다.
- 런타임 검증: 재시작 또는 reload 이후 실제 변수 값이 기대대로 반영되었는지 확인한다.
# 배포판과 버전에 따라 --validate-config 지원 여부가 다를 수 있다.
mysqld --validate-config --verbose 2>&1 | less
# 재시작 후 실제 값 확인
mysql -e "SHOW GLOBAL VARIABLES LIKE 'innodb_buffer_pool_size';"
mysql -e "SHOW GLOBAL VARIABLES LIKE 'max_connections';"
mysqld --validate-config를 사용할 수 없는 버전에서는 staging 서버에서 같은 설정으로 기동 테스트를 수행하거나, 변경 범위를 작게 나누어 maintenance window에 적용하는 것이 안전하다.
4. SET GLOBAL과 SET SESSION: 즉시 적용되지만 사라질 수 있는 변경
SET GLOBAL은 동작 중인 서버의 전역 변수를 즉시 변경한다. 대표적으로 장애 대응, 임시 완화, 관측 설정 변경에 사용된다.
-- 신규 연결 수용량을 즉시 늘림
SET GLOBAL max_connections = 800;
-- slow query log 기준을 임시로 낮춰 관측 강화
SET GLOBAL long_query_time = 0.5;
SET GLOBAL slow_query_log = ON;
그러나 SET GLOBAL 변경은 일반적으로 서버 재시작 후 사라진다. 또한 모든 변수 변경이 기존 세션에 즉시 적용되는 것은 아니다. 예를 들어 일부 session 변수는 새 연결부터 반영되며, 이미 연결된 애플리케이션 세션은 기존 값을 유지할 수 있다.
-- 전역 sql_mode 변경: 새 세션의 기본값에 영향
SET GLOBAL sql_mode = 'STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';
-- 현재 접속 세션에만 적용
SET SESSION sql_mode = 'STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION';
운영에서 중요한 질문은 “어느 세션이 어떤 값을 사용하고 있는가”다. 애플리케이션 connection pool이 오래 유지되는 환경에서는 전역 변수를 바꾸어도 이미 열린 연결에는 기대한 변화가 나타나지 않을 수 있다. 이 경우 connection pool 재시작, 세션 재연결, 또는 애플리케이션 초기화 SQL 확인이 필요하다.
세션별 변수 차이는 다음처럼 확인할 수 있다.
-- 현재 세션 값
SELECT @@session.sql_mode, @@global.sql_mode;
-- isolation level 확인
SELECT @@session.transaction_isolation, @@global.transaction_isolation;
실행 결과(MySQL 8.0.46):
+-----------------------------------------------------------------------+-----------------------------------------------------------------------+
| @@session.sql_mode | @@global.sql_mode |
+-----------------------------------------------------------------------+-----------------------------------------------------------------------+
| STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION | STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION |
+-----------------------------------------------------------------------+-----------------------------------------------------------------------+
+---------------------------------+--------------------------------+
| @@session.transaction_isolation | @@global.transaction_isolation |
+---------------------------------+--------------------------------+
| REPEATABLE-READ | REPEATABLE-READ |
+---------------------------------+--------------------------------+
SET GLOBAL은 신속하지만 변경 이력을 놓치기 쉽다. 따라서 운영 표준에서는 SET GLOBAL을 “응급 또는 실험적 변경”으로 분류하고, 효과가 확인되면 설정 파일, SET PERSIST, parameter group 등 영속 계층에 반영할지 별도로 결정해야 한다.
5. SET PERSIST와 mysqld-auto.cnf: MySQL 8.0의 영속 런타임 설정
MySQL 8.0은 SET PERSIST를 통해 동적 시스템 변수를 재시작 후에도 유지할 수 있다. 이 명령은 값을 즉시 적용하고, 데이터 디렉터리 아래의 mysqld-auto.cnf에 persisted 설정을 기록한다.
-- 즉시 적용 + 재시작 후 유지
SET PERSIST max_connections = 800;
-- 즉시 적용하지 않고 다음 재시작부터 적용할 때 사용
SET PERSIST_ONLY read_only = ON;
RESET PERSIST read_only;
운영 관점에서 SET PERSIST의 장점은 빠른 변경과 영속성을 함께 제공한다는 점이다. 그러나 이것은 동시에 위험 요소이기도 하다. 변경이 파일 기반 configuration management를 우회해 저장되기 때문이다. 시간이 지나면 my.cnf에는 max_connections = 500이 남아 있는데, mysqld-auto.cnf에는 800이 저장되어 실제 런타임 값은 800이 되는 식의 혼란이 생길 수 있다.
SET PERSIST 사용 시에는 다음 원칙을 권장한다.
- 운영 표준에서 persisted 변수 사용 여부를 명확히 정한다.
- configuration management로
my.cnf를 관리한다면,SET PERSIST는 임시 변경 또는 제한된 변수에만 사용한다. - 적용 후
performance_schema.persisted_variables를 기록하고 변경 티켓에 남긴다. - 롤백 절차로
RESET PERSIST사용 방법을 문서화한다.
-- persisted 변수 목록 확인
SELECT variable_name, variable_value
FROM performance_schema.persisted_variables
ORDER BY variable_name;
-- 특정 persisted 변수 제거
RESET PERSIST max_connections;
-- 모든 persisted 변수 제거: 운영에서는 매우 주의해서 사용
RESET PERSIST;
실행 결과(MySQL 8.0.46):
+-----------------+----------------+
| variable_name | variable_value |
+-----------------+----------------+
| max_connections | 800 |
+-----------------+----------------+
RESET PERSIST는 persisted 파일에 기록된 값을 제거하지만, 현재 런타임 값까지 항상 원래대로 되돌리는 명령으로 이해하면 안 된다. 필요하면 별도로 SET GLOBAL 또는 재시작을 통해 런타임 상태를 정리해야 한다.
또한 mysqld-auto.cnf는 사람이 직접 편집하는 파일이 아니다. JSON 형태로 저장되지만 MySQL 서버가 관리하는 내부 설정 파일로 취급해야 한다. 손상되면 서버 시작 실패의 원인이 될 수 있으므로, 백업이나 재해 복구 절차에서는 해당 파일의 존재와 의미를 알고 있어야 한다.
6. Aurora MySQL parameter group: 파일 대신 관리 계층으로 설정한다
Amazon Aurora MySQL에서는 사용자가 OS의 my.cnf를 직접 수정하지 않는다. 설정은 DB parameter group과 DB cluster parameter group으로 관리된다. 이 차이는 운영 절차에 직접적인 영향을 준다.
Aurora 설정은 크게 다음 두 종류로 나뉜다.
| 계층 | 적용 대상 | 예시 | 운영상 주의점 |
|---|---|---|---|
| DB cluster parameter group | 클러스터 전체에 적용되는 설정 | binlog, character set, 일부 InnoDB/복제 관련 설정 | writer/reader 전체 영향 가능 |
| DB parameter group | 개별 DB instance에 적용되는 설정 | instance 성격의 메모리/연결 관련 설정 | writer와 reader별 차이 발생 가능 |
Aurora에서는 각 파라미터가 dynamic인지 static인지에 따라 적용 방식이 달라진다. dynamic 파라미터는 즉시 반영될 수 있지만, static 파라미터는 재부팅이 필요하다. AWS 콘솔이나 CLI에서는 적용 상태가 pending-reboot로 표시될 수 있다.
# 파라미터 그룹 값 확인 예시
aws rds describe-db-parameters \
--db-parameter-group-name example-mysql-parameter-group \
--query "Parameters[?ParameterName=='max_connections']"
# 클러스터 파라미터 그룹 확인 예시
aws rds describe-db-cluster-parameters \
--db-cluster-parameter-group-name example-aurora-cluster-parameter-group \
--query "Parameters[?ParameterName=='time_zone']"
Aurora 운영에서 자주 발생하는 오해는 다음과 같다.
- writer에 접속해
SET GLOBAL로 바꾼 값을 parameter group 변경으로 착각한다. - reader instance의 DB parameter group이 writer와 달라 성능 특성이 달라진다.
pending-reboot상태를 무시하고 변경이 적용되었다고 보고한다.- failover 후 새 writer가 다른 instance parameter group을 사용하면서 동작이 달라진다.
Aurora에서는 parameter group이 설정의 공식 원천이다. 응급 상황에서 SET GLOBAL을 사용할 수는 있지만, 장기 운영 값은 parameter group에 반영해야 한다. 또한 failover를 고려해 writer 후보가 될 수 있는 reader들의 parameter group 정합성도 확인해야 한다.
-- Aurora에서도 실제 런타임 값은 MySQL 내부에서 확인해야 한다.
SHOW GLOBAL VARIABLES LIKE 'max_connections';
SHOW GLOBAL VARIABLES LIKE 'innodb_flush_log_at_trx_commit';
SHOW GLOBAL VARIABLES LIKE 'time_zone';
실행 결과(MySQL 8.0.46):
+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| max_connections | 800 |
+-----------------+-------+
+--------------------------------+-------+
| Variable_name | Value |
+--------------------------------+-------+
| innodb_flush_log_at_trx_commit | 1 |
+--------------------------------+-------+
+---------------+--------+
| Variable_name | Value |
+---------------+--------+
| time_zone | SYSTEM |
+---------------+--------+
AWS CLI의 설정값과 MySQL 내부 런타임 값이 다르면, 아직 재부팅이 필요한 상태인지, 다른 parameter group이 붙어 있는지, 세션 값과 전역 값을 혼동한 것인지 확인해야 한다.
7. 변경 전 영향 분석: 변수 하나가 바꾸는 실행 경로
설정 변경의 위험은 변수 이름만 보고 판단하기 어렵다. 같은 “성능 개선” 목적이라도 내부 동작 경로가 다르기 때문이다.
7.1 연결 수 관련 변수
max_connections를 늘리면 더 많은 동시 연결을 받을 수 있다. 그러나 MySQL은 연결별로 thread stack, net buffer, sort buffer, join buffer, temporary table memory 등을 사용할 수 있다. 모든 연결이 동시에 최대 버퍼를 쓰지는 않더라도, 장애 상황에서는 연결 폭증과 무거운 쿼리가 함께 발생할 수 있다.
SHOW GLOBAL STATUS LIKE 'Threads_connected';
SHOW GLOBAL STATUS LIKE 'Max_used_connections';
SHOW GLOBAL VARIABLES LIKE 'max_connections';
SELECT
@@global.max_connections AS max_connections,
@@global.thread_stack AS thread_stack,
@@global.sort_buffer_size AS sort_buffer_size,
@@global.join_buffer_size AS join_buffer_size,
@@global.tmp_table_size AS tmp_table_size;
실행 결과(MySQL 8.0.46):
+-------------------+-------+
| Variable_name | Value |
+-------------------+-------+
| Threads_connected | 1 |
+-------------------+-------+
+----------------------+-------+
| Variable_name | Value |
+----------------------+-------+
| Max_used_connections | 1 |
+----------------------+-------+
+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| max_connections | 800 |
+-----------------+-------+
+-----------------+--------------+------------------+------------------+----------------+
| max_connections | thread_stack | sort_buffer_size | join_buffer_size | tmp_table_size |
+-----------------+--------------+------------------+------------------+----------------+
| 800 | 1048576 | 262144 | 262144 | 16777216 |
+-----------------+--------------+------------------+------------------+----------------+
max_connections 증가는 원인 해결이 아니라 완충 장치일 때가 많다. connection leak, 느린 쿼리, lock wait, connection pool 설정 오류를 함께 확인해야 한다.
7.2 InnoDB 메모리 관련 변수
innodb_buffer_pool_size는 InnoDB 성능에 큰 영향을 준다. 버퍼 풀이 너무 작으면 디스크 읽기가 증가하고, 너무 크면 OS page cache, mysqld 외 메모리, 백업/모니터링 에이전트의 여유 메모리를 침범할 수 있다.
SHOW GLOBAL VARIABLES LIKE 'innodb_buffer_pool_size';
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_reads';
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_read_requests';
SELECT
ROUND(
1 - (
SUM(CASE WHEN variable_name = 'Innodb_buffer_pool_reads' THEN variable_value ELSE 0 END) /
NULLIF(SUM(CASE WHEN variable_name = 'Innodb_buffer_pool_read_requests' THEN variable_value ELSE 0 END), 0)
), 6
) AS approximate_buffer_pool_hit_ratio
FROM performance_schema.global_status
WHERE variable_name IN ('Innodb_buffer_pool_reads', 'Innodb_buffer_pool_read_requests');
실행 결과(MySQL 8.0.46):
+-------------------------+----------+
| Variable_name | Value |
+-------------------------+----------+
| innodb_buffer_pool_size | 67108864 |
+-------------------------+----------+
+--------------------------+-------+
| Variable_name | Value |
+--------------------------+-------+
| Innodb_buffer_pool_reads | 998 |
+--------------------------+-------+
+----------------------------------+-------+
| Variable_name | Value |
+----------------------------------+-------+
| Innodb_buffer_pool_read_requests | 15542 |
+----------------------------------+-------+
+-----------------------------------+
| approximate_buffer_pool_hit_ratio |
+-----------------------------------+
| 0.935787 |
+-----------------------------------+
히트율만으로 크기를 결정해서는 안 된다. working set, checkpoint 압력, redo log 크기, 쿼리 패턴, OS 메모리 여유를 함께 봐야 한다. Aurora MySQL은 스토리지 계층이 일반 EBS 기반 MySQL과 다르므로, 같은 변수라도 I/O 지연과 캐시 계층의 해석이 달라질 수 있다.
7.3 로그와 관측 변수
slow_query_log, long_query_time, log_output 같은 변수는 장애 분석에 유용하지만, 설정에 따라 디스크 사용량과 로그 처리 비용이 증가한다.
SET GLOBAL slow_query_log = ON;
SET GLOBAL long_query_time = 1;
SET GLOBAL log_queries_not_using_indexes = OFF;
SHOW GLOBAL VARIABLES WHERE Variable_name IN (
'slow_query_log', 'long_query_time', 'log_output', 'log_queries_not_using_indexes'
);
실행 결과(MySQL 8.0.46):
+-------------------------------+----------+
| Variable_name | Value |
+-------------------------------+----------+
| log_output | FILE |
| log_queries_not_using_indexes | OFF |
| long_query_time | 1.000000 |
| slow_query_log | ON |
+-------------------------------+----------+
운영 중 관측 강도를 높일 때는 로그 보관 위치, rotation 정책, 모니터링 수집량을 함께 확인해야 한다. Aurora에서는 slow query log를 CloudWatch Logs로 내보내는 설정 여부와 비용도 고려해야 한다.
8. 안전한 설정 변경 절차
운영 환경에서 설정 변경은 다음 절차를 표준으로 삼는 것이 좋다.
8.1 변경 전 현재 상태 기록
변경 전에는 실제 런타임 값과 영속 설정을 모두 기록한다.
-- 변경 대상 변수의 현재 값 기록
SHOW GLOBAL VARIABLES WHERE Variable_name IN (
'max_connections',
'innodb_buffer_pool_size',
'long_query_time',
'slow_query_log'
);
-- MySQL 8.0 persisted 설정 기록
SELECT variable_name, variable_value
FROM performance_schema.persisted_variables
WHERE variable_name IN (
'max_connections',
'innodb_buffer_pool_size',
'long_query_time',
'slow_query_log'
);
실행 결과(MySQL 8.0.46):
+-------------------------+----------+
| Variable_name | Value |
+-------------------------+----------+
| innodb_buffer_pool_size | 67108864 |
| long_query_time | 1.000000 |
| max_connections | 800 |
| slow_query_log | ON |
+-------------------------+----------+
# 설정 파일 백업 예시: 실제 운영에서는 변경 관리 절차에 맞춘 경로를 사용한다.
cp /etc/my.cnf /etc/my.cnf.before-change-$(date +%Y%m%d%H%M%S)
8.2 적용 범위 결정
변경 요청을 받으면 먼저 어느 계층에 적용할지 결정한다.
- 일시적 장애 완화인가? →
SET GLOBAL을 고려하되, 종료 조건과 롤백 값을 명시한다. - 재시작 후에도 유지되어야 하는가? →
my.cnf,SET PERSIST, parameter group 중 표준 계층을 선택한다. - Aurora 클러스터 전체에 필요한가? → cluster parameter group 대상인지 확인한다.
- 특정 reader 또는 writer instance만 필요한가? → DB parameter group 정합성을 검토한다.
- 세션별 동작인가? → 애플리케이션 connection string, init SQL, ORM 설정을 함께 확인한다.
8.3 작은 단위로 적용하고 관측한다
메모리, 연결, 로그, optimizer 관련 값은 한 번에 여러 개를 바꾸지 않는 것이 원칙이다. 여러 변수를 동시에 바꾸면 성능 변화의 원인을 분리하기 어렵다.
적용 후에는 최소한 다음 지표를 확인한다.
SHOW GLOBAL STATUS LIKE 'Threads_connected';
SHOW GLOBAL STATUS LIKE 'Threads_running';
SHOW GLOBAL STATUS LIKE 'Max_used_connections';
SHOW GLOBAL STATUS LIKE 'Created_tmp_disk_tables';
SHOW GLOBAL STATUS LIKE 'Innodb_row_lock_waits';
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_reads';
실행 결과(MySQL 8.0.46):
+-------------------+-------+
| Variable_name | Value |
+-------------------+-------+
| Threads_connected | 1 |
+-------------------+-------+
+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| Threads_running | 2 |
+-----------------+-------+
+----------------------+-------+
| Variable_name | Value |
+----------------------+-------+
| Max_used_connections | 1 |
+----------------------+-------+
+-------------------------+-------+
| Variable_name | Value |
+-------------------------+-------+
| Created_tmp_disk_tables | 0 |
+-------------------------+-------+
+-----------------------+-------+
| Variable_name | Value |
+-----------------------+-------+
| Innodb_row_lock_waits | 0 |
+-----------------------+-------+
+--------------------------+-------+
| Variable_name | Value |
+--------------------------+-------+
| Innodb_buffer_pool_reads | 998 |
+--------------------------+-------+
-- 최근 statement 관측: performance_schema가 활성화되어 있어야 한다.
SELECT
digest_text,
count_star,
ROUND(sum_timer_wait / 1000000000000, 2) AS total_seconds,
ROUND(avg_timer_wait / 1000000000000, 4) AS avg_seconds,
sum_rows_examined,
sum_rows_sent
FROM performance_schema.events_statements_summary_by_digest
ORDER BY sum_timer_wait DESC
LIMIT 10;
8.4 롤백 기준을 먼저 정한다
설정 변경은 “문제가 생기면 되돌린다”가 아니라 “어떤 조건이면 몇 분 안에 어떤 값으로 되돌린다”로 운영되어야 한다. 예를 들어 long_query_time을 낮춰 관측을 강화했는데 로그량이 급증하면 원래 값으로 되돌리고, max_connections를 늘린 뒤 메모리 압박이 커지면 connection pool 제한과 함께 재조정해야 한다.
-- 예시 롤백
SET GLOBAL long_query_time = 2;
SET GLOBAL max_connections = 500;
영속 계층까지 변경했다면 롤백도 같은 계층에서 수행해야 한다. SET GLOBAL로만 되돌리면 재시작 후 다시 문제가 재현될 수 있다.
9. 설정 충돌과 드리프트 관리
설정 드리프트란 문서화된 기대값, 설정 파일, persisted 설정, 실제 런타임 값이 서로 달라지는 상태를 말한다. MySQL 운영에서는 다음 네 값을 구분해 관리해야 한다.
- 표준 설정 저장소의 기대값
my.cnf또는 배포된 파일의 값mysqld-auto.cnf또는 parameter group의 값- 현재 서버에서 조회되는
@@global값
드리프트 점검 쿼리와 명령은 환경별로 달라지지만, 최소한 MySQL 내부에서는 다음 정보를 정기적으로 수집할 수 있다.
SELECT variable_name, variable_value
FROM performance_schema.global_variables
WHERE variable_name IN (
'max_connections',
'innodb_buffer_pool_size',
'sql_mode',
'transaction_isolation',
'time_zone',
'slow_query_log',
'long_query_time'
)
ORDER BY variable_name;
SELECT variable_name, variable_value
FROM performance_schema.persisted_variables
ORDER BY variable_name;
실행 결과(MySQL 8.0.46):
+-------------------------+-----------------------------------------------------------------------+
| variable_name | variable_value |
+-------------------------+-----------------------------------------------------------------------+
| innodb_buffer_pool_size | 67108864 |
| long_query_time | 2.000000 |
| max_connections | 500 |
| slow_query_log | ON |
| sql_mode | STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION |
| time_zone | SYSTEM |
| transaction_isolation | REPEATABLE-READ |
+-------------------------+-----------------------------------------------------------------------+
Aurora에서는 CLI 또는 콘솔에서 parameter group 변경 이력과 현재 적용 상태를 함께 확인한다.
aws rds describe-db-instances \
--query "DBInstances[].{DBInstanceIdentifier:DBInstanceIdentifier,DBParameterGroups:DBParameterGroups}"
aws rds describe-db-clusters \
--query "DBClusters[].{DBClusterIdentifier:DBClusterIdentifier,DBClusterParameterGroup:DBClusterParameterGroup}"
설정 드리프트를 줄이려면 운영팀 내에서 “영구 설정의 단일 원천”을 정해야 한다. 일반 MySQL에서는 Git으로 관리되는 설정 파일을 기준으로 삼고, SET PERSIST는 예외적으로 사용하는 방식이 흔하다. Aurora에서는 parameter group이 단일 원천이며, 콘솔에서 임시로 바꾼 값도 변경 관리에 반드시 기록되어야 한다.
10. 장애 사례로 보는 흔한 오해
10.1 재시작 후 max_connections가 원래대로 돌아간 경우
장애 중 SET GLOBAL max_connections = 1500으로 연결 오류가 줄었다. 그러나 야간 패치로 mysqld가 재시작되면서 my.cnf의 max_connections = 500이 다시 적용되었고, 다음 트래픽 피크에서 같은 장애가 반복되었다.
이 사례의 핵심은 SET GLOBAL의 비영속성을 놓친 것이다. 응급 변경은 반드시 사후에 영속 계층 반영 여부를 결정해야 한다.
10.2 Aurora failover 후 성능이 달라진 경우
writer와 reader의 DB parameter group이 다르게 설정되어 있었고, failover 후 reader가 writer가 되면서 일부 메모리 및 로그 설정이 바뀌었다. 애플리케이션은 같은 클러스터 endpoint를 사용했지만 내부 instance 설정이 달라져 성능 특성이 변했다.
Aurora에서는 writer 후보 instance의 parameter group 정합성을 정기적으로 점검해야 한다. 특히 failover를 운영 절차로 사용하는 환경에서는 “현재 writer만 정상”이어서는 충분하지 않다.
10.3 sql_mode 변경 후 일부 INSERT가 실패한 경우
sql_mode에 strict 관련 옵션을 추가하면서 기존 애플리케이션이 암묵적으로 허용하던 잘못된 날짜, 잘린 문자열, 기본값 누락이 오류로 바뀌었다. 데이터 품질 측면에서는 올바른 방향일 수 있지만, 운영 적용은 애플리케이션 검증과 함께 진행되어야 한다.
sql_mode는 단순 성능 변수가 아니라 SQL 의미론을 바꾸는 변수다. 세션별 설정, ORM 초기화 SQL, connection pool 재사용까지 함께 확인해야 한다.
11. 운영 체크리스트
설정 변경 전후에는 다음 항목을 확인한다.
- 현재 런타임 값(
@@global,@@session - 설정 파일,
SET PERSIST - MySQL 8.0 환경에서는
performance_schema.persisted_variables -
pending-reboot
12. 의사결정 기준: 어떤 방식으로 바꿀 것인가
다음 기준으로 설정 변경 방식을 선택할 수 있다.
| 상황 | 권장 방식 | 이유 |
|---|---|---|
| 장애 중 일시적 완화 | SET GLOBAL |
빠르게 적용하고 효과를 확인할 수 있음 |
| 일반 MySQL의 표준 영구 설정 | my.cnf + 재시작 계획 |
Git/배포 도구로 이력 관리가 쉬움 |
| MySQL 8.0에서 제한된 영속 런타임 변경 | SET PERSIST |
즉시 적용과 재시작 후 유지가 가능하지만 드리프트 관리 필요 |
| Aurora MySQL 영구 설정 | parameter group | Aurora의 공식 설정 관리 계층 |
| 애플리케이션별 SQL 동작 조정 | session 변수 또는 connection init SQL | 서비스별 영향 범위를 제한할 수 있음 |
| 의미론 변경 또는 optimizer 영향 변수 | staging 검증 후 단계 적용 | 쿼리 결과 또는 실행 계획 변화 가능 |
중요한 원칙은 변경 방식보다 “검증 가능한 상태”를 만드는 것이다. 어떤 방식으로 바꾸든 운영자가 현재 값, 영속 값, 적용 범위, 롤백 방법을 설명할 수 있어야 한다.
13. 결론
MySQL 설정 관리는 파일 편집, SQL 명령, 클라우드 parameter group이 함께 얽힌 운영 영역이다. my.cnf는 재현성과 명시성이 강하고, SET GLOBAL은 빠르지만 재시작 후 사라질 수 있으며, SET PERSIST는 편리하지만 설정 드리프트를 만들 수 있다. Aurora MySQL에서는 parameter group이 공식 설정 원천이며, dynamic/static 여부와 failover 후보 instance의 정합성까지 고려해야 한다.
운영자는 설정 변경을 단일 명령으로 보지 말고, 적용 계층과 런타임 효과를 분리해 관리해야 한다. 다음 글들에서는 이러한 설정 기준 위에서 InnoDB, 옵티마이저, 트랜잭션, 복제 관련 주요 변수들이 실제 실행 경로와 장애 양상에 어떤 영향을 주는지 더 구체적으로 다룰 수 있다.