모든 태그

# DBRE

10개의 글

사람 손이 붙어 있던 다섯 곳을 끊다: 설정 드리프트·변경 리뷰·인덱스 판정·인시던트 리포트·월간 점검

이기종 DBMS 운영 관리 플랫폼 DBTower 9편. 현업 DBA의 병목이 어디에 남는지를 렌즈로, 사람 손이 선형으로 붙던 다섯 지점을 기능으로 끊었습니다. (1) 설정 드리프트 이력: 파라미터 diff의 공간축("A와 B가 다른가")에 시간축("언제부터 무엇이 바뀌었나")을 붙였습니다. 거울 테이블과 변경 로그로 무변경 주기엔 스냅샷 한 줄만 쌓이게 했고, work_mem 4096→8192 실변경을 감지해 카드를 쐈습니다. 검증 중 MongoDB parameters()가 $clusterTime 같은 응답 gossip 필드를 흘려 매번 오탐이 나던 기존 버그도 잡았습니다. (2) 스키마 변경 리뷰 게이트: 배포 전 DDL을 규칙으로 판정(락 위험·DEFAULT 없는 NOT NULL·DROP·WHERE 없는 대량 변경)하고 실제 행수로 락 위험을 확정한 뒤 AI 1차 소견을 붙여 ADMIN 승인·자동 감사까지. 실행은 하지 않고 gh-ost 경로만 안내합니다. (3) 인덱스 사용 통계 주기 영속: "이 인덱스 지워도 되나"는 재시작 누적 카운터의 순간값으론 못 답합니다. 5기종 스캔 통계를 6시간 주기로 영속하고(Oracle은 미지원 정직), lakehouse가 first-vs-last 델타·리셋 클램프로 분기 창 판정 마트를 짓습니다. (4) 인시던트 리포트: 장애 구간을 주면 시점 비교·설정 변경·플랜 플립·대기·가용성을 한 장으로 재구성하고 AI가 재료 내 사실만으로 요약합니다. (5) 월간 점검 리포트: 헬스·백업·Advisor·용량·낭비·설정 변경을 매월 자동 발행합니다. 다섯 개 전부 읽고 판정·기록까지가 몫이고 대상 DB는 바꾸지 않습니다. 신규 모듈 하나(review)는 이벤트로 alert에 카드를 위임하고, 공개 파사드 둘(score·finops)로 Modulith 경계를 순환 없이 유지했습니다. 테스트 514건, VERIFICATION 110개 절.

관제탑과 대화하고 두 저장소를 잇다. 이모지로 진단을 부르고, 창고가 계산한 평소로 오탐을 지운다

이기종 DBMS 운영 관리 플랫폼 DBTower. 앞부분은 알림에서 진단까지의 왕복을 완성합니다. 회귀·이상·운영 경보가 밋밋한 텍스트에서 구조화된 Discord embed 카드가 됩니다(심각도 색·담당 팀·AI 1차 분석·질문이 미리 채워진 진단 딥링크). 알림에 돋보기 이모지를 달면 봇이 그 인스턴스를 AI로 진단해 답글을 붙이죠. 여기엔 함정이 둘 있었습니다. 왼쪽 돋보기(U+1F50D)와 오른쪽 돋보기(U+1F50E)가 서로 다른 유니코드라는 점, 그리고 웹훅이 쓴 메시지의 embed를 봇이 읽으려면 특권 인텐트가 필요하다는 점입니다. 후자는 발사 시점에 message_id를 인스턴스에 매핑해 권한 0개로 풀었습니다. 대상이 하필 죽어 있어 진단 도구가 전부 빈손이었을 때, AI 답글은 수치를 지어내는 대신 "근본원인을 확정하지 못했습니다"라고 답했습니다. 이번 실측에서 가장 인상적인 대목이었습니다. MCP 정적 토큰은 OAuth 2.1 브라우저 로그인으로 바꿨고(302 대신 401 함정, redirect_uri userinfo 우회), Vault 동적 자격증명으로 유출 창을 TTL 2분으로 줄였습니다. 뒷부분은 lakehouse(장기 분석계)와의 루프를 양방향으로 닫습니다. 받아오는 쪽에서는, lakehouse가 수개월 이력으로 계산한 요일×시간대 베이스라인을 V24 테이블로 받아 14일 창에 충분통계량 복원(Σx=n·m, Σx²=(n−1)s²+n·m²)으로 가중 병합했습니다. 실측 스파이크(psql 3,000회)의 판정이 장기 테이블 내용에 따라 뒤집혀 z=7.42로 발화했고, 관측 수가 101(장기 100+단기 1)로 찍히며 병합이 실제로 작동한 자국이 남았습니다. 내보내는 쪽에서는, 대기 이벤트(V25)와 오브젝트 크기(V26)를 주기 영속하는 잡을 신설하고 plan_snapshot 보존에 48시간 하한을 병행했습니다. 자연어 서빙은 Metabot이 Cloud 전용이라 생긴 갭을 MCP 도구 두 개(장기 마트 SELECT·Metabase 카드 생성)로 메웠고, 카드 76이 실제로 생성되어 bar 차트가 143ms에 렌더됐습니다.

