2017-06-09 107 views
10

我有一個包含3個成員和一個存儲數據的Python應用程序的MongoDB副本集。如何使用insert_many方法處理pymongo AutoReconnect異常

def safe_mongo_call(method, num_retries, *args, **kwargs): 
    while True: 
     try: 
      return method(*args, **kwargs) 
     except (pymongo.errors.AutoReconnect, 
       pymongo.errors.ServerSelectionTimeoutError) as e: 
      if num_retries > 0: 
       logger.debug('Retrying MongoDB operation: %s', str(e)) 
       num_retries -= 1 
      else: 
       raise 

我不知道但如何使用批量寫入時,處理這些異常,例如:

我可以使用單個文檔插入時,用包裝材料如下處理pymongo的AutoReconnect例外insert_many方法。根據documentation,批量寫入不是原子性的,因此即使發生其中一個例外,也可能已經有一些文檔成功寫入數據庫。因此,我不能像上面那樣簡單地重用包裝器方法。

如何處理這些情況的最佳方式是什麼?

+0

相關:HTTPS ://gist.github.com/anthonywu/1696591 – TheChetan

+1

您提供的代碼與我在問題中發佈的內容基本相同。我的用例不同,涉及批量操作,因爲部分文檔已經寫入數據庫,所以不能簡單地重試。 –

回答

3

對於這種情況有BulkWriteError必須提供什麼已經做 https://api.mongodb.com/python/current/examples/bulk.html#ordered-bulk-write-operations

但在連接丟失的情況下autoReconnect的被髮送,而不是和操作進度的信息似乎丟失細節(測試對於pymongo == 3.5.1)

在任何情況下,您都需要重新構建已寫入的內容以及未重寫的內容,然後重試其餘項目的操作。 在後一種情況下,它會是一個有點困難,因爲你沒有什麼一直在實際寫入之前的信息,但仍是可行的

爲草圖的解決方案: 要插入指定的的ObjectId除非每個文檔_id已經存在。您可能自己處理這個問題 - 遍歷文檔,爲那些缺失的文檔手動分配_id並將ID保存在臨時變量中。一旦你遇到異常,找到最後成功插入的槓桿,即利用類似於二進制搜索的方法具有最壞的O(logN)查詢,並且也可以使用事實批量操作被拆分成更小的批次(https://api.mongodb.com/python/current/examples/bulk.html#bulk-insert)。當然,這種方法的適用性取決於您在mongod實例上的負載配置文件以及是否允許附加查詢突發。如果BulkWriteError按預期拋出,則可以只抓取未插入的文檔,然後僅重試這些文檔的操作。

回到autoReconnect的問題,我個人開出罰單在蒙戈 - python的驅動問題跟蹤,機會是很高的或者是錯誤或像正在做的目的

+0

我檢查了所有這些,但這就是問題所在,如果引發AutoReconnect,它缺少關於迄今爲止所做的工作的信息。你能否詳細說明如何*重建已經寫好的內容*?因爲這不是那麼容易,考慮到寫入可能來自多個地方,並且項目可以具有相同的語義密鑰(不是重複的)。 –

+0

擴大我的答案 – ffeast

+0

打開票可能是一個很好的方向,至少要找出是否有技術上的原因,爲什麼這樣做。 –