데이터데이터베이스
문장 제한 시간
문장 하나에 10초 상한이 있습니다. 넘으면 57014로 끊기고, 이 값은 올릴 수 없습니다.
프로젝트 데이터베이스는 문장 하나에 10초 상한을 둡니다. 넘으면 그 문장이 다음 오류로 끊깁니다.
[57014] canceling statement due to statement timeout왜 두는가
프로젝트의 데이터베이스는 워커와 같은 프로세스 안에서 한 차선으로 실행됩니다. 문장 하나가 길게 돌면 그 프로젝트의 다른 요청이 전부 뒤에서 기다립니다. 상한은 그 대기를 10초로 묶습니다.
show statement_timeout은 0입니다
이 상한은 PostgreSQL의 statement_timeout 설정이 아니라 런타임이 따로 두는 천장입니다. 그래서 SHOW statement_timeout은 0을 답하고, SET statement_timeout으로 올릴 수 없습니다. 내리는 것은 됩니다 — 더 짧은 statement_timeout을 세션에 두면 그 값이 먼저 듭니다.
오류 코드가 같은 57014라서 둘이 구분되지 않습니다. 10초 근처에서 끊겼다면 이 천장입니다.
걸리면
문장을 잘게 나누세요. 큰 UPDATE는 키 범위로 묶어 여러 번 실행하고, 대량 INSERT는 1,000행 안팎으로 끊어 세션 하나의 트랜잭션에 넣습니다.
// 12,000곳의 best_rank 재계산 — 한 문장이면 10초를 넘긴다
for (let offset = 0; ; offset += 2000) {
const ids = await env.db.exec("select id from places order by id limit 2000 offset $1", [offset]);
if (ids.length === 0) break;
await env.db.exec(
`update places p set best_rank = b.min_rank
from (select place_id, min(rank) as min_rank from rankings
where place_id = any($1) group by place_id) b
where b.place_id = p.id`,
[ids.map((r) => r.id)],
);
}빈 테이블에서 통과한 마이그레이션이 데이터가 들어온 뒤 같은 문장에서 걸릴 수 있습니다. 상관 서브쿼리 UPDATE가 대표적입니다 — 집계를 한 번 하고 조인으로 붙이면 대개 상한 안에 듭니다.
값
| 항목 | 값 |
|---|---|
| 문장 상한 | 10초 |
| 오류 코드 | 57014 |
| 올릴 수 있는가 | 아니오 |
| 내릴 수 있는가 | 예 (SET statement_timeout) |