여럿이 쓰는 관제탑: 팀 경계와 멀티노드, 그리고 호스트 차원

이기종 DBMS 운영 관리 플랫폼 DBTower의 멀티테넌시와 호스트 차원 기록입니다. 앞부분은 여러 팀이 한 콘솔을 쓰기 시작하는 국면을 다룹니다. 팀 사용자는 자기 팀 인스턴스와 전역만 보고, 남의 팀 인스턴스는 id로 직접 찔러도 403이 아니라 404를 받습니다(존재 자체를 숨김). 강제 지점은 단 한 곳(RegistryService)입니다. 세션을 메타 DB로 옮겨 재시작에도 로그인이 살아남게 했고, 그 과정에서 Boot 자동구성이 인메모리로 조용히 폴백하는 함정을 밟았습니다. 이렇게 준비한 노드를 실제로 늘렸더니, 분산 락 하나 때문에 두 번째 노드가 놀고 있었습니다. 샤드별 락으로 바꾸니 두 노드가 수집을 나눠 들고, 한 노드를 죽이면 남은 노드가 설정 변경 없이 전 샤드를 인수하며, 같은 쿠키로 로그인도 유지됩니다. 로그인 잠금 카운터도 메타 DB로 옮겨, 노드 A에서 두 번·B에서 한 번 틀리자 네 번째가 잠기는 것을 실측했습니다. 최대 볼륨 테이블은 월별로 파티셔닝해 보존 정리를 DELETE 1.9초에서 DROP 12.8ms로 줄이고 블로트를 아예 없앴으며, 커넥션은 온디맨드로 바꿔 격리 대상의 유휴 커넥션을 1개 영구에서 0으로 만들었습니다. 뒷부분은 호스트 차원입니다. 디스크 포화 예측은 잔량이 아니라 속도를 봅니다. 여유가 76.8%나 남았는데 치명 경보가 뜨는 화면을 실쓰기 부하로 직접 만들었습니다. 초당 17MB씩 줄고 있으면 20시간 뒤 장애이므로 이 경보가 맞습니다. 여기서도 node-exporter가 rootfs 마운트 없이 컨테이너 자기 자신만 보고 있던 함정과, mountpoint="/" 고정이 데이터 전용 마운트를 쓰는 실무와 어긋나는 설계 함정을 만났습니다. 마지막은 서버 공유 인지입니다. 등록 단위는 DB인데 물리 단위는 서버라, 같은 서버에 DB 두 개를 등록하면 세션·복제·데드락 경보가 두 번 울립니다. 이를 그룹당 1회로 줄이되 "누구에게 해당하는지"를 명시하고, 헬스 스코어(위험 귀속)는 일부러 dedup하지 않은 선 긋기를 기록했습니다.

아무도 못 쓰던 프로젝트를 셀프호스트 제품으로 끌어올리고, 화면 패리티까지 맞추다

