programing

SQL 화학: 만들기 vs.세션 재사용

newstyles 2023. 7. 18. 21:36

SQL 화학: 만들기 vs.세션 재사용

간단한 질문입니다. SQL 화학은 전화에 대해 이야기합니다.sessionmaker()한 번이지만 결과를 부르는Session()DB와 대화해야 할 때마다 클래스를 지정합니다.나에게 그것은 내가 첫번째를 하는 두번째를 의미합니다.session.add(x)아니면 비슷한 것을 먼저 할 것입니다.

from project import Session
session = Session()

지금까지 제가 한 일은 전화를 거는 것이었습니다.session = Session() 모델에서 한 번만 실행한 다음 항상 같은 세션을 내 응용 프로그램의 모든 위치에 가져옵니다.이것은 웹 애플리케이션이므로 일반적으로 동일한 의미를 갖습니다(한 뷰가 실행되는 것처럼).

하지만 어디가 다른가요?내 기능이 완료될 때까지 항상 하나의 세션을 데이터베이스 작업에 사용하지 않고 다음 번에 DB와 대화할 때 새로운 세션을 만드는 것의 단점은 무엇입니까?

여러 개의 스레드를 사용할 경우 각각의 세션이 필요하다는 것을 알게 되었습니다.하지만 사용하기scoped_session()저는 이미 그 문제가 존재하지 않는지 확인했습니다, 그렇죠?

제 추측 중 틀린 것이 있다면 명확히 해주세요.

sessionmaker()공장입니다. 새로운 생성을 위한 구성 옵션을 배치하도록 장려하기 위해 있습니다.Session한 곳에 있는 물건들.그것은 선택 사항입니다. 당신이 쉽게 전화할 수 있습니다.Session(bind=engine, expire_on_commit=False)언제든지 새로운 것이 필요할 때Session그것이 장황하고 중복된다는 것을 제외하고, 저는 각각 이 중복 문제에 새롭고 더 혼란스러운 방식으로 접근한 소규모 "도우미"의 확산을 멈추고 싶었습니다.

그렇게sessionmaker()생성을 지원하는 도구일 뿐입니다.Session필요할 때 사용할 수 있습니다.

다음 파트.제 생각에 문제는, 새로운 것을 만드는 것과 무엇이 다른가 하는 것입니다.Session()하나를 계속 사용하는 것과 비교하여 다양한 지점에서.답은 많지 않습니다. Session는 입력한 모든 개체에 대한 컨테이너이며 열린 트랜잭션도 추적합니다.당신이 전화하는 그 순간에rollback()또는commit()거래는 끝났고, 그리고.SessionSQL을 다시 내보내는 호출이 있을 때까지 데이터베이스에 연결되지 않습니다.매핑된 개체에 대한 링크는 개체가 보류 중인 변경 사항을 제거하면 참조하기가 매우 약합니다. 따라서 이러한 점에서도Session응용 프로그램이 매핑된 개체에 대한 모든 참조를 잃게 되면 새 상태로 다시 비워집니다.기본값으로 유지하는 경우"expire_on_commit"설정하면 커밋 후 모든 개체가 만료됩니다.에 그 에약Session5분 또는 20분 동안 어슬렁거리다가 다음 번에 사용할 때 데이터베이스에서 모든 종류의 것이 변경되면 20분 동안 메모리에 저장되어 있음에도 불구하고 다음 번에 해당 개체에 액세스할 때 완전히 새로운 상태가 로드됩니다.

웹 애플리케이션에서, 우리는 보통 이렇게 말합니다. 여러분은 왜 새로운 것을 만들지 않습니까?Session동일한 요청을 반복적으로 사용하는 대신 각 요청에 대해 사용합니다.이렇게 하면 새 요청이 "정리"를 시작할 수 있습니다.이전 요청의 일부 개체가 아직 수집되지 않았으며 사용자가 해제한 경우"expire_on_commit"아마도 이전 요청의 어떤 상태가 여전히 남아 있을 것이고, 그 상태는 심지어 꽤 오래되었을 수도 있습니다.당신이 떠나는 것을 조심한다면,expire_on_commit전원이 켜져 있고 확실히 전화하기 위해.commit()또는rollback()요청이 끝나면 괜찮지만, 만약 당신이 새로운 것으로 시작한다면.Session당신이 깨끗하게 시작하는 것에 대해 의문의 여지가 없습니다. 래서각요청새로 .Session새로운 시작을 확실히 하고 사용할 수 있는 가장 간단한 방법입니다.expire_on_commit이 는 이플래호출을작업많에은추가 SQL수때거있사다항을 호출하는 에 많은 추가 할 수 입니다.commit()질문에 답인지 .이것이 당신의 질문에 대한 답인지 확실하지 않습니다.

다음 라운드는 스레드화에 대해 언급한 내용입니다.만약 당신의 앱이 멀티스레드라면, 우리는 그것을 확인하는 것을 추천합니다.Session 입니다.뭔가. scoped_session()기본적으로 현재 스레드에 로컬로 설정됩니다.웹 앱에서, 요청에 대한 로컬은 사실 훨씬 더 좋습니다. 라크스-SQ "scope function을 LAlchemy에 .scoped_session()요청 범위 세션을 얻을 수 있습니다.평균 피라미드 응용프로그램은 세션을 "요청" 레지스트리에 고정합니다.이러한 체계를 사용할 때 "요청 시 새 세션 만들기" 아이디어는 계속해서 문제를 해결하는 가장 간단한 방법처럼 보입니다.

탁월한 zzeek의 답변 외에도 일회용 자체 폐쇄 세션을 빠르게 만들 수 있는 간단한 방법이 있습니다.

from contextlib import contextmanager

from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session, sessionmaker

@contextmanager
def db_session(db_url):
    """ Creates a context with an open SQLAlchemy session.
    """
    engine = create_engine(db_url, convert_unicode=True)
    connection = engine.connect()
    db_session = scoped_session(sessionmaker(autocommit=False, autoflush=True, bind=engine))
    yield db_session
    db_session.close()
    connection.close()

용도:

from mymodels import Foo

with db_session("sqlite://") as db:
    foos = db.query(Foo).all()

언급URL : https://stackoverflow.com/questions/12223335/sqlalchemy-creating-vs-reusing-a-session