Skip to content
isdnetworks
Go back

중간에서 멈추는 DDL 스크립트

(수정됨)

해외몰 스키마 파일 global_mall_ddl.sql 을 열었더니 테이블 58개를 전부 지우고 다시 만드는 구성이었다. 첫 줄부터 DROP TABLE TB_COMM_BRND_MST; 식으로 이어진다. 존재 여부를 확인하는 IF EXISTS 는 붙어 있지 않았다.

Table of contents

Open Table of contents

증상 — 지우고 다시 만드는 스크립트

없는 테이블을 지우려 하면 오류가 나고 mysql 클라이언트는 거기서 멈춘다. --force 를 주면 이후 문장이 계속 실행되는데, 그러면 오히려 더 나쁘게 일부만 반영된 상태가 된다.

새 환경에 처음 적용할 때는 테이블이 하나도 없으니 첫 문장부터 실패한다. 중간에 테이블이 추가된 뒤에도 목록에 없는 것은 안 지워지고 옛 구조 그대로 남는다.

조치 — 한 단어가 성질을 바꾼다

멈추지 않게 하는 데는 두 가지 방법이 있었다. 실행할 때 mysql --force 를 주는 것과, 58줄 전부를 DROP TABLE IF EXISTS 로 바꾸는 것이다. 뒤쪽을 골랐다. 이유는 --force 는 오타로 난 오류까지 똑같이 넘겨 버려서다. MySQL 5.7 매뉴얼의 DROP TABLE 절은 IF EXISTS 가 없는 테이블에 오류 대신 NOTE 만 낸다고 적고 있다. 이 한 단어로 몇 번을 돌려도 같은 결과가 나온다.

한 번만 되는 스크립트는 실행 전 상태에 의존하므로 실패하면 손으로 정리해야 하고, 재실행 가능한 스크립트는 상태와 무관하므로 실패해도 다시 돌리면 된다. 배포가 중간에 죽을 수 있는 자리에서는 뒤쪽만 쓴다.

주의 — 순서와 제약

지우는 순서가 TB_COMM_·TB_OPR_·TB_PRD_ 알파벳순이었는데 외래키가 없어서 지금은 문제가 없다. 참조되는 테이블을 먼저 지우면 실패하므로 외래키가 생기면 이 스크립트가 깨진다.

그때는 역순으로 지우거나 SET foreign_key_checks = 0 으로 제약을 잠시 끄는 방식이 필요하다. 지금 안 걸린다는 것과 앞으로 안 걸린다는 것은 다르므로 그 사실을 주석으로 남길 자리였다.

이름이 말하지 않는 용도

파일명 global_mall_ddl.sql 이 스키마 정의라는 뜻만 담고 있어서 초기화용인지 마이그레이션용인지 알 수 없었다. 받는 사람이 스키마 파일로 보고 운영에 돌리면 전 테이블이 날아간다.

이름이 reset_dev_schema.sql 처럼 용도를 말하게 했다. 파괴적인 스크립트에는 첫 줄에 -- WARNING 주석이 붙게 했다. 개발 환경 전용이고 전 테이블을 지운다는 문장이 파일을 열자마자 보이게 했다.

필수 제약의 시점

같은 파일에서 product_name 까지 DEFAULT NULL 로, 컬럼이 대체로 빈 값을 허용하게 정의돼 있는 것도 봤다. 필수 여부가 데이터베이스에 없고 애플리케이션 검증에만 있는 상태였다.

들어오는 경로가 하나가 아니므로 검증을 거치는 경로와 안 거치는 경로가 섞인다. 나중에 NOT NULL 을 걸려면 이미 빈 값인 행을 먼저 채워야 한다. 무엇으로 채울지 모르는 경우가 대부분이다. 필수 제약은 처음에 거는 것이 가장 싸고 정말 필수인 몇 개만 골라야 한다.

정리


Share this post on:

Previous Post
외주 산출물의 목적과 구성
Next Post
규제가 컬럼이 될 때