여러 사용자가 SAS Studio 에서 같은 쿼리를 동시에 돌린다. 세 번째까지는 전부 정상인데 네 번째 라운드에서 모든 세션이 한꺼번에 연결 끊김으로 바뀐다. 그런데 sas-compute-server 파드는 살아 있다.
파드가 살아 있다는 점이 중요하다. 파드가 죽어서 세션이 끊긴 것이 아니라, 세션이 응답을 못 받아 끊긴 것으로 보이는 상황이다.
원본 사례에서 다음이 차례로 배제됐다.
| 후보 | 배제 근거 |
|---|---|
| 세션 개수 한계 | 같은 수의 세션으로 call sleep() 만 반복하면 열 번을 돌려도 끊기지 않았다 |
| 인그레스 타임아웃 | 끊기는 시점이 유휴 시간과 무관하고, 실행 중에 끊긴다 |
| 런처 · compute 자원 | 파드가 살아 있고 OOMKilled 나 Evicted 흔적이 없다 |
| 반복 실행 자체 | 부하를 주지 않는 코드로는 재현되지 않는다 |
즉 외부 DB 를 때리는 쿼리일 때만 재현된다.
DB 를 타지 않는 코드로 같은 동시성·반복 횟수를 돌려 본다. 이것이 안 터지면 Viya 쪽 세션 관리 문제가 아니다.
data _null_;
call sleep(30, 1);
run;
MySQL 프로토콜 계열이면 프로세스 목록을 본다.
SHOW PROCESSLIST;
SAS compute 호스트에서 온 Sleep 상태 커넥션이 수백에서 수만 초까지 누적돼 있으면, 쿼리가 끝난 뒤에도 커넥션이 반환되지 않고 DB 가 계속 붙들고 있다는 뜻이다.
유휴 커넥션 수명을 확인한다.
SHOW VARIABLES LIKE 'wait_timeout';
SHOW VARIABLES LIKE 'interactive_timeout';
기본값이 28800(8 시간)이면 유휴 커넥션이 8 시간 동안 남는다. 라운드를 거듭할수록 누적되다가 임계에 닿는 순간 DB 가 새 연결을 거절하거나 응답을 지연시키고, SAS 쪽에서는 전 세션 동시 끊김으로 나타난다.
PROC SQL 로 외부 DB 를 조회하면 실행이 DB 안에서 끝나는 것이 아니라 결과를 SAS Compute 로 끌어온다.
SAS Compute
-> DB 커넥션 열기
-> SQL 제출
-> DB 실행
-> 결과 fetch
-> 커넥션 반환(또는 유휴 상태로 방치)
세션마다 커넥션을 따로 열고, fetch 가 끝날 때까지 반환되지 않는다. 여러 세션이 같은 쿼리를 반복하면 유휴 커넥션이 누적되고 DB 쪽 슬롯·메모리가 임계에 닿는다.
CAS 에 올려 두고 CAS 액션으로 처리하면 커넥션 관리를 CAS 가 맡고 왕복이 사라지므로 같은 동시성에서도 잘 버틴다. 대량·동시·반복 조회를 CAS 경유로 권장하는 이유다.
| 방향 | 내용 |
|---|---|
| DB 유휴 커넥션 수명 단축 | wait_timeout 을 운영에 맞게 줄여 누적을 끊는다. DB 팀과 합의해 정한다 |
| 커넥션 재사용 정리 | LIBNAME 에서 세션 단위 연결을 명시적으로 끊도록 구성한다 |
| CAS 경유로 전환 | 자주 쓰는 데이터는 CASLIB 로 적재하고 CAS 액션으로 조회한다 |
| 동시성 제한 | 배치·큐잉으로 같은 쿼리의 동시 실행을 줄인다 |