SQLAlchemy

SQLAlchemy

SQLAlchemy는 Python에서 사용되는 강력하고 유연한 SQL 툴킷 및 객체 관계 매핑(Object-Relational Mapping, ORM) 라이브러리이다. 이 라이브러리는 데이터베이스와의 상호 작용을 쉽고 효율적으로 만들어 주며, SQL과 객체 지향 프로그래밍 사이의 간격을 줄여 준다.

주요 특징

  • ORM 레이어: Python 클래스를 데이터베이스 테이블에 매핑하고, Python 객체를 해당 테이블의 행과 동기화한다. 이를 통해 SQL 쿼리를 직접 작성하지 않고도 데이터베이스 작업을 할 수 있다.
  • SQL 표현 언어: 복잡한 SQL 쿼리를 Python 코드로 작성할 수 있는 선언적 방식을 제공한다. 이를 통해 데이터베이스와의 상호작용을 보다 세밀하게 제어할 수 있다.
  • 데이터페이스 독립성: SQLAlchemy는 다양한 데이터베이스 엔진을 지원한다. SQLite, PostgreSQL, MySQL, Oracle, Microsoft SQL Seerver 등과 같은 주요 데이터베이스에 모두 호환된다.
  • 트랜잭션 관리: 세선 기반의 작업을 통해 트랜잭션 관리를 쉽게 할 수 있으며, 데이터베이스 연결과 트랜잭션의 생명 주기를 효율적으로 관리한다.
  • 유연성 및 확장성: 다양한 사용 사례와 요구 사항에 맞게 SQLAlchemy를 확장하고 맞춤화할 수 있다.

예제 코드

from sqlalchemy import create_engine, Column, Integer, String, MetaData, Table

# SQLite 데이터베이스에 연결 및 메타데이터 객체 생성
engine = create_engine('mysql+pymysql://<USERNAME>:<PASSWORD>@{HOST}:{PORT}/<DBNAME>', echo=True)
metadata = MetaData()

# 테이블 정의 및 생성

users = Table('users', meatdata,
			Column('id', Integer, primary_key=True),
			Column('name', String),
			Column('age', Integer)
		)
metadata.create_all(engine)

SQLAlchemy는 그 유연성과 강력한 기능으로 인해 Python 개발자들 사이에서 데이터베이스 작업에 대한 선호도가 높은 라이브러리이다. 데이터베이스 작업을 Pythonic하게 만들어 주며, 복잡한 쿼리와 데이터베이스 상호작용을 보다 쉽게 할 수 있게 도와준다.

SQLAlchemy 기본 객체

engine

데이터베이스와의 연결을 관리 (URL 형식의 DB 접근 주소를 필요로 함 (create_engine))

from sqlalchemy import create_engine

# 1. engein 생성
engine = create_engine(
	'mysql+pymysql://<USERNAME>:<PASSWORD>@{HOST}:{PORT}/<DBNAME>',
	echo=True,
	pool_size=2,
	pool_recycle=3600,
	max_overflow=0,
	pool_timeout=3,
	isolation_level='READ UNCOMMITTED'
)

create_engine

  • echo
    • log 기록
  • pool_size
    • 연결 풀 내에서 도시에 유지할 연결의 최대 수 (0: 무제한)
  • pool_recycle
    • MySQL/MariaDB의 고정된 기간 동안 유휴 상태였던 연결에 대해 자동 연결 종료 (기본갑 8시간) 자동으로 삭제 처리 되려면, 명시적인 값 설정 필요
  • max_overflow
    • 풀에 있는 연결의 최대 추가 갯수
  • pool_timeout
    • 연결 풀에서 연결을 가져오기 위해 대기할 최대 시간
  • isolation_level
    • 트랜잭션 격리 수준 설정

isolation 관련

  • create_engine.isolation_level의 인수를 통한 설정 방법 외에도 Connection.execution.options.isolation_elvel를 통한, 연결 마다의 설정도 가능
  • READ COMMITED, READ UNCOMMITTED, REPEATABLE READ, SERIALIZABLE, AUTOCOMMIT 레벨들이 있음

engine.dispose()

  • engine에서 가진 connection pool 자체를 다 종료한다.

Base

