業務でデータベースとしてMongoDBやAWS DocumentDBを使っていると、時おり以下のような接続時の失敗に出くわすことがあります。
このようなエラーが表示された場合、「書き込みの再試行が使えない」という内容の問題が発生しています。
本記事では、この問題の原因と解決方法について、現場の視点で丁寧に解説します。
エラーの内容を正しく理解する
このエラーの文意は、書き込み再試行機能が使えない環境で、誤ってそれを有効にしていることを示しています。
通常、書き込み再試行とは、通信の途中で処理が失敗しても、もう一度同じ内容を送って再処理してくれる機能です。
これにより、一時的な通信障害があっても処理が安全に完了するようになっています。
しかし、この機能はすべての情報記録装置で対応しているわけではありません。
原因の多くは接続設定にある
この問題の多くは、以下のような条件下で発生します。
- AWS DocumentDBを使っている
- 接続の際に
retryWrites=trueのような設定を指定している - 対応していない機能を接続時に有効にしてしまっている
AWS DocumentDBはMongoDBと互換性がありますが、機能の一部に制限があります。
特にこの書き込み再試行機能はDocumentDBでは標準で無効です。
接続文字列の修正
もっとも簡単で確実な対処方法は、接続時の文字列設定から再試行機能を無効にすることです。
例えば、以下のようになっている接続文字列
# 変更前
mongodb://利用者名:暗号@接続先情報/記録先?retryWrites=true
これを次のように変更します。
# 変更後
mongodb://利用者名:暗号@接続先情報/記録先?retryWrites=false
この変更により、対応していない機能を無理に使おうとせず、正常に接続できるようになります。
MongoDBの本来の機能が必要なら代替案を使う
もし本来のMongoDBで提供される書き込み再試行のような安全性が必要な場合は、以下の選択肢を検討することになります。
- 本家MongoDB(自己管理または提供型)を使う
- AWS DocumentDBの今後の対応を待つ
- 書き込み処理を手動で再試行する仕組みを実装する
AWS DocumentDBを使い続ける必要がある場合、再試行処理を自分で書くことで同じような効果を得ることも可能です。
# 例:書き込み処理を3回までやり直す処理
for (let i = 0; i < 3; i++) {
try {
await 書き込み処理();
break;
} catch (e) {
if (i === 2) throw e;
}
}
利用している開発用ライブラリの見直し
Node.jsなどでMongoDBの接続に使っているライブラリにもよって挙動が異なることがあります。
以下のような確認をしましょう。
- 使用中の道具が
retryWritesを自動で有効にしていないか - 接続時の初期設定を上書きできるか
場合によっては、接続処理の初期化部分を次のように明示的に書き換える必要があります。
const client = new MongoClient(接続先, {
retryWrites: false
});
こうすることで、意図しない機能が使われないように制御できます。
まとめ
この問題の本質は、「使えない機能を有効にしてしまっている」ことです。
- AWS DocumentDBは
retryWritesに対応していない - 接続設定で無効にすれば即時解決する
- 安全な処理が必要なら再試行処理を自前で実装する
MongoDBエラーの中でもこの301番の問題は比較的単純ですが、初心者には誤解されやすいものです。
今回の内容が、同じような悩みを持つ技術者の助けになれば幸いです。


コメント