세션
기본 API는 호출마다 새 데이터베이스 세션을 사용합니다. 세션을 직접 열어야 하는 경우와 이유를 설명합니다.
기본 동작: 호출마다 새 세션
await env.db.exec("select 1");이 한 줄은 연결, 쿼리 실행, 동기화, 연결 해제를 모두 수행합니다. 따라서 호출 사이에는 세션 상태가 남지 않습니다.
BEGIN은 다음 호출까지 유지되지 않습니다.SET설정은 다음 호출에 적용되지 않습니다.- prepared statement와 temporary table도 유지되지 않습니다.
연결을 재사용하지 않는 이유
연결을 재사용하려면 앞선 요청이 남긴 상태를 완전히 제거했다는 보장이 필요합니다. PostgreSQL의 DISCARD ALL이 그 역할을 하지만, 이 엔진에서 모든 상태를 안전하게 지우는지 아직 확인되지 않았습니다.
안전성이 확인되지 않은 상태에서 연결을 재사용하면, 한 요청의 SET 설정이나 temporary table이 다른 사용자의 요청에 영향을 줄 수 있습니다. 그래서 현재는 매번 연결을 닫고 새로 엽니다. 요청 간에 세션 상태가 전달되지 않습니다.
성능 특성
| 단계 | 비용 |
|---|---|
| 새 세션 기본 비용 | 2.6 ms |
$1 파라미터 | +0.6 ms |
| 실제 테이블 조회(카탈로그 준비) | +5 ms |
| 쓰기(커밋 + flush) | +9 ms |
테이블 조회의 5ms는 호출마다 새 세션을 열며 카탈로그를 준비하는 비용입니다. 안전한 세션 재사용이 확인되면 줄일 수 있습니다. PostgreSQL 프로토콜로 직접 연결해 세션을 유지하면 동일한 쿼리는 0.55ms입니다.
세션 직접 사용하기
여러 SQL 문을 같은 세션에서 실행해야 한다면 세션 핸들을 사용하세요.
const s = await env.db.session();
try {
await s.exec("begin");
await s.exec("insert into a values ($1)", [1]);
await s.exec("insert into b values ($1)", [2]);
await s.exec("commit");
} finally {
await s.close();
}@runlot/pg에서는 pool.connect()가 같은 역할을 합니다.
규칙
close()는 멱등입니다. 여러 번 호출해도 됩니다.close()는 열려 있는 트랜잭션을 롤백합니다. 커밋하려면 직접COMMIT을 보내야 합니다.- 닫힌 핸들에서 SQL을 실행하면
08003오류가 발생합니다. - SQL 문을 실행하지 않은 채 30초가 지나면 세션을 회수하고 열린 트랜잭션을 롤백합니다.
요청 범위 안에서만 사용하세요
세션 핸들을 전역 변수에 저장하거나 요청 밖으로 전달하지 마세요. 30초 제한에 걸려 트랜잭션이 롤백될 수 있고, 세션을 잡고 있는 동안 다른 요청도 대기합니다.
동시 요청은 순서대로 처리됩니다
프로젝트당 데이터베이스 요청은 한 번에 하나씩 처리됩니다. 세션을 오래 유지하는 요청이 있으면 다른 요청은 대기합니다. 긴 트랜잭션은 프로젝트 전체의 응답 시간을 늘릴 수 있습니다.
SQL 문 하나의 기본 실행 제한은 10초입니다. 이를 넘는 쿼리는 중단됩니다.