- 공유 링크 만들기
- X
- 이메일
- 기타 앱
- 공유 링크 만들기
- X
- 이메일
- 기타 앱
Django에서 트랜잭션 관리하기
안녕하세요! 오늘은 Django에서 데이터베이스 트랜잭션을 효과적으로 관리하는 방법에 대해 알아보겠습니다.
1. 트랜잭션의 중요성
트랜잭션은 데이터베이스의 일관성과 무결성을 보장하는 중요한 개념입니다. Django에서는 여러 가지 방법으로 트랜잭션을 관리할 수 있습니다.
1.1 기본 개념
- 원자성(Atomicity): 트랜잭션은 모두 실행되거나 모두 실행되지 않아야 합니다.
- 일관성(Consistency): 트랜잭션 전후로 데이터베이스의 일관성이 유지되어야 합니다.
- 격리성(Isolation): 동시에 실행되는 트랜잭션들이 서로 영향을 주지 않아야 합니다.
- 지속성(Durability): 완료된 트랜잭션의 결과는 영구적으로 저장되어야 합니다.
2. Django의 트랜잭션 관리
2.1 기본 설정
# settings.py
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'mydatabase',
'USER': 'myuser',
'PASSWORD': 'mypassword',
'HOST': 'localhost',
'PORT': '5432',
'ATOMIC_REQUESTS': True, # 모든 뷰를 트랜잭션으로 래핑
}
}
2.2 데코레이터 사용
from django.db import transaction
@transaction.atomic
def create_order(user, items):
order = Order.objects.create(user=user)
for item in items:
OrderItem.objects.create(
order=order,
product=item.product,
quantity=item.quantity
)
return order
3. 트랜잭션 격리 수준
3.1 격리 수준 설정
# settings.py
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'OPTIONS': {
'isolation_level': 'READ COMMITTED', # 기본값
}
}
}
3.2 격리 수준 종류
- READ UNCOMMITTED: 다른 트랜잭션의 커밋되지 않은 변경사항을 읽을 수 있습니다.
- READ COMMITTED: 커밋된 변경사항만 읽을 수 있습니다.
- REPEATABLE READ: 트랜잭션 내에서 동일한 쿼리는 항상 같은 결과를 반환합니다.
- SERIALIZABLE: 가장 엄격한 격리 수준으로, 동시성 문제를 완전히 방지합니다.
4. 고급 트랜잭션 관리
4.1 중첩 트랜잭션
@transaction.atomic
def process_order(order_id):
order = Order.objects.select_for_update().get(id=order_id)
try:
with transaction.atomic():
# 재고 확인
for item in order.items.all():
if item.product.stock < item.quantity:
raise InsufficientStockError()
item.product.stock -= item.quantity
item.product.save()
except InsufficientStockError:
# 외부 트랜잭션은 계속 진행
order.status = 'failed'
order.save()
raise
4.2 저장점(Savepoint) 사용
@transaction.atomic
def complex_operation():
# 첫 번째 작업
obj1 = Model1.objects.create()
# 저장점 생성
sid = transaction.savepoint()
try:
# 두 번째 작업
obj2 = Model2.objects.create()
# 세 번째 작업
obj3 = Model3.objects.create()
except Exception:
# 두 번째와 세 번째 작업 롤백
transaction.savepoint_rollback(sid)
raise
5. 동시성 제어
5.1 낙관적 락(Optimistic Locking)
class Product(models.Model):
name = models.CharField(max_length=100)
stock = models.IntegerField()
version = models.IntegerField(default=0)
def save(self, *args, **kwargs):
self.version += 1
super().save(*args, **kwargs)
def update_stock(product_id, quantity):
product = Product.objects.get(id=product_id)
old_version = product.version
# 재고 업데이트
product.stock -= quantity
product.save()
# 버전 확인
if Product.objects.filter(id=product_id, version=old_version).exists():
return True
else:
raise ConcurrentModificationError()
5.2 비관적 락(Pessimistic Locking)
def process_order(order_id):
with transaction.atomic():
# 행 수준 락
order = Order.objects.select_for_update().get(id=order_id)
# 주문 처리
order.status = 'processing'
order.save()
# 주문 항목 처리
for item in order.items.all():
product = Product.objects.select_for_update().get(id=item.product_id)
if product.stock >= item.quantity:
product.stock -= item.quantity
product.save()
else:
raise InsufficientStockError()
6. 실전 예제
6.1 주문 처리 시스템
class OrderService:
@transaction.atomic
def create_order(self, user, items):
# 주문 생성
order = Order.objects.create(
user=user,
status='pending'
)
# 주문 항목 생성
for item in items:
OrderItem.objects.create(
order=order,
product=item.product,
quantity=item.quantity,
price=item.product.price
)
# 결제 처리
try:
payment = PaymentService.process_payment(order)
order.status = 'paid'
order.save()
return order
except PaymentError:
order.status = 'failed'
order.save()
raise
6.2 재고 관리 시스템
class InventoryService:
@transaction.atomic
def update_stock(self, product_id, quantity):
product = Product.objects.select_for_update().get(id=product_id)
if product.stock + quantity < 0:
raise InsufficientStockError()
product.stock += quantity
product.save()
# 재고 변경 이력 기록
StockHistory.objects.create(
product=product,
quantity=quantity,
new_stock=product.stock
)
7. 주의사항
- 트랜잭션 범위: 너무 큰 트랜잭션은 성능에 영향을 줄 수 있습니다.
- 데드락: 여러 트랜잭션이 서로를 기다리는 상황을 주의해야 합니다.
- 롤백: 예외 처리를 통해 적절한 롤백이 이루어지도록 해야 합니다.
- 성능: 트랜잭션 격리 수준이 높을수록 성능에 영향을 줄 수 있습니다.
결론
Django의 트랜잭션 관리 기능을 잘 활용하면 데이터의 일관성과 무결성을 보장할 수 있습니다. 적절한 트랜잭션 전략을 선택하고, 동시성 문제를 고려하여 안정적인 애플리케이션을 개발할 수 있습니다. 추가적인 질문이나 궁금한 점이 있으시면 댓글로 남겨주세요!
- 공유 링크 만들기
- X
- 이메일
- 기타 앱
댓글
댓글 쓰기