はじめに
WEB開発から見たDB設計(テーブル設計)ではWEB開発時のテーブル設計についてまとめました。
次はアプリ開発者にはあまり機会が少ないDB側およびアプリ側の設定をWEB開発の観点からまとめます。
DB側の設定項目
- ログ
DB側の設定説明
ログ
データベースにもログを記録する機能があります。
大抵のWEBサービスの場合、DBを使うときはネットワーク経由で接続をするため、アプリ側でログを取っていてもネットワークの途中で切れてアクセスが失敗することがあります。
そのため、DB側でもちゃんとsqlが届いたことを確認できるようにログを出したほうが良いです。
ただし、大量に出るためログローテートなどでちゃんと容量を圧迫しないように処理することが必要です。
postgresの設定
# log_directory = 'log'
-> log_directory = 'log' へ変更
# log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log'
-> log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log' へ変更
# log_statement = 'none'
-> log_statement = 'all' へ変更
アプリ側の設定項目
- アプリケーション名
- タイムアウト値
- セッション(プール数)
アプリ側の設定説明
アプリケーション名
アプリからDBを利用をする際は、DBの使用のたびに接続をするのではなく、一度接続をした際にセッションを使いまわして接続のロスをなくしています。
バグなどで使いまわすのに失敗して多くのセッションを作成してしまうとDBに負担がかかる上に、DBに設定されている上限を超えるとセッションが作成できなくなってしまいます。
その時のためにどこのセッションが悪いのかを判断できるようにセッションにアプリケーション名を付けます。
個人的には関数名をつけるのがわかりよいと思っています。
postgresqlにsqlalchemyでアプリケーション名をつける例
sqlalchemyの使い方については以前まとめた記事を見てください。その差分のみここに記載しています。
sqlalchemyを使用してpythonでDBアクセスをする
ENGINE = create_engine(CONNECT_STR, connect_args={"application_name":"py_app"})
結果
SELECT * FROM pg_stat_activity;
16384 animal_db 75 10 postgres py_app 000.00.0.0 (NULL) 57196 2019/09/03 21:42:15.004 (NULL) 2019/09/03 21:42:15.057 2019/09/03 21:42:15.073 Client ClientRead idle (NULL) (NULL) COMMIT client backend
タイムアウト値
ここが一番重要な点です。
DBアクセスをした際に何かの原因でアプリが停止するのを防ぐために設定した時間を過ぎたら接続が切断されるようにタイムアウト値を設定します。
WEBアプリではとかく早いレスポンスが期待されます。サービスにもよりますが最長で秒オーダーになります。そのため、長くとも5秒程度のタイムアウトにするべきです。
※WEBサイトを開いたときに5秒以上待たされるときをイメージしてみてください。
DBサーバへの物理的な距離やDBサーバのメモリ等環境によって左右されるので実際は測定してから考えることになると思います。
postgresqlにsqlalchemyでタイムアウトをつける例
pool_timeoutはプール獲得のタイムアウトでconnect_timeoutが接続のタイムアウトになります。
sqlalchemyの使い方については以前まとめた記事を見てください。その差分のみここに記載しています。
sqlalchemyを使用してpythonでDBアクセスをする
ENGINE = create_engine(CONNECT_STR, pool_timeout=10, connect_args={'connect_timeout': 10})
セッション(プール数)
基本的にはプロセスやスレッドに対して1つあれば事足りますが、ネットワーク異常などで切れたセッションが解除される前に
再接続してしまう可能性を考えて各プロセスに対して2個程度プールがあったほうが安心です。
例はsqlalchemyを使用してpythonでDBアクセスをするに記載しています。
おわりに
DB接続をするときに気を付けるべきことを記載しました。
ここら辺の設定は何もしなくても正常に動きますが、異常が発生したときに威力を発揮する設定になります。
そのため、いざ開発しようというときに抜けていることがありテストの時に気づくというケースがありました。
タイムアウトなどDB側の設定でもいじれますが、DB全体に影響を与えるため基本的にはアプリ側でコントロールしたほうが良いと思います。