Base 클래스의 역할은 모든 ORM 모델의 기반으로 declarative_base() 함수를 통해 호출하여 생성되며 모든 모델은 이 Base 클래스를 상속 받아야 한다. Base를 상속받은 각 모델은 테이블의 구조(이름, 컬럼, 데이터 타입 등)를 정의한다.

from sqlalchemy.orm import declarative_base
from sqlalchemy import Column, Integer, String

# 2. Base: 모든 모델의 기본 클래스
Base = declarative_base()

class User(Base):
	__tablename__ = "users"
	id = Column(Integer, primary_key=True, autoincrement=True)
	name = Column(String(50), nullable=False)
	age = Column(Integer, nullable=False)

MetaData

SQLAlchemy에서 데이터베이스의 스키마(테이블, 컬럼, 인덱스, 제약조건, 관계 등) 정보를 저장하고 관리하는 객체이다. Base를 상속받아 생성된 모델들의 정보를 담고 있다. Base 클래스가 생성될 때 자동으로 MetaData 객체도 생성되며, 모든 모델 클래스들이 MetaData에 등록된다. 이를 통해 전체 데이터베이스 구조를 관리할 수 있게 된다.

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Colun, Integer, String

# 2. Base: 모든 모델의 기본 클래스
Base = declarative_base()

# 3.1 Base.metamdata: 각 모델에 대한 메타 정보
print(Base.metadata.tables)   # 테이블 정보 출력

# immutabledict({
	 # 'users': 
		 # Table('users', 
			 # MetaData(bind=None), 
			 # Column('id', Integer(), table=<users>, primary_key=True, nullable=False), 
			 # Column('name', String(), table=<users>), 
			 # Column('age', Integer(), table=<users>), schema=None) 
 # }) 
 
 # 3.2 Base.metadata의 정보를 바탕으로 engine에 연결된 DB에 테이블 생성
 Base.metadata.create_all(engine)

sessionmaker, Session

세션은 데이터베이스 엔진과 연결되어 해당 DB의 트랜잭션을 관리하고, 데이터베이스 간의 변경사항을 추적하는 중요한 역할을 한다. sessionmaker를 사용해 session 팩토리 생성한다. 최종 세션 객체 Session()을 생성하고, DB에 대한 조회, 삽입, 갱신, 삭제 등을 수행한다.

from sqlalchemy.orm import sessionmaker

# 1. 데이터베이스 엔진 생성 
engine = create_engine('sqlite:///example.db') 

# 2. Base를 이용한 모델 정의와 3. meta를 이용한 테이블 생성은 생략

 # 4.1 sessionmaker를 사용해 세션 팩토리 생성 
 Session = sessionmaker(bind=engine) 

 # 4.2 세션 객체 생성 - DB에 대한 쿼리, 삽입, 갱신 등을 수행 
 session = Session()

session의 재사용

Session은 내부적으로 데이터베이스 연결을 풀(connection pool)에서 가져와 사용하고, 작업이 끝나면 풀에 반환한다.

Session.close()

  • pool에 있는 세션을 사용하다가, 다시 반환하는 것이다.
  • ORM 객체 해제: 세션이 관리하고 있는 ORM 객체에 대한 “관리 상태”를 해제하여, 세션이 해당 객체의 변경 사항을 추적하지 않음을 의미한다.
  • 세션 상태 초기화: Session은 내부적으로 사용된 리소스와 캐시를 정리한다.
  • session.close()를 하더라도 객체는 여전히 존재하며, 필요할 때 다시 사용 가능하다.
  • session.close()를 호출 후 세션 객체를 재사용하여 새 쿼리를 실행하거나 트랜잭션을 시작한다면 세션은 pool에서 새 연결을 가져와 데이터베이스와 통신한다.

즉 세션은 DB와의 연결을 완전히 닫는 것이 아닌 재사용 가능한 상태로 만든다는 것이다.

만약 connection pool까지 종료하려면? engine.dispose()

# 세션 생성
session = Session()

# 데이터베이스 작업 수행
user = session.query(User).first()

# 세션 닫기
session.close()

# 세션을 다시 사용하여 새 쿼리 수행
another_user = session.query(User).first()   # 재사용 가능

출처: https://wikidocs.net/226764, https://yubi5050.tistory.com/317

* TOC {:toc}

© 2021. All rights reserved.