마이그레이션의 명시적 트랜잭션 충돌 해결

이 글의 목차 7개 항목

문제와 원인

D1 배치로 마이그레이션을 실행하면 첫 BEGIN TRANSACTION에서 중단돼 스키마 변경과 태그 정리 SQL까지 도달하지 못했다. 파일 양끝의 BEGIN TRANSACTION;·COMMIT;이 D1 배치의 트랜잭션 처리와 충돌했다.

수정 전 코드

0289_operational_health_and_retention.sql

BEGIN TRANSACTION;
COMMIT;

수정 후 코드

0289_operational_health_and_retention.sql

SQL 파일의 BEGIN TRANSACTION;과 COMMIT; 두 명령을 제거하고, 나머지 테이블 생성·컬럼 추가·태그 정리·인덱스 생성 명령을 기존 순서대로 D1 배치에 전달했다.

CREATE TABLE IF NOT EXISTS `app_schema_state` (
  `id` integer PRIMARY KEY NOT NULL CHECK (`id` = 1),
  `migration_version` text NOT NULL,
  `applied_at` text NOT NULL DEFAULT CURRENT_TIMESTAMP
);

INSERT INTO `app_schema_state` (`id`, `migration_version`, `applied_at`)
VALUES (1, '0289', CURRENT_TIMESTAMP)
ON CONFLICT (`id`) DO UPDATE SET
  `migration_version` = excluded.`migration_version`,
  `applied_at` = excluded.`applied_at`;

D1Database.batch

await database.batch(statements.map((sql) => database.prepare(sql)));

태그 정리는 문항 JSON에 없는 인덱스 행을 삭제한 뒤 빠진 태그를 INSERT OR IGNORE로 채운다. 이 순서를 유지해 stale-audit-tag 1행을 제거하고 normalization 1행을 추가했다.

검증 결과

Wrangler의 로컬 D1 두 개에 같은 기초 테이블과 문항 1개를 넣어 원본·수정본 SQL을 각각 실행했다. 문항 태그는 sql, normalization, 초기 인덱스는 sql, stale-audit-tag로 구성했다.

D1의 BEGIN TRANSACTION 오류원본 보기 (새 창)

D1의 BEGIN TRANSACTION 오류

100%원본 보기 (새 창)

확대한 이미지는 상하좌우로 이동할 수 있습니다. 키보드는 이미지 영역에 초점을 두고 방향키를 사용하세요. Esc로 닫습니다.

항목수정 전수정 후
batch() 명령 수28개26개
실행 결과BEGIN TRANSACTION 오류26개 명령 성공
app_schema_state 버전갱신 실패0289
오래된 태그 stale-audit-tag1행 유지제거
누락 태그 normalization0행1행 추가
최종 태그 인덱스sql, stale-audit-tag · 2행normalization, sql · 2행
스키마 0289와 정상 태그 인덱스 2행원본 보기 (새 창)

스키마 0289와 정상 태그 인덱스 2행

100%원본 보기 (새 창)

확대한 이미지는 상하좌우로 이동할 수 있습니다. 키보드는 이미지 영역에 초점을 두고 방향키를 사용하세요. Esc로 닫습니다.