#DBによるロック処理(排他制御)の実装#
##前提として##
- ロックは最小限にする(長いとロック待ちが多発)
- 必ず1人ずつ処理させたい部分にロックを加える
- DBにロック処理は任せる
(LOCK [ TABLE ] name [, ...] [ IN lockmode MODE ] [ NOWAIT ]
) - デッドロックは何かがおかしいので必ず解決する
##ロックテーブルを一つにまとめる##
- ロックする箇所を一つにまとめるのもアリ ⇒ share_lock 等のテーブルを用意
- share_lockをロックする事で一人一人処理される事を約束する ⇒ 必ずこの中で排他制御したい処理をする
- デッドロックの発生箇所を把握しやすくし、発生を抑えることが出来る
##行ロック##
- 最終的に確認する必要があれば、その行だけロックをしてから確認の処理をする
- 決済などは先に済ましてからロックする。(ロック時間は極力短くする)
- 別途cron処理があれば、cron側を NOWAIT として、ロックされていたら(処理中)エラーとして次の処理にする等を考慮する
##ロックのモード##
http://www.ecoop.net/memo/archives/2008-05-30-1.html
- ACCESS EXCLUSIVE を使う事はほぼ無い(最強、違うセッションからのアクセスは許さない)
- EXCLUSIVE 基本読み取りは大丈夫な場合が多いので、見直す
#高負荷時(大量アクセス時)の考察#
##メモリ不足##
- フレームワークによってはメモリを一気に食ってしまうような場合がある。
- その為大量にそのページへ流れると、一気にメモリ不足に陥りレスポンスが遅くなってしまう。(※DBで大量のデータがあるテーブルを検索、一覧を取得してモデル化する時など)
##DBのindexを見直す##
- 検索で時間がかかっている場合などはindexを見直して、検索で使うけどindexが張られていない状態を無くす
##abテスト(ApacheBench)を出来れば行う##
- 同時アクセス数を数値で指定して、どのくらいのアクセスに耐えられるのか把握する必要がある。
- 出来れば本サーバもしくはそれに近い環境で出来ると良い。ローカル環境でも出来るが参考程度。
http://qiita.com/flexfirm/items/ac5a2f53cfa933a37192
http://kaworu.jpn.org/kaworu/2013-02-23-1.php
このあたりが参考になる。
Complete requests ⇒ 成功した数
Failed requests ⇒ 失敗した数 ※ここを減らす
HTML transferred ⇒ HTMLの容量(この容量があまりに多かったり少なかったりしたら、想定しているページが表示されていない)
Requests per second ⇒ 1秒あたり何リクエストさばけるか ※ここを増やす
Time per request ⇒ 1リクエストあたりの処理時間 ※ここを短くする
Percentage of the requests served within a certain time ⇒ 右側に表示された時間内に処理されたリクエストの割合。「75% 3000」は、75%のリクエストが3000ms以内に処理されたことを表す。
#まとめ#
- 共有ロックテーブルをつくって、テーブルロックはその箇所のみにする
- 更新したい行だけロックをすることで、他からの影響は受けないようにする
というのが特に勉強になりました。
ロックのモードも重要で、全てをロックする事(検索も許さない)で負荷が上がってしまうので、更新だけロックするように調整しました。
フレームワークの使い方によってメモリを消費してしまうので、
高負荷(アクセスが多い)の場合は顕著にレスポンスが遅くなったりします。
abテストを行って、アクセス数が増えると著しくレスポンスが遅くなる個所を見つけて処理を見直す必要ありです。