본문 바로가기

# Development/Database

[SQLAlchemy] 트랜잭션(transaction) 관리: add, flush, commit 메서드의 활용

트랜잭션(transaction) 관리: add, flush, commit 메서드의 활용

 

SQLAlchemy는 Python으로 데이터베이스와 상호작용하는 데 사용되는 강력하고 유연한 ORM(Object-Relational Mapping) 라이브러리다.  SQLAlchemy로 데이터베이스 객체를 다룰 때 가장 신경써야 하는 부분은 트랜잭션(Transaction)이다. 트랜잭션 관리를 위해 SQLAlchemy의 메서드 add, delete, flush, commit을 어떻게 사용해야 하는지 알아보자.
 

트랜잭션(Transaction)

트랜잭션은 데이터베이스의 일관성 유지를 위한 작업 단위를 나타낸다.
 
이 작업들은 성공적으로 완료되거나 혹은 실패할 수 있는 논리적인 작업의 단위이다.
 
트랜잭션 내의 작업이 모두 성공하면 commit되어 데이터베이스에 반영되고,
하나라도 실패 할 경우 이전 상태로 rollback되어 해당 트랜젝션 이전 상태로 돌아간다.
 
데이터베이스 조작의 일관성을 보장하고 데이터베이스의 원자성을 유지하는 데 중요한 역할을 한다.
 

SQLAlchemy 매서드

add

add 메서드는 SQLAlchemy 세션에 새로운 객체를 추가한다.
이때 세션에 추가된 객체는 아직 데이터베이스에 반영되지 않은 상태이다.

from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base

# 엔진 생성 및 연결
engine = create_engine('sqlite:///mydatabase.db')

# 세션 생성
Session = sessionmaker(bind=engine)
session = Session()

Base = declarative_base()

class User(Base):
    __tablename__ = 'users'
    id = Column(Integer, primary_key=True)
    name = Column(String)

# 새로운 User 객체 생성 및 세션에 추가
new_user = User(name='John')
session.add(new_user)

 

🔮 SqlAlcemy 세션이란?
SQLAlchemy에서 트랜잭션을 관리하는 추상화된 객체이며, 한 세션에 어러개의 트랜잭션을 관리 할 수 있다.
더 자세한 사항은 공식 문서에 작성된 Session 페이지에서 확인 할 수 있다.
 

Session Basics —     SQLAlchemy 1.3 Documentation

Session Basics What does the Session do ? In the most general sense, the Session establishes all conversations with the database and represents a “holding zone” for all the objects which you’ve loaded or associated with it during its lifespan. It pro

docs.sqlalchemy.org

 

flush

flush 메서드는 세션에 대기 중인 모든 변경 사항을 데이터베이스에 적용한다. 

 이때 데이터베이스에 레코드가 삽입, 수정 또는 삭제된다.
flush는 데이터베이스와 상호작용하지만 트랜잭션을 커밋하지 않는다.

session.flush()

 

commit

commit 메서드는 데이터베이스에 반영된 모든 변경사항을 영구적으로 저장한다. 

session.commit()

 

flush는 언제 사용하지?

add세션에 객체를 추가하고(insert) 마지막에 commit을 한다면, flush는 굳이 사용안해도 되지 않을까? 라는 생각이 들 수 있다. 하지만 서로 다른 클래스 객체에 대해서 add 된 내용이 commit 될 때 순서가 보장되지 않기 때문 중간에 flush를 통해 트랜잭션 순서를 보장해줘야 한다.
 
예를 들어 FK가 걸려있는 여러 테이블 객체를 다룰 때, user 객체를 먼저 생성하고 id 컬럼을 payment 객체 에서 FK로 사용하는 상황에서 flush 없이 user와 payment 객체를 추가하는 작업을 진행하면 아래와 같은 에러를 만날 가능성이 크다.

sqlalchemy.exc.IntegrityError: (mysql.connector.errors.IntegrityError) 1452 (23000): 
Cannot add or update a child row: a foreign key constraint fails

 
사실 sqlalchemy의  sessionmaker 정의를 살펴보면 autoflush가 True로 설정되어 있다.

class sqlalchemy.orm.sessionmaker(bind=None, class_=<class 'sqlalchemy.orm.session.Session'>, 
autoflush=True, autocommit=False, expire_on_commit=True, info=None, **kw)

 
그렇기 때문에 따로 초기 값을 변경하지 않는 이상 session.flush()를 하지 않아도 트랜잭션 순서가 데이터베이스에 적용된다. 하지만 명시적으로 flush()를 사용하는 것은 코드의 가독성과 안정성을 높이는 데 도움이 된다. 언제 세션에서 변경사항을 데이터베이스에 반영할지를 명시할 수 있기 때문이다. 
 

마무리

SQLAlchemy의 add, flush, commit 메서드는 데이터베이스 트랜잭션(Transaction)을 효과적으로 관리하고 조절하는데 중요한 역할을 한다. add 메서드로 세션에 객체를 추가하고, flush 메서드로 변경 사항을 데이터베이스에 반영하며, commit 메서드로 변경 사항을 영구적으로 저장한다.

이러한 메서드들을 잘 활용하면 데이터의 일관성과 안전성을 보장한다. 데이터베이스 트랜잭션을 안전하게 관리할 수 있다. 하지만 각각의 특성을 알지 못하고 사용하면 백엔드 개발 과정에서 트랜잭션과 관련된 에러를 꽤나 마주칠 수 있다.
 
메서드 들을 잘 활용 할 수 있도록 좀 더 공부하고 싶다면 앞서 언급한 SQLAlchemy 공식 문서들을 참고하면 좋다.

 

SQLAlchemy Documentation —     SQLAlchemy 1.3 Documentation

SQLAlchemy Documentation Getting Started A high level view and getting set up. Overview | Installation Guide | Frequently Asked Questions | Migration from 1.2 | Glossary | Error Messages | Changelog catalog SQLAlchemy ORM Here, the Object Relational Mapper

docs.sqlalchemy.org

 

Flask-SQLAlchemy — Flask-SQLAlchemy Documentation (3.1.x)

 

flask-sqlalchemy.palletsprojects.com