runlot

문장 제한 시간

문장 하나에 10초 상한이 있습니다. 넘으면 57014로 끊기고, 이 값은 올릴 수 없습니다.

프로젝트 데이터베이스는 문장 하나에 10초 상한을 둡니다. 넘으면 그 문장이 다음 오류로 끊깁니다.

[57014] canceling statement due to statement timeout

왜 두는가

프로젝트의 데이터베이스는 워커와 같은 프로세스 안에서 한 차선으로 실행됩니다. 문장 하나가 길게 돌면 그 프로젝트의 다른 요청이 전부 뒤에서 기다립니다. 상한은 그 대기를 10초로 묶습니다.

show statement_timeout은 0입니다

이 상한은 PostgreSQL의 statement_timeout 설정이 아니라 런타임이 따로 두는 천장입니다. 그래서 SHOW statement_timeout0을 답하고, 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)

이 페이지의 목차