인계받은 환경을 보니 RDS 인스턴스가 하나였다. SHOW DATABASES 를 떠 보니 그 안에 스키마가 여섯 개다.
game_prod
game_dev
game_test
game_backup_20151120
tmp
test2
Table of contents
Open Table of contents
무엇이 운영인지 확인했다
이름만으로는 어느 것이 실제로 쓰이는지 알 수 없어서 접속 설정을 열어 어느 쪽이 무엇을 보는지부터 봤다.
$ grep -rn "database" application/config/database.php
운영 서버는 game_prod 를 보고 시험 서버는 game_dev 를 보는 것으로 설정에 적혀 있었다. information_schema.PROCESSLIST 로도 어느 HOST 에서 어느 DB 로 붙는지 확인했다.
game_test 와 tmp 와 test2 는 아무도 안 보는데 그래도 지우기 전에 크기와 표 수를 세어 확인할 필요가 있었다.
SELECT table_schema, COUNT(*) AS tables,
ROUND(SUM(data_length + index_length) / 1024 / 1024) AS mb
FROM information_schema.TABLES
GROUP BY table_schema;
game_prod 84 4210
game_dev 84 180
game_test 61 92
game_backup_20151120 84 3980
tmp 3 2
test2 12 44
game_backup_20151120 이 4기가인데 두 달 전에 뜬 백업이 지워지지 않고 그대로 남아 있었다.
같은 인스턴스가 왜 문제인가
자원을 공유한다는 것이 첫 번째다. 시험 서버에서 큰 쿼리를 돌리면 같은 인스턴스의 운영 쪽이 느려지고 실제로 그랬다. 시험용 통계 쿼리가 몇 분씩 도는 동안 게임 응답이 늦어졌다.
SHOW PROCESSLIST;
SHOW PROCESSLIST 로 확인하면 운영과 시험 접속이 한 목록에 섞여 나온다.
두 번째는 실수다. 접속해서 USE game_prod 를 치면 그대로 운영이라 스키마 이름 하나 차이로 갈린다.
인스턴스를 나눴다
운영과 시험이 자원을 나눠 쓰지 않게 시험용 인스턴스를 따로 만들었다.
game-prod (운영)
game-dev (시험)
사양은 시험 쪽을 작게 잡았는데 시험은 부하가 적으니 큰 것이 필요 없기 때문이다.
옮기는 순서는 이렇게 했다.
- 시험 인스턴스 생성
game_dev스키마를 덤프해서 옮김- 시험 서버 접속 설정 변경
- 시험 서버에서 동작 확인
- 옛 인스턴스에서
game_dev삭제
5번을 바로 하지 않고 일주일 두고 시험 서버가 정상인지 본 뒤에 지웠다.
백업 스키마를 정리했다
game_backup_20151120 은 같은 인스턴스에 있으니 백업이 아니었고 인스턴스가 죽으면 같이 죽는다.
그래서 덤프를 떠서 별도 저장소로 옮긴 뒤에 인스턴스에서 스키마를 지웠다.
$ mysqldump -h ... game_backup_20151120 | gzip > backup_20151120.sql.gz
$ aws s3 cp backup_20151120.sql.gz s3://.../db-backup/
gzip 으로 4기가가 800메가로 압축됐고 인스턴스 용량이 그만큼 줄었다. 같은 장비 안의 사본은 사본이 아니라는 것이 요점이고 이것을 정리하고 나서야 실제 백업이 없다는 사실이 드러났다.
인스턴스 설정을 봤더니 자동 백업 보관 기간이 1일로 기본값 그대로 남아 있었다. 문제가 하루 뒤에 발견되면 되돌릴 지점이 없어서 7일로 늘렸고 용량 비용이 늘지만 그만한 값이었다.
자동 백업에는 성질이 하나 더 있었다. 매뉴얼에 인스턴스를 지울 때 자동 백업을 남기겠다고 고르지 않으면 인스턴스와 함께 지워진다고 적혀 있다. 수동 스냅샷은 그것과 별개로 남으므로 인스턴스를 지우기 전에 수동 스냅샷을 하나 떠 두는 것을 절차에 넣었다.
검증 — 복원과 계정 분리
백업이 실제로 되돌려지는지도 확인할 필요가 있었다. 시험 인스턴스로 특정 시점 복원을 한 번 해 보고 COUNT(*) 와 MAX 값으로 자료가 온전한지 봤다. 설정이 켜져 있다는 것만으로는 백업이 된다고 말할 수 없다. 복원이 되는지 해 보기 전까지는 백업이 있다고 말할 수 없었다.
계정이 하나로 전부 접속하고 있는 것도 고쳤는데 시험 서버도 배치도 사람도 같은 계정을 쓰고 있었다.
app_prod 운영 애플리케이션 game_prod 에만 권한
app_dev 시험 애플리케이션 game_dev 에만 권한
batch 배치 필요한 테이블만
readonly 조회용 SELECT 만
GRANT SELECT 만 준 readonly 를 만들고 나니 확인 작업을 안심하고 할 수 있었다. 조회만 하는 자리에서 실수로 UPDATE 를 쳐도 권한이 없어 아무 일도 안 일어난다.
정리하면서 앞으로 만들 것의 이름도 정했다.
{서비스}-{환경} 인스턴스
{서비스}_{용도} 스키마
{서비스}_{용도}_{계정} 접속 계정
임시로 만드는 것에는 만든 날짜와 만든 사람을 넣게 했다. tmp 나 test2 가 다시 안 생기게 하려는 것이다.
정리
- 운영과 시험이 한 RDS 인스턴스에 있으면 자원을 공유하고 실수하기 쉽다
- 스키마 이름만으로는 무엇이 쓰이는지 모르므로 접속하는 쪽을 확인한다
information_schema.TABLES로 크기와 표 수를 세면 무엇이 남았는지 드러난다SHOW PROCESSLIST에 운영과 시험 접속이 한 목록에 나온다- 같은 장비 안의 사본은 사본이 아니다
- 옛 스키마 삭제는 새 쪽이 정상인 것을 본 뒤로 미룬다
- 인스턴스를 지우면 자동 백업도 함께 지워진다 — 수동 스냅샷은 남는다
- 자동 백업 기간이 기본값이면 되돌릴 수 있는 범위가 짧다
- 복원을 해 보기 전에는 백업이 있다고 말할 수 없다
GRANT SELECT계정이 있으면 확인 작업이 안전하다- 이름 규칙을 정하고 임시 대상에는 날짜와 만든 사람을 넣는다