Django
はデフォルトでクエリが即座にコミットされるんですが、それだと処理中に例外が発生した場合などにロールバックされず、データの整合性を保つことができなくなることがあります。データの整合性を保つために、1つのリクエストの処理を1つのトランザクションにまとめるための設定方法を説明したいと思います。
前提条件
- Python : 3.8.2
- Django : 3.0.8
実装方法
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'db',
'USER': 'root',
'PASSWORD': 'root',
'HOST': '127.0.0.1',
'PORT': '3306',
'ATOMIC_REQUESTS': True, # 追加
}
}
setting.py
の DATABESES
に 'ATOMIC_REQUESTS': True
を追加します。
これで一つのリクエストの開始から終了までを一つのトランザクションにまとめることができます。リクエスト内で複数のクエリ実行時に途中で例外が発生した場合、ロールバックされ途中までの処理はなかったことになります。
注意点
ATOMIC_REQUESTS
を設定する方法では View
関数の処理だけがトランザクションとしてまとめられるので、ミドルウェアなどは対象外となります。
トランザクションを個別に設定する
ATOMIC_REQUESTS
を使用せず、各処理毎に個別にトランザクションを設定したい場合は @transaction.atomic
を使用します。
from django.db import transaction
@transaction.atomic
def viewfunc(request):
foo()
with 文を使用してトランザクションを設定する
with
文を使用してトランザクションを設定することもできます。
from django.db import transaction
def viewfunc(request):
foo() # このコードは即時コミットされます
with transaction.atomic():
# このブロックの中は1つのトランザクションとして扱われます
bar()
最後に
システム開発していると1リクエストで複数のレコードの更新や複数のテーブルにデータを追加・編集することもよくあると思います。そういう場合、トランザクションを設定し例外発生時にはロールバックさせることでデータの整合性を保つことが必要になってくると思います。適切にトランザクションを設定し、データの整合性のあるシステムを開発したいですね。
コメント