이기종 DBMS 운영 관리 플랫폼 DBTower 프로덕션화·화면 패리티 편. 기능은 레퍼런스로 삼은 사례를 넘어섰는데, 정작 "남이 클론해서 실제로 쓸 수 있나"를 물으니 답이 아니었습니다. 블로커는 넷이었습니다. 라이선스가 없어 법적으로 아무도 못 썼습니다. 암호화 fail-closed가 하필 셀프호스트가 쓰는 docker 프로필만 비껴가, 대상 DB 비밀번호가 평문으로 저장됐습니다. 비밀번호 컬럼이 든 옛 H2 파일은 커밋된 채였고, AI 판단 규칙 파일은 이미지에서 빠져 빈 프롬프트로 돌고 있었습니다. Phase 0(배포 블로커) 넷을 없애고, 관제탑이 자기 자신을 지키기 시작하고(로그인 잠금·메타 백업·웹 HTTPS), 문의에 참조 테이블 스키마를 붙였습니다. 이어서 레퍼런스 발표의 화면 11장을 컬럼 단위로 전수 대조하며 표 컬럼 패리티를 맞췄고, 그 과정에서 함정 셋을 만났습니다. 단위 테스트 382건이 초록인데도 웹 콘솔 전체가 백화된 채 커밋돼 있었습니다. "카탈로그 재구성(근사)" 배지는 알고 보니 게으름의 라벨이었습니다. CPU 그래프를 붙이다 보니 활동 그래프가 9시간 미래의 빈 구간을 조회하고 있었습니다. 전부 라이브 실측과 함께 기록합니다.

백업이 진짜가 되기까지: 로그 백업 5기종과 시점 복구, 그리고 정석까지의 네 걸음

이기종 DBMS 운영 관리 플랫폼 DBTower 6편. 백업 대장정입니다. 전반부는 로그 백업이 MSSQL만 되던 것을 MySQL binlog, PostgreSQL WAL, MongoDB oplog, Oracle 아카이브 로그까지 다섯 기종 전부로 넓히며 "기종이 못 하는 것"과 "하다가 깨진 것"을 구분하는 UNSUPPORTED 상태를 만들고, 최신 파일 하나만 수집하면 체인에 조용한 구멍이 난다는 것을 "마지막 이전 전부" 보충 수집으로 고치고, 생성한 복원 안내문을 실제로 실행해 SQL Server와 PostgreSQL에서 목표 시점의 상태를 정확히 재현한 기록입니다. 후반부는 그걸 현업의 정석 쪽으로 옮겨 가는 네 걸음입니다. Mongo oplog 증분($gte로 일부러 만든 겹침 한 건이 체인 무결의 증거, 산출물 28분의 1), pg_receivewal 스트리밍(복제 슬롯 덕에 수신자를 죽여도 재시작 사이 유실 0, 그리고 죽은 프로세스를 산 것처럼 보이게 하던 docker exec -i 함정), MySQL 물리 백업 XtraBackup(MYSQL_PWD를 안 읽고 /dev/stdin defaults를 조용히 무시하는 함정 두 겹, 검증은 파일 존재가 아니라 실제 prepare 실행), 그리고 AES-256-GCM 산출물 암호화(변조된 백업은 조용히 오염되는 대신 명확히 실패한다)까지입니다.

DBTower 포트폴리오 총정리: 이기종 DBMS 5기종을 인터페이스 하나로 관제·진단하기까지, 실측 117절

MySQL, PostgreSQL, SQL Server, Oracle, MongoDB를 하나의 관제탑에서 등록하고 진단하고 백업하고 자율 감시하는 컨트롤 플레인 DBTower의 포트폴리오 총정리입니다. 도구 파편화와 DBA 반복 문의라는 문제 정의에서 출발합니다. 추상화 경계를 SQL이 아니라 운영 행위에 그은 설계 결정과, 그 결정을 성격이 정반대인 두 기종을 실제로 추가해 코어 0줄 수정으로 증명한 과정을 담았습니다. 자기 자신을 관리 대상으로 등록해 자기 풀스캔을 잡은 도그푸딩(21.269ms에서 0.062ms), 따옴표 하나로 인덱스가 죽는 암시적 형변환을 추정 대 실제 괴리 300배로 지목하고 정합성 사고까지 증명한 심층 진단, FULL 앵커와 LOG 체인이 병행하는 정석 백업과 실제 시점 복구, 결함 20건 이상을 스스로 감사해 FIX와 SKIP을 가른 하드닝까지. 모든 성능 수치는 개선 전후를 직접 잰 실측이고, 재현 절차는 저장소 VERIFICATION.md 117개 절에 있습니다.

v1.0.0 이후, 다섯 기종을 더 깊이 판 심화 아크들과 내가 만든 걸 감사한 기록

