refactor: 문서 개선 중

This commit is contained in:
donghyeon-ka
2026-09-21 14:30:55 +09:00
parent c93cdea150
commit 805a18f486
1497 changed files with 525837 additions and 59152 deletions
@@ -35,7 +35,7 @@ source:
<!-- body:start -->
`REQUIRES_NEW`는 바깥 트랜잭션의 커넥션을 **핀한 채로** 새 물리 JDBC 커넥션을 딴다. 그래서 풀 사이징 제약이 곱셈이 된다 — `maximumPoolSize >= (concurrent_threads × (1 + max_inNew_depth)) + 1`.
`REQUIRES_NEW`는 바깥 트랜잭션의 리소스를 유지한 채 독립적인 inner transaction 리소스를 요구할 수 있다. 이 프로젝트는 그 concurrency model을 기준으로 `maximumPoolSize >= (concurrent_threads × (1 + max_inNew_depth)) + 1`을 보수적 sizing rule로 사용한다. Spring API 전체에 성립하는 보편 법칙으로 읽어서는 안 된다.
## 커넥션 비용이 곱셈이 되는 이유
@@ -44,7 +44,7 @@ source:
## 레코드마다 inNew 를 도는 루프가 금지인 이유
풀 고갈과 데드락이다.
모든 worker가 outer connection을 잡은 채 inner connection을 기다리고 추가 여유가 없을 때 pool exhaustion이 생기며, 대기가 서로의 반납을 전제로 하면 교착 형태로 진행할 수 있기 때문이다.
## 같은 곱셈 함정이 database-per-tenant에서 반복된다
@@ -70,13 +70,11 @@ source:
maxPoolSize >= concurrent_threads * (1 + max_inNew_depth) + 1
```
중첩 깊이 1 이면 스레드당 두 커넥션이다. 동시 스레드가 100 이면 최소 201 이 필요하다.
이 프로젝트가 가정한 모델에서 중첩 깊이 1이면 worker 하나가 outer와 inner connection을 동시에 필요로 할 수 있다. 예를 들어 동시 worker 100을 최대 동시성으로 잡고 여유 1을 두는 이 규칙이라면 201을 산정한다. 실제 필요한 값은 transaction manager 동작과 workload의 동시성으로 검증해야 한다.
## 지켜지지 않으면 데드락이
## 여유가 없으면 pool exhaustion과 교착 위험이 생긴
모든 스레드가 바깥 커넥션을 잡고 안쪽 커넥션을 기다린다. 아무도 반납하지 않으므로 전부 풀 획득 타임아웃까지 대기한다.
이 상태는 부하가 임계를 넘는 순간 한꺼번에 나타난다. 그 전까지는 아무 증상이 없다.
모든 worker가 바깥 커넥션을 잡고 안쪽 커넥션을 기다리는 동시에 pool에 남은 connection이 없으면 획득 대기가 누적된다. 이 대기가 서로가 반납해야 할 connection을 기다리는 구조가 되면 acquisition timeout과 교착 형태로 이어질 수 있다. 실제 발생 여부와 임계점은 workload와 pool 설정으로 확인해야 한다.
## 풀 사이징의 다른 근거와 충돌한다
@@ -92,13 +90,13 @@ test). Fixed-size pool recommended (minimumIdle = maximumPoolSize).
:::warning
근거가 같은 손잡이를 반대 방향으로 민다. 작은 풀 공리는 값을 줄이라 하고 중첩 하한은 늘리라 한다. 해소하는 방법은 풀을 키우는 것이 아니라 중첩 깊이를 줄이는 것이다.
기준은 서로 다른 질문에 답한다. 일반적인 pool sizing은 불필요하게 큰 pool을 피하려는 기준이고, 중첩 transaction 규칙은 특정 동시성에서 추가 connection 수요가 생길 수 있음을 반영한다. 먼저 불필요한 `REQUIRES_NEW` 중첩을 줄이고, 남은 동시성 모델을 부하 테스트로 확인한 뒤 `maximumPoolSize`를 정한다.
:::
## 고정 크기 풀
최소 유휴를 최대 크기와 같게 두는 것을 권장한다. 풀이 줄었다가 늘어나는 동안 중첩 하한이 일시적으로 깨지는 것을 막는다.
`minimumIdle = maximumPoolSize`인 fixed-size 설정은 connection creation 지연을 피하고 응답성을 예측하기 쉽게 하려는 운영 선택이다. `minimumIdle`이 더 작다고 `maximumPoolSize` 용량 자체가 사라지는 것은 아니다. `REQUIRES_NEW` 안전 여유는 `maximumPoolSize`와 실제 concurrency model로 판단한다.
## 멀티테넌시에서의 확장