2015年6月14日日曜日

セッション管理をDBで行う時の間違った設計

とある有名システムにて、重たい時のセッション動作が不安定なのでソースを見ていたところ!


セッションデータをDBで管理は良いのですが、トランザクションを開始していないというお粗末な物でした。
トランザクションを開始していない・・・これはデータを消失してしまうことを意味するのです。

たとえば
ページAを開く。
ページBに移動しようとしたら、重くて開かないからページCに移動。
ページBやCに移動する時にセッションへデータ書き込みがあった場合、セッションがどっちのデータになるかは神すらもわからない状態。

また、セッションに保存してそのままリダイレクトといった動作(ログインやログアウト)はよくある設計ですが、重いとセッション書き込み順序が逆転してうまく動作しません。

なのでセッションをDBで管理する場合は、トランザクションによる保護を絶対忘れないようにしましょう。

フレームワークを使っていればフレームワークがしっかり処理するので問題ないですが、DB操作に慣れていない人が自作するとこの肝心な部分が抜け落ちてしまうのですよね。


セッション専用のコネクションを張り、トランザクションを開始し、for update でロック。 これを最低限おこないましょう。
セッションをDBでというソースを載せているブログで、これが抜けているのが多く見受けられました。
ただし、闇雲にロックしてしまうと、範囲ロックをしてしまい、結果、デッドロックするということになります。for updateを使う時はこれに注意です。
1行のみロックするには、その行が存在していなければなりません。 なので、無かったら作って、その後にロックをすることでデッドロックを避けられます。


あとは、アクセスの全てでセッションを開始するような設計は絶対にやめましょう。 サーバが落ちる原因になります。
セッションのロックが解除されるまで、次のアクセスが許可されません。
1ページでいくつもセッションを開くような動作だった場合、どうなるかは想像できると思います。

セッションまわりって意外と落ちる原因になりやすく、初心者が気が付かない盲点だったりします。
特にPHPのセッションまわりのデフォルト設定は超小規模サイト向けであり使い物にならなく、気がきいていないと思います!