이기종 DBMS 운영 관리 플랫폼 DBTower 심화 편. v1.0.0을 찍은 뒤 문서에 정직한 잔여로 남겨둔 것들을 다시 붙잡았습니다. 그중 셋을 닫았습니다. 쿼리도 데이터도 그대로인데 갑자기 느려지는 플랜 플립을 PostgreSQL 16의 GENERIC_PLAN으로 감지하고, 로컬 백업을 S3 호환 오프사이트로 올려 3-2-1을 채웠으며, TLS 강제 관리형 서비스에 붙되 인증서 검증 우회 옵션은 일부러 만들지 않았습니다. 여기서 심화 아크 넷으로 들어갑니다. 플랜 플립은 기종마다 다른 획득 경로를 shape 정규화 한 겹으로 통일해 다섯 기종으로 넓혔고, p95의 정직 등급은 누적에서 최근 구간으로, 미지원에서 추정으로 끌어올리되 못 올리는 Oracle은 라벨로 대비시켰습니다. 설정 변경 없이 세 기종에서 데드락을 읽었고, 관제가 부하가 되지 않도록 스케일을 다섯 축으로 제어했습니다. 끝으로 만든 것을 스스로 감사해, 동시성·정확성·보안·수명주기 네 축을 훑고 OWASP·CWE·벤더 문서와 대조해 FIX와 SKIP을 갈랐습니다.

인증부터 셀프호스트 v1.0.0까지, 운영 안전 8축으로 프로덕션에 올리다

이기종 DBMS 운영 관리 플랫폼 DBTower의 운영 안전 편입니다. 네트워크에 닿는 누구나 인스턴스를 등록·삭제·백업할 수 있던 결격 사유에서 출발해, 세션+토큰 이중 인증과 역할 분리, 비밀번호 AES-256-GCM 암호화, ddl-auto 드리프트의 Flyway 이관(Boot 4 스타터의 조용한 미실행 함정 포함), 실측으로 확정한 최소 권한 계정, 스케줄러 분산 락, 복원 검증까지 운영 안전을 8개 축으로 닫았습니다. Phase C에서는 멱등 등록 PUT을 종점 삼아 K8s(CloudNativePG e2e)·Ansible(changed=0)·Terraform(validate)을 관제탑에 이었고, 진단이 대상 DB의 부하가 되지 않도록 쿼리 타임아웃·MongoDB 소켓 상한·죽은 DB 지수 백오프 가드레일을 달았습니다. 마무리는 SaaS의 네 벽을 피해 Grafana처럼 셀프호스트 배터리 포함 이미지로 찍은 v1.0.0입니다.

채널을 갈아끼우고 5기종을 인터페이스 뒤로 숨긴, 스스로 진단하는 관제탑

이기종 DBMS 운영 관리 플랫폼 DBTower. 하나의 분석 코어를 세 갈래 채널로 냅니다. 사람이 보는 웹 콘솔, AI 에이전트가 호출하는 MCP 도구, 온콜에게 곧장 꽂히는 웹훅 push. '새 기종 = Operator 구현체 1개'라는 주장은 SQL도 JDBC도 없는 MongoDB와 상용 Oracle을 실제로 붙여 검증했고, DBA가 장애 때 가장 먼저 보는 Wait Event를 5기종으로 통합하면서 'JPA로 통일하면 되지 않냐'는 질문에도 답합니다. 고정 임계 없는 이상 감지(z=378)와 암시적 형변환을 code=12345로 지목하는 심층 원인 진단까지, 플랫폼이 스스로 보고 판단하되 대상 DB는 건드리지 않는 자율 진단 스택을 실측과 함께 담았습니다.

이기종 DBMS를 하나의 컨트롤 플레인으로: DBTower 설계와 쿼리 회귀 감지

MySQL·PostgreSQL·SQL Server처럼 서로 다른 DBMS를 등록부터 모니터링, 백업까지 한 곳에서 관리하는 컨트롤 플레인 DBTower의 설계편입니다. 기종마다 다른 통계 소스(performance_schema·pg_stat_statements·DMV)를 DbmsOperator 인터페이스 하나로 묶었고, 같은 '백업'이 mysqldump·pg_dump·BACKUP DATABASE로 갈리는 차이도 그 인터페이스 뒤로 감췄습니다. '부하 상위 쿼리가 곧 범인은 아니다'라는 문제의식에서 시점 비교가 나왔고, 플랫폼이 자기 자신을 등록해 병목을 잡은 도그푸딩에서는 Seq Scan을 21ms에서 0.06ms로 줄였습니다. 이 시점 비교를 사람이 아니라 플랫폼이 스스로 돌려 쿼리 회귀를 자동으로 감지하고 Discord로 알립니다. 이런 설계 결정과 실측 수치를 함께 기록했습니다.