Python/sqlalchemy

SQLAlchemy Session과 AsyncSession은 synchronizable한 객체일까?

검정비니 2024. 2. 23. 14:15
728x90
반응형

SQLAlchemy에서 세션은 단일 데이터베이스 트랜잭션을 나타내는 변경 가능한 상태 저장 객체이다.

따라서 세션 객체는 신중한 동기화 없이는 동시 스레드 또는 비동기 작업 간에 공유할 수 없다.

세션은 non-concurrent 방식으로 (즉 특정 Session 객체는 한 번에 하나의 스레드 또는 작업에서만) 사용되어야 한다.

 

SQLAlchemy의 asyncio 확장 기능에서 AsyncSession 객체를 사용하는 경우, 이 객체는 Session 객체를 기반으로 만들어지는 단순한 프록시일 뿐이며 동일한 규칙이 적용된다.

AsyncSession은 동기화되지 않고 mutable(변경 가능)한 stateful한 특성을 가지는 객체이므로 여러 asyncio 작업에서 단일 인스턴스의 AsyncSession을 한 번에 사용하는 것은 안전하지 않다.

 

트랜잭션 내의 데이터베이스 연결은 비동시적이고 순차적인 방식으로 작동하도록 설계된 상태 저장 객체이기도 하다.

쿼리는 connection에서 순서대로 실행되며, 데이터베이스 서버는 명령이 실행되는 정확한 순서대로 처리한다.

세션이 이 연결에서 명령을 내보내고 결과를 수신할 때 세션 자체는 이 연결에 존재하는 명령 및 데이터의 상태와 일치하는 내부 상태 변경, 즉 트랜잭션이 시작, 커밋 또는 롤백되었는지 여부, 작동 중인 세이브포인트가 있는지 여부, 로컬 ORM 맵 객체와 개별 데이터베이스 행의 상태의 세분화된 동기화 등을 통해 전환된다.

 

동시성을 위해 데이터베이스 애플리케이션을 설계할 때 적절한 모델은 각 동시 작업/스레드가 자체 데이터베이스 트랜잭션과 함께 작동하는 모델이다.

그렇기 때문에 데이터베이스 동시성 문제를 논의할 때 사용되는 표준 용어는 다중 동시 트랜잭션이다.

기존 RDMS에서는 여러 명령을 동시에 수신하고 처리하는 단일 데이터베이스 트랜잭션에 대한 아날로그가 없었다.

 

따라서 SQLAlchemy의 세션과 AsyncSession의 동시성 모델은 스레드당 세션, task당 AsyncSession이다.

여러 스레드를 사용하는 애플리케이션 또는 asyncio.gather()와 같은 API를 사용할 때와 같이 비동기 작업에서 여러 작업을 사용하는 애플리케이션은 각 스레드에 자체 Session이 있고 각 비동기 작업에 자체 AsyncSession이 있는지 확인하고 싶을 것이다.

이 사용을 보장하는 가장 좋은 방법은 스레드 또는 태스크 내부의 최상위 파이썬 함수 내에서 로컬로 표준 컨텍스트 관리자 패턴을 사용하여 세션 또는 AsyncSession의 수명이 로컬 범위 내에서 유지되도록 하는 것입니다.

 

반응형