DB 엔지니어가 sustaining 성격의 업무들로 모든 리소스를 소비할 수는 없음
단순한 요청 수행을 위해 하루에서 길게는 일주일까지 검토와 커뮤니케이션에 비용 소모
개발자들이 직접 DDL, DML, DCL 등을 안전하게 실행할 수 있게 되어 커뮤니케이션 비용 하락, 개발 속도 향상
작업 중 DBMS 서버의 부하가 높아지면 자동으로 작업을 중단
작업 전 테이블의 용량을 검사해서 기준 이상이면 실행하지 않음
요청 작업 중 메타데이터 락으로 인해 신규 세션이 block 되는 경우 자동 kill (https://leezzangmin.tistory.com/51)
실행 전 롱쿼리가 존재하면 작업이 수행되지 않음
1대의 DBMS 당 global하게 동시에 실행되는 작업은 1개로 제한
작업 가능 시간을 설정하여 그 외 시간에는 작업을 block (서비스 도메인에 따라 부하가 높은 시간으로 설정 가능)
작업 시작, 종료, 실패 시 슬랙으로 알림
운영 중 마주치게 되는 비표준 설정값들로 인한 오버헤드를 사전에 파악하고 줄이기 위함
클러스터 파라미터 그룹 변수(ex.`max_connetions`, `character_set_database` 등) 중 DB팀 표준과 다른 값이 있으면 알림
클러스터 생성 변수(ex.`DeletionProtection`, `BackupRetentionPeriod` 등) 중 DB팀 표준과 다른 값이 있으면 알림
인스턴스 생성 변수(ex. `AutoMinorVersionUpgrade`, 태그존재 여부 등) 중 DB팀 표준과 다른 값이 있으면 알림
스키마 생성 표준(ex. 네이밍 컨벤션, COMMENT 필수 기입, CHARSET 및 COLLATE 등)에 어긋나는 테이블 및 컬럼이 있으면 알림
AWS SDK 를 사용하여 계정의 모든 DBMS 클러스터 목록을 조회
클러스터의 버전, CPU, Memory, Storage, Connection, QPS 등의 상태 조회
스키마, 테이블 목록 및 용량 등 조회
테이블 스키마의 변경 히스토리 조회
사람의 손으로 운영하는 DB라서 이슈 대응 등의 긴급한 상황에서는 수동으로 스키마를 조작하게 됨
이런 히스토리는 추적하기 어려워서 prod와 stage, dev 간의 스키마가 불일치한 상태로 서비스가 지속됨
미리 파악하기 힘든 장애를 방지하기 위해 각 환경의 스키마 차이점을 검사
object_name, 컬럼 및 제약조건 개수, charset, collation, comment, routine_definition, security_type, definer 등
검사한 결과는 슬랙으로 전달되어 히스토리 관리가 가능
모든 요청과 승인/반려/조회 로그는 접근 가능한 테이블에 적재됩니다.
요청 가능한 유저는 사전에 계정 생성 프로세스를 통해 테이블에 적재되며, 인가 받은 유저만 요청을 생성할 수 있습니다. (계정 만료일 존재)
각각의 개별 요청은 Admin X명 이상의 승인/반려 리뷰 프로세스를 거쳐야 하기 때문에 Admin 슬랙 계정이 탈취되어도 안전합니다.
335809051-cfa4b930-92c8-4c9e-bcb7-94ecbcd8f234_.online-video-cutter.com._.1.mp4
DB 표준 목록
-
클러스터 생성 표준값
public class ClusterCreationStandard { public final static Map<String, String> clusterCreationStandard = new HashMap<>(); static { clusterCreationStandard.put("BackupRetentionPeriod", "7"); clusterCreationStandard.put("MultiAZ", "true"); clusterCreationStandard.put("DeletionProtection", "true"); clusterCreationStandard.put("Engine", "aurora-mysql"); clusterCreationStandard.put("EngineVersion", "8.0.mysql_aurora.3.03.1"); clusterCreationStandard.put("Port", "3306"); clusterCreationStandard.put("MasterUsername", "admin"); } }
-
인스턴스 생성 표준값
public class InstanceCreationStandard { public final static Map<String, String> instanceCreationStandard = new HashMap<>(); static { instanceCreationStandard.put("AutoMinorVersionUpgrade", "false"); instanceCreationStandard.put("DeletionProtection", "true"); instanceCreationStandard.put("PerformanceInsightsEnabled", "true"); instanceCreationStandard.put("EnabledCloudwatchLogsExports", "[slowquery]"); instanceCreationStandard.put("TagList", "[]"); } }
-
파라미터 표준값
public class ParameterGroupStandard { public final static Map<String, String> standardParameters = new HashMap<>(); static { standardParameters.put("max_connections", "10000"); standardParameters.put("max_connections", "10000"); standardParameters.put("max_allowed_packet", "1073741824"); standardParameters.put("character_set_connection", "utf8mb4"); standardParameters.put("character_set_database", "utf8mb4"); standardParameters.put("character_set_filesystem", "utf8mb4"); standardParameters.put("character_set_server", "utf8mb4"); standardParameters.put("character_set_results", "utf8mb4"); standardParameters.put("collation_connection", "utf8mb4_0900_ai_ci"); standardParameters.put("collation_server", "utf8mb4_0900_ai_ci"); standardParameters.put("slow_query_log", "1"); standardParameters.put("log_slow_extra", "ON"); standardParameters.put("time_zone", "UTC"); standardParameters.put("transaction_isolation", "REPEATABLE-READ"); standardParameters.put("performance_schema", "1"); standardParameters.put("log_bin_trust_function_creators", "1"); standardParameters.put("innodb_print_ddl_logs", "1"); standardParameters.put("lower_case_table_names", "1"); standardParameters.put("innodb_monitor_enable", "all"); standardParameters.put("activate_all_roles_on_login", "1"); standardParameters.put("binlog_format", "ROW"); standardParameters.put("binlog_row_image", "FULL"); standardParameters.put("log_output", "FILE"); standardParameters.put("sql_mode", "NO_ENGINE_SUBSTITUTION,ERROR_FOR_DIVISION_BY_ZERO,STRICT_TRANS_TABLES"); standardParameters.put("general_log", "0"); standardParameters.put("log_error_verbosity", "3"); standardParameters.put("log_slow_admin_statements", "1"); standardParameters.put("max_connect_errors", "1000000"); standardParameters.put("sysdate-is-now", "1"); standardParameters.put("interactive_timeout", "1800"); standardParameters.put("wait_timeout", "1800"); standardParameters.put("event_scheduler", "OFF"); standardParameters.put("explicit_defaults_for_timestamp", "1"); standardParameters.put("innodb_lock_wait_timeout", "15"); standardParameters.put("innodb_print_all_deadlocks", "1"); standardParameters.put("performance_schema_events_statements_history_size", "10000"); standardParameters.put("performance_schema_events_statements_history_long_size", "10000"); standardParameters.put("innodb_log_file_size", "3000000000"); // 3 GB standardParameters.put("innodb_flush_log_at_trx_commit", "1"); standardParameters.put("innodb_buffer_pool_size", "{DBInstanceClassMemory*3/4}"); standardParameters.put("sync_binlog", "1"); } }
- Java 17 & SpringBoot 3 & Junit
- AWS SDK (for java)
- Slack API, SDK (interactivity + block kit)
- 환경변수에 설정
- ENCRYPT_KEY, SLACK_TOKEN, SLACK_APP_SIGNING_SECRET, SLACK_DEFAULT_CHANNEL_ID, SLACK_VERIFICATION_TOKEN, SLACK_ADMIN_USER_IDS
- application.properties 파일에 inhouse용 DB 접속 정보 기재 필요
- 실행하는 환경에서 aws configure 사전 수행 필요
- 해당 롤에 rds, secret manager, cloudwatch, performance insights 권한 필요
- profile name이 겹치지 않게 여러 프로필 설정 가능
- Database credential 은 aws Secret Manager에 등록 필요
- postfix 는
-db-credential
로 지정
- postfix 는
- 클러스터 필수 설정 태그
- env: [prod, stage, dev] (환경 명)
- service: [user, shop, order] (서비스 명)
- profiles 설정 필요 (dev, stage, prod 등)
- schema.sql 스크립트 미리 수행
- performance_schema 활성화
- slack app 설정 및 https 도메인 활성화 필요
- slash comamnd 등록 (SlackController.java -> databaseRequestCommand())
- interactivity enable
- callback url 설정
- slack channel 에 bot add
레인 캠벨과 채리티 메이저즈의 [Database Reliability Engineering: Designing and Operating Resilient Database Systems](O'Reilly, 2017)와 같은 책을 통해 기술 조직은 데이터베이스 엔지니어를 모든 데이터베이스의 단독 운영자가 아닌 비즈니스 성장의 주체로 보게 되었습니다. 한때 DBA의 기본 일상은 스키마 디자인 및 쿼리 최적화와 관련되어 있었지만, 이제는 개발자에게 이러한 기술을 가르치고 개발자가 자신의 스키마 변경사항을 안전하게 배포할 수 있도록 시스템을 관리하는 일을 담당합니다. - [실비아 보트로스 - MySQL 성능 최적화](O'Reilly, 2021) 중