Docs Menu
Docs Home
/ / /
PyMongo
/

MongoDB Server実行時間の制限

項目一覧

  • Overview
  • timeout() メソッド
  • ネストされたタイムアウト ブロック
  • スレッドとタスクの安全性
  • timeoutMS 接続オプション
  • 例外の処理
  • トラブルシューティング
  • ServerSelectionTimeoutError
  • ネットワークタイムアウト
  • ExecutionTimeout
  • WTimeoutError
  • BulkWriteError
  • API ドキュメント

PyMongo を使用してサーバー操作を実行する場合、サーバーがこの操作を完了するのにかかる時間を制限することもできます。 そのためには、クライアント側の 操作タイムアウトを指定します。 タイムアウトは、サーバー選択、接続チェックアウト、直列化、サーバー側実行など、操作を完了するために必要なすべてのステップを適用します。 タイムアウトが経過すると、PyMongo はタイムアウトの例外を発生させます。

タイムアウトを指定するには、 timeout()メソッドを使用する方法と、 timeoutMS接続オプションを使用する方法の 2 つがあります。

コードでタイムアウトを指定するには、 timeout()メソッドを呼び出して、タイムアウトの長さを秒単位で渡します。 次の例に示すように、 withステートメントでtimeout()メソッドを呼び出す必要があります。

with pymongo.timeout(10):
collection.insert_one({"name": "Yngwie"})

上記の例では、挿入操作が10秒以内に完了しない場合、PyMongo はエラーを発生させます。

指定したタイムアウトは、 withブロック内のすべての操作に適用されます。 次の例では、挿入操作と検索操作の両方が合計10秒以内に完了する必要があります。

with pymongo.timeout(10):
coll.insert_one({"name": "Yngwie"})
coll.find_one({"name": "Yngwie"})

実行がネストされたタイムアウト ブロックになると、外部タイムアウトは一時停止されます。 実行によりネストされたタイムアウト ブロックが終了すると、以前のタイムアウトが再開されます。

重要

ネストされたタイムアウト ブロックを使用すると、外部タイムアウト ブロックの期限を短縮できますが、延長することはできません。

次の例は、 timeout()メソッドへのネストされた呼び出しを使用する方法を示しています。

1with pymongo.timeout(5):
2 collection.find_one()
3 with pymongo.timeout(3):
4 collection.find_one()
5 collection.find_one()
6 with pymongo.timeout(10):
7 collection.find_one()
8 collection.find_one()

前の例では、コードは次の手順を実行しています。

  • Line 1 : 5 秒のタイムアウト ブロックを作成します。

  • 2行: 5 秒のタイムアウト ブロック内でfind_one()メソッドを呼び出します。 サーバーは
    この操作は 5 秒のタイムアウト以内に完了してください。
  • Line 3 : ネストされた 3 秒のタイムアウト ブロックを作成します。

  • 4行: 3 秒のタイムアウト ブロック内でfind_one()メソッドを呼び出します。 サーバーは
    この操作は 3 秒以内に完了します。
  • 5行: 3 秒のタイムアウト ブロック外でfind_one()メソッドを呼び出します。 サーバーは
    この操作を元の 5 秒のタイムアウト内に完了します。
  • Line 6 : ネストされた 10 秒のタイムアウト ブロックを作成します。

  • 7行: 10 秒のタイムアウト ブロック内でfind_one()メソッドを呼び出します。 ネストされたタイムアウト
    ブロックは外部タイムアウト ブロックを延長できないため、サーバーは元の 5 秒タイムアウト内にこの操作を完了する必要があります。
  • 8行: 10 秒のタイムアウト ブロック外でfind_one()メソッドを呼び出します。 サーバーはこの操作を元の 5 秒のタイムアウト内に完了する必要があります。

timeout()メソッドはスレッドセーフです。 タイムアウトは現在のスレッドにのみ適用され、複数のスレッドが並行して異なるタイムアウトを設定できます。

timeout()メソッドはasyncioセーフでもあります。 タイムアウトは現在のタスクにのみ適用され、複数のタスクが同時に異なるタイムアウトを設定できます。

次の例は、非同期アプリケーション用のMongoDB Pythonドライバーである Motor とともに メソッドを使用する方法を示しています。timeout()

import motor.motor_asyncio
client = motor.motor_asyncio.AsyncIOMotorClient()
coll = client["test-db"]["test-collection"]
with pymongo.timeout(10):
await coll.insert_one({"name": "Yngwie"})
await coll.find_one({"name": "Yngwie"})

MongoDB 配置に接続するときにタイムアウトを指定するには、 timeoutMS接続オプションをタイムアウトの長さ(ミリ秒単位)に設定します。 これは、MongoClient コンストラクターに引数を渡す方法と、 接続stringのパラメーターを使用する方法の 2 つがあります。

次のコード例では、 timeoutMSオプションを使用して10秒のタイムアウトを指定しています。

client = pymongo.MongoClient("mongodb://<db_username>:<db_password>@<hostname:<port>",
timeoutMS=10000)
uri = "mongodb://<db_username>:<db_password>@<hostname:<port>/?timeoutMS=10000"
client = pymongo.MongoClient(uri)

