SQLAlchemyのセッション

SQLAlchemyを使っていてセッションとコネクションがわからなかったのでまとめました。

(記事中に間違いなどあれば是非コメントでお知らせ願えたらありがたいです)

定義の再確認

セッション(Session)
データベースとの論理的な接続
データベースとの通信のための情報(ログイン情報や現在のトランザクションレベル)を保持している
コネクション(Connection)
データベースとの低レベルプロトコルを用いた物理的な接続

備考

  • コネクションは複数のセッションを持つことができる
  • セッションは複数のトランザクションにまたいで寿命を存続できる

普通はコネクションで一つのセッションを持つようにするらしい。

セッションをいつ開始・終了するか

セッションをいつ開始・終了するかについてはいくつかのパターンがある。

WEBアプリでの場合

典型的なWEBアプリでは、WEBクライアントからのリクエストごとにセッションの開始・終了を行う。

つまり、リクエストの寿命 = セッションの寿命となる。

いくつかのPythonのWAFではセッションの寿命を制御してくれる統合ライブラリを提供していて、可能ならばそれらの使用を推奨するとのこと。

(FlaskならばFlask-SQLAlchemy、PyramidならばZope-SQLAlchemyなど)

それ以外の場合

Pythonを利用するのはWEBアプリを作る場合だけではないと思う。

その場合は、上記の統合ライブラリを使えない。

SQLAlchemyはそのような場合に備えて自前でヘルパー関数を持っている。

それがscoped_sessionだ。

自分のユースケースでは、データ分析するためにデータをMySQLから取り出したいので、scoped_sessionを使う必要がありそうだ。

scoped_session

今まで、『scoped_sessionって何だろう?』という状態で使っていたので簡単にまとめておく。

scoped_sessionは以下のように使ってSessionオブジェクトを生成することができる。

>>> from sqlalchemy.orm import scoped_session
>>> from sqlalchemy.orm import sessionmaker

>>> session_factory = sessionmaker(bind=some_engine)
>>> Session = scoped_session(session_factory)

生成されたSessionオブジェクトは以下のようにして使うことができ、このsome_sessionを使えばデータベースと通信ができる。

some_session = Session()

Sessionは何回呼び出しても同じオブジェクトを返し続ける。

>>> some_other_session = Session()
>>> some_session is some_other_session
True

これは同じセッションを異なった場所で簡単に使えるようにするためにあるものらしい。

一見して、クラスをインスタンス化しているように見えるので新しいセッションが生成されるのかと思いきや違うらしい。

とても紛らわしい。 ← 勉強不足なだけ。

新しいセッションを開始するには、以下のコードのように、

現在のSessionを削除し、もう一度Sessionを呼び出せばDBとの新しいセッションが開始される。

>>> Session.remove()
>>> new_session = Session()
>>> new_session is some_session
False

WEBアプリの場合はこの一連の流れを統合ライブラリが行ってくれるが、

それ以外の場合はセッションの寿命を管理したいならば、自前でこのコードを書く必要がある。

感想

今までなんとなく使っていたscoped_sessionについて知ることが出来て良かったです。

今回は、プログラムで重いクエリを叩くとプログラムがハングすることがあり、セッション周りが原因で起きているのではないかと思い調査しました。

調査後にMySQLのセッションタイムアウト時間を見てみると8時間に設定されており、

結局のところハングの原因はセッション周りではなく、単に自分のPythonコードが重くて止まっているように見えていただけという。。

参考

セッションとコネクションの定義について
sql server - What is the difference between a connection and a session? - Database Administrators Stack Exchange
SQLAlchemyのSession全般について
Session Basics — SQLAlchemy 0.9 Documentation
scoped_sessionヘルパーについて
Contextual/Thread-local Sessions — SQLAlchemy 0.9 Documentation