経緯
最近通勤中に読んでる以下の書籍から学んだことをピックアップします。
https://www.amazon.co.jp/%E7%8F%BE%E5%A0%B4%E3%81%A7%E4%BD%BF%E3%81%88%E3%82%8B-Django-%E3%81%AE%E6%95%99%E7%A7%91%E6%9B%B8%E3%80%8A%E5%9F%BA%E7%A4%8E%E7%B7%A8%E3%80%8B-%E6%A8%AA%E7%80%AC-%E6%98%8E%E4%BB%81/dp/4802094744
DjangoのデフォルトのDBトランザクション
Djangoではモデルクラスのモデルマネージャ(objects)を経由してDBとクエリ(SQL文)をやり取りします。
そして、モデルマネージャでクエリを実行した場合、発行されたSQLがDDLであったとしてもその時点でDBに反映(commit)されるとのことです。
これは存じておりませんでした。。
極端な例ですが、以下のようになるそうです。
# import省略
def update(request):
# 処理省略
TableA.objects.save() # この時点でコミット
TableB.objects.delete() # この時点でコミット
raise Exception # 例外発生
# ここまでに実行されたクエリはテーブルへ反映済み。ロールバックされない。
# 処理省略
しかし、settings.pyの「DATABASES」にプロパティを追加すると挙動が変わるとのことです。
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'mydb',
'USER': 'root',
'PASSWORD': '',
'HOST': '127.0.0.1',
'PORT': '3306',
'ATOMIC_REQUESTS': True, # これを追加
}
}
上記設定により1リクエスト単位でトランザクションが管理されるようになります。
# import省略
def update(request):
# 処理省略
TableA.objects.save()
TableB.objects.delete()
# 処理省略
# リクエスト内で例外が発生しなかった場合はトランザクションがcommitされる
まとめ
今後、ログ出力機能を現在開発中のアプリケーションに埋め込んで実際に挙動が変化する旨を確認してみようと思います。
本日は書き溜めのみ。