timeoutMSオプションを指定すると、PyMongo は指定されたタイムアウトを各サーバー操作に自動的に適用します。 次のコード例では、10 秒のタイムアウトを指定し、insert_one() メソッドとfind_one() メソッドを呼び出します。timeoutMSオプションとtimeout()メソッドの使用を比較するには、対応するタブを選択します。

uri = "mongodb://<db_username>:<db_password>@<hostname@:<port>/?timeoutMS=10000"
client = pymongo.MongoClient(uri)
coll = client["test-db"]["test-collection"]
coll.insert_one({"name": "Yngwie"}) # Uses a 10-second timeout.
coll.find_one({"name": "Yngwie"}) # Also uses a 10-second timeout.
client = MongoClient()
coll = client["test-db"]["test-collection"]
with pymongo.timeout(10):
coll.insert_one({"name": "Yngwie"})
with pymongo.timeout(10):
coll.find_one({"name": "Yngwie"})

重要

timeout() が timeoutMS を上書きする

timeoutMSオプションを指定して、コード内でtimeout()メソッドを呼び出すと、PyMongo はtimeoutブロック内のtimeoutMSの値を無視します。

client = MongoClient("mongodb://localhost/?timeoutMS=10000")
coll = client["test-db"]["test-collection"]
coll.insert_one({"name": "Yngwie"}) # Uses the client's 10-second timeout
# pymongo.timeout overrides the client's timeoutMS.
with pymongo.timeout(20):
coll.insert_one({"name": "Yngwie"}) # Uses the 20-second timeout
with pymongo.timeout(5):
coll.find_one({"name": "Yngwie"}) # Uses the 5-second timeout

サーバー操作が指定されたタイムアウトを超えると、PyMongo はタイムアウトの例外を発生させ、 PyMongoError.timeoutプロパティをTrueに設定します。

次のコード例は、タイムアウト例外を処理する方法の 1 つを示しています。 exceptブロック内では、コードはtimeoutプロパティをチェックして、例外がタイムアウトによって発生したかどうかを判断します。

try:
with pymongo.timeout(10):
coll.insert_one({"name": "Yngwie"})
time.sleep(10)
# The deadline has now expired. The next operation will raise
# a timeout exception.
coll.find_one({"name": "Yngwie"})
except PyMongoError as exc:
if exc.timeout:
print(f"block timed out: {exc!r}")
else:
print(f"failed with non-timeout error: {exc!r}")

次のセクションでは、タイムアウトの使用時に発生する可能性のあるエラーについて説明します。

このエラーは、クライアントが指定されたタイムアウト内に操作を実行するために利用できるサーバーを見つけられなかったことを示しています。

pymongo.errors.ServerSelectionTimeoutError: No servers found yet, Timeout: -0.00202266700216569s, Topology Description: <TopologyDescription id: 63698e87cebfd22ab1bd2ae0, topology_type: Unknown, servers: [<ServerDescription ('localhost', 27017) server_type: Unknown, rtt: None>]>

このエラーは、クライアントが指定されたタイムアウト内に接続を確立できなかったこと、または操作が送信されたがサーバーが時間内に応答しなかったことを示しています。

pymongo.errors.NetworkTimeout: localhost:27017: timed out

このエラーは、指定されたタイムアウトを超えたため、サーバーが操作をキャンセルしたことを示している可能性があります。 PyMongo がこの例外を発生させた場合でも、サーバー上で操作が部分的に完了している可能性があります。

pymongo.errors.ExecutionTimeout: operation exceeded time limit, full error: {'ok': 0.0, 'errmsg': 'operation exceeded time limit', 'code': 50, 'codeName': 'MaxTimeMSExpired'}

また、指定されたタイムアウト内に操作を完了できなかったため、クライアントが操作をキャンセルしたことを示す場合もあります。

pymongo.errors.ExecutionTimeout: operation would exceed time limit, remaining timeout:0.00196 <= network round trip time:0.00427

このエラーは、サーバーが指定されたタイムアウト内に、指定された書込み保証 (write concern) に従って要求された書込み操作を完了できなかったことを示しています。

pymongo.errors.WTimeoutError: operation exceeded time limit, full error: {'code': 50, 'codeName': 'MaxTimeMSExpired', 'errmsg': 'operation exceeded time limit', 'errInfo': {'writeConcern': {'w': 1, 'wtimeout': 0}}}

このエラーは、サーバーが指定されたタイムアウト内に、指定された書込み保証 (write concern) に従い、 メソッドまたは メソッドを完了できなかったことを示しています。insert_many()bulk_write()

pymongo.errors.BulkWriteError: batch op errors occurred, full error: {'writeErrors': [], 'writeConcernErrors': [{'code': 50, 'codeName': 'MaxTimeMSExpired', 'errmsg': 'operation exceeded time limit', 'errInfo': {'writeConcern': {'w': 1, 'wtimeout': 0}}}], 'nInserted': 2, 'nUpserted': 0, 'nMatched': 0, 'nModified': 0, 'nRemoved': 0, 'upserted': []}

PyMongo でタイムアウトの使用の詳細については、次の API ドキュメントを参照してください。

戻る

Stable API