D1 디버깅 (Debug D1)
D1은 데이터베이스를 쿼리할 때 반환되는 예외(exception)와 오류를 캡처하고 기록할 수 있게 해 줘요. D1을 디버깅하려면 Workers를 디버깅할 때 사용하는 것과 동일한 도구를 사용해요.
출처: 문서
본문
D1의 stmt.과 db. 메서드는 오류가 발생할 때마다 Error 객체를 던져요. 예외를 캡처하려면 e.message 값을 기록해요.
예를 들어 아래 코드에는 INSERT 대신 INSERTZ라는 잘못된 키워드가 있는 쿼리예요:
try {
// This is an intentional misspelling
await db.exec("INSERTZ INTO my_table (name, employees) VALUES ()");
} catch (e: any) {
console.error({
message: e.message
});
}
위 코드는 다음 오류 메시지를 던져요:
{
"message": "D1_EXEC_ERROR: Error in line 1: INSERTZ INTO my_table (name, employees) VALUES (): sql error: near \"INSERTZ\": syntax error in INSERTZ INTO my_table (name, employees) VALUES () at offset 0"
}
오류 목록 (Error list)
D1은 확장된(상세한) 오류 메시지와 함께 다음 오류 상수를 반환해요:
| 오류 메시지 | 설명 | 권장 조치 | | D1_ERROR | 특정 D1 오류의 접두사. | 아래의 "D1_ERROR 목록"을 참고해 본인의 오류를 자세히 확인하세요. | | D1_EXEC_ERROR | Exec 오류 - x행의 y 오류. | | | D1_TYPE_ERROR | 열(column)과 값(value) 사이에 타입 불일치가 있을 때 반환돼요. 흔한 원인은 undefined 변수(지원되지 않음)를 null 대신 제공하는 것이에요. | 값과 열의 타입이 일치하는지 확인하세요. | | D1_COLUMN_NOTFOUND | 열을 찾을 수 없음. | 데이터베이스에 존재하는 열을 선택했는지 확인하세요. |
다음 표는 D1_ERROR의 구체적인 사례를 나열해요.
D1_ERROR 목록
| D1_ERROR 타입 | 설명 | 권장 조치 | | No SQL statements detected. | 입력한 쿼리에 SQL 문이 포함되어 있지 않음. | 앱 조치: 쿼리에 유효한 SQL 문이 하나 이상 포함되도록 하세요. | | Your account has exceeded D1's maximum account storage limit, please contact Cloudflare to raise your limit | 계정의 모든 D1 데이터베이스의 총 저장 용량이 계정 저장 한도를 초과했음. | 앱 조치: 사용하지 않는 데이터베이스를 삭제하거나, 계정을 유료 플랜으로 업그레이드하세요. | | Exceeded maximum DB size. | D1 데이터베이스가 저장 한도를 초과했음. | 앱 조치: 데이터베이스에서 데이터 행을 삭제하거나, 데이터를 여러 데이터베이스로 샤딩하세요. | | Your account has exceeded D1's free tier daily row read limit. Upgrade to a paid plan or wait until tomorrow (midnight UTC) to continue. See https://developers.cloudflare.com/d1/platform/limits/ for more details. | 계정이 D1 무료 티어의 일일 행 읽기 한도에 도달했음. | 앱 조치: UTC 자정이 되어 한도가 초기화될 때까지 기다리거나, 계정을 유료 플랜으로 업그레이드하세요. Limits 문서를 참고하세요. | | Your account has exceeded D1's free tier daily row write limit. Upgrade to a paid plan or wait until tomorrow (midnight UTC) to continue. See https://developers.cloudflare.com/d1/platform/limits/ for more details. | 계정이 D1 무료 티어의 일일 행 쓰기 한도에 도달했음. | 앱 조치: UTC 자정이 되어 한도가 초기화될 때까지 기다리거나, 계정을 유료 플랜으로 업그레이드하세요. Limits 문서를 참고하세요. | | D1 DB reset because its code was updated. | Cloudflare가 D1(또는 기반 Durable Object)의 코드를 업데이트했고, D1 데이터베이스를 포함한 Durable Object가 재시작 중임. | 작업을 재시도하세요. | | Internal error while starting up D1 DB storage caused object to be reset. | D1 데이터베이스를 포함한 Durable Object가 시작에 실패했음. | 작업을 재시도하세요. | | Network connection lost. | 네트워크 오류. | 작업을 재시도하세요. 위의 "작업 재시도" 참고를 확인하세요. | | Replica disconnected from primary. | 읽기 복제본과 주 인스턴스 사이의 네트워크 오류. | 작업을 재시도하세요. 위의 "작업 재시도" 참고를 확인하세요. | | Internal error in D1 DB storage caused object to be reset. | 오류로 인해 D1 데이터베이스가 재시작되었음. | 작업을 재시도하세요. | | Cannot resolve D1 DB due to transient issue on remote node. | 쿼리가 D1 데이터베이스를 포함한 Durable Object에 도달하지 못했음. | 작업을 재시도하세요. 위의 "작업 재시도" 참고를 확인하세요. | | Can't read from request stream because client disconnected. | 쿼리 요청이 이루어졌지만(예: SQL 쿼리 업로드), 쿼리가 완전히 실행되기 전에 연결이 닫혔음. | 앱 조치: 작업을 재시도하고 연결이 열려 있도록 유지하세요. | | D1 DB storage operation exceeded timeout which caused object to be reset. | 쿼리가 대량의 정보(예: GB 단위)를 쓰려고 해서 시간이 너무 오래 걸리고 있음. | 앱 조치: 쿼리를 최적화하고(각 쿼리가 더 짧게 걸리도록), 부하를 시간에 분산해 요청 수를 줄이거나, 쿼리를 샤딩하세요. | | D1 DB is overloaded. Requests queued for too long. | 요청이 너무 많거나, 대기 중인 요청이 너무 오래 걸려 D1 데이터베이스에 대한 요청이 너무 오래 대기열에 머물렀음. | 앱 조치: 쿼리를 최적화하고, 부하를 시간에 분산해 요청 수를 줄이거나, 쿼리를 샤딩하세요. | | D1 DB is overloaded. Too many requests queued. | 요청이 너무 많거나, 대기 중인 요청이 너무 오래 걸려 D1 데이터베이스의 요청 대기열이 너무 길어졌음. | 앱 조치: 쿼리를 최적화하고, 부하를 시간에 분산해 요청 수를 줄이거나, 쿼리를 샤딩하세요. | | D1 DB's isolate exceeded its memory limit and was reset. | 쿼리가 메모리에 너무 많이 로드해서 D1 데이터베이스가 크래시했음. | 앱 조치: 쿼리를 최적화하고, 부하를 시간에 분산해 요청 수를 줄이거나, 쿼리를 샤딩하세요. | | D1 DB exceeded its CPU time limit and was reset. | 쿼리가 많은 CPU 시간을 사용하고 있음(예: 9GB 이상 테이블 스캔, 대규모 import/export 시도). | 앱 조치: 쿼리를 더 작은 샤드로 나누세요. |
자동 재시도 (Automatic retries)
D1은 읽기 전용 쿼리를 감지해, 재시도 가능한 오류가 있는 실패가 발생하면 해당 쿼리를 최대 두 번까지 자동으로 실행하려 시도해요.
D1은 재시도 시도가 데이터베이스 쓰기를 일으키지 않도록 보장해요. 이 덕분에 자동 재시도는 부작용(side-effect)으로부터 안전해요. 설령 수정을 일으키는 쿼리가 읽기 전용 감지를 통과한다 해도 말이죠. D1은 매 쿼리 실행 후 수정 여부를 확인하고, 재시도 시도로 인해 쓰기가 발생했다면 해당 쿼리를 롤백해요.
로그 보기
wrangler tail을 사용하거나 Cloudflare 대시보드를 통해 Worker에서 생성되는 실시간 로그 스트림을 확인할 수 있어요.
이슈 보고 (Report issues)
-
버그를 신고하거나 기능을 요청하려면 Cloudflare Community Forums로 이동해요.
-
피드백을 보내려면 D1 Discord 채널로 가세요.
-
Wrangler에 문제가 있다면 Wrangler GitHub 저장소에 이슈를 보고해요.
버그 보고에는 다음 항목을 최대한 많이 포함해야 해요:
-
데이터베이스의 ID.
wrangler d1 list를 사용해 데이터베이스 이름을 ID와 매칭하세요. -
문제가 발생했을 때 실행한 쿼리(들). 개인 식별 정보(PII)는 반드시 제거(redact)하세요.
-
쿼리를 실행하는 Worker 코드. Workers Binding API를 사용한
bind()호출을 포함해요. -
전체 오류 텍스트.
error.cause.message의 내용을 포함해요.
관련 리소스 (Related resources)
-
Workers를 디버깅하는 방법을 배워요.
-
Worker와 D1에서 생성되는 로그에 접근하는 방법을 이해해요.
-
wrangler dev를 사용해 Worker와 D1을 로컬에서 실행하고 배포 전에 문제를 디버깅하세요.