🦔
アプリ起動時にDB起動を待つ
めったに変更されないけれども参照回数が多いデータは、アプリケーションのメモリ内にキャッシュするのが効率的です。
これはISUCONでもよくやる最適化なのですが、起動時にキャッシュするデータをDBから読み込むと再起動試験でfailする要因になりえます。
-
db.Open()
はコネクションプールを初期化するだけでDBに接続しないので接続エラーも起こらないのだが、このAPIの結果err == nil
だと接続できるように錯覚しがち - 開発中のアプリケーション再起動時に常にDBサーバーが生きているのでエラーが起こらない
- 再起動試験しても先にDBサーバーが起動したり、アプリサーバーの再起動が完了(再起動前のDBからキャッシュを取得できる)してからDBを再起動し始めるとやはりエラーが起こらず気づけ無い。
こんなミスでfailノースコア敗退するのはあまりにももったいないので、アプリケーション起動時にDBの起動を待つコードスニペットなりコピペライブラリなりを用意しておきましょう。
// db.Open() が成功した直後にこれを入れる.
for {
err := db.Ping()
if err == nil {
break
}
log.Print(err)
time.Sleep(time.Second * 2)
}
log.Print("DB ready!")
db.Ping()
はコネクションを1つ作り、ドライバが対応している場合はそのDBに対してPingをします。接続エラーが起こる場合はこれで検出できます。
Ping の代わりに _, err := db.Exec("SELECT COUNT(*) FROM table")
などで使うテーブルへのアクセスできることの確認&バッファプールに乗せるなどの工夫も考えられます。
Discussion