runlot

마이그레이션

번호 붙은 SQL 파일과 DB 안의 원장 하나. 도구를 얹지 않습니다.

my-app/
  migrations/
    0001_init.sql
    0002_add_posts.sql
runlot pg migrate
0001_init
0002_add_posts

적용할 것이 없으면 그렇게 말합니다.

파일 규칙

NNNN_이름.sql 입니다. 번호로 시작해야 하고 양수여야 합니다. 디렉토리는 기본적으로 <프로젝트>/migrations 이고 --migrations 로 바꿀 수 있습니다.

원장

적용된 것은 데이터베이스 안의 표 하나에 남습니다.

CREATE TABLE IF NOT EXISTS schema_migrations (
  version    int  PRIMARY KEY,
  name       text NOT NULL,
  sha256     text NOT NULL,
  applied_at timestamptz NOT NULL DEFAULT now()
)

무엇이 언제 적용됐는지가 SQL 한 줄로 읽혀야 하기 때문에 도구를 얹지 않았습니다.

runlot pg execute -c "select version, name, applied_at from schema_migrations order by version"

한 트랜잭션에 들어갑니다

각 파일은 DDL 과 원장 삽입이 같은 트랜잭션에 들어갑니다. 그래서 최악의 경우가 "한쪽이 실패한다" 이지 "두 번 적용된다" 가 아닙니다.

어긋나면 멈춥니다

  • 이미 적용된 파일의 내용이 바뀌었을 때 (sha256 이 다릅니다)
  • 원장에는 있는데 파일이 없을 때
  • 이미 적용된 번호보다 작은 번호가 새로 나타났을 때

세 경우 모두 아무것도 적용하지 않고 멈춥니다. 이미 나간 마이그레이션은 고치지 말고 새 번호로 덧쓰세요.

ORM 의 마이그레이션 도구와 함께 쓰기

prisma migratedrizzle-kitSQL 을 만드는 데만 씁니다. 만들어진 SQL 을 migrations/NNNN_*.sql 로 옮기고 runlot pg migrate 로 적용하세요.

# Prisma
npx prisma migrate diff --from-schema-datamodel prisma/schema.prisma \
  --to-schema-datasource prisma/schema.prisma --script > migrations/0003_posts.sql

# Drizzle
npx drizzle-kit generate
cp drizzle/0003_*.sql migrations/0003_posts.sql

prisma migrate deploy 를 워커 안에서 실행하는 길은 없습니다 — 워커 안에 migrate 엔진이 없습니다.

TypeORM 의 synchronize 와 Sequelize 의 sync({ force: true }) 는 런타임 DDL 이라 실제로 돕니다. 개발 중에는 편하지만 프로덕션 마이그레이션 경로로 쓰지 마세요.

SQL 을 한 번만 돌리고 싶을 때

runlot pg execute -c "alter table posts add column pinned boolean not null default false"
runlot pg execute -f ./fix.sql

원장에 남지 않습니다. 스키마를 바꾸는 일은 마이그레이션 파일로 남기시는 편이 좋습니다.

이 페이지에서