2017-06-09 31 views
10

Mam zestaw replik MongoDB z 3 elementami i aplikacją Python, która przechowuje w niej dane.Jak radzić sobie z wyjątkiem AutoReconnect pymongo z metodą insert_many

mogę poradzić pymongo za AutoReconnect wyjątek przy użyciu pojedynczych wkładek dokumentu z obwolutą następująco:

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 

nie jestem pewien, choć jak do obsługi tych wyjątków przy użyciu większość pisze, np Metoda insert_many. Zgodnie z documentation, zapisy masowe nie są atomowe, więc nawet jeśli wystąpi jeden z wyjątków, może być już kilka dokumentów zapisanych do bazy danych z powodzeniem. W związku z tym nie mogę po prostu ponownie użyć metody opakowania jak wyżej.

Jaki jest najlepszy sposób radzenia sobie w takich sytuacjach?

+0

Stosowna: https : //gist.github.com/anthonywu/1696591 – TheChetan

+1

Kod, który podałeś, działa w zasadzie tak samo, jak to, co napisałem w pytaniu. Mój przypadek użycia jest inny i obejmuje operacje zbiorcze, których nie można po prostu powtórzyć, ponieważ część dokumentów może już zostać zapisana w bazie danych. –

Odpowiedz

3

W tym przypadku nie ma BulkWriteError że musi podać szczegółowe informacje na temat tego, co zostało zrobione https://api.mongodb.com/python/current/examples/bulk.html#ordered-bulk-write-operations

ale w przypadku utraty połączenia AutoReconnect jest wysyłana zamiast i informacji o postępach działań wydaje się być stracone (testowane dla pymongo == 3.5.1)

W każdym razie musisz zrekonstruować to, co zostało napisane, a co nie, i ponowić operację dla pozostałych elementów. W tym drugim przypadku byłoby to nieco trudniejsze, jak nie masz wcześniejszej informacji na temat, co zostało napisane, ale faktycznie nadal wykonalne

jako szkic rozwiązania: każdy dokument, który ma zostać wstawiony jest przypisany ObjectId chyba _id jest już obecny. Sam możesz sobie z tym poradzić - wykonaj iteracje po dokumentach, ręcznie przypisz je, aby je pominąć, i zapisz identyfikatory w zmiennej tymczasowej. Po trafieniu wyjątku, ostatnie pomyślne wstawienie efektu dźwigni, tj. Podejście binarne, mające na celu wyszukiwanie najgorszych zapytań typu O (logN), powinno być pomyślnie wprowadzone, a być może wykorzystywać również fakt, że operacje zbiorcze są dzielone na mniejsze partie (https://api.mongodb.com/python/current/examples/bulk.html#bulk-insert). Ale oczywiście zastosowanie tego podejścia zależy od profilu obciążenia, który masz na swoich instancjach mongody i czy dodatkowe impulsy zapytań są dopuszczalne. Jeśli zgłoszenie zostało wykonane zgodnie z oczekiwaniami, można po prostu pobrać dokumenty, które nie zostały wstawione, i ponowić operację tylko dla tych dokumentów.

Powrót do AutoReconnect problemu, ja osobiście otworzyć bilet w Mongo-python-driver zagadnień tracker, szanse są wysokie, jego albo błąd lub robione tak celowo

+0

Sprawdziłem to wszystko, ale to jest problem, jeśli "AutoReconnect" jest generowany, brakuje informacji o tym, co zostało zrobione do tej pory. Czy możesz opracować, jak * zrekonstruować to, co zostało napisane *? Ponieważ nie jest to takie łatwe, biorąc pod uwagę, że może istnieć wiele miejsc, z których mogą pochodzić zapisy, a także przedmioty mogą mieć te same klucze semantyczne (nie będące duplikatami). –

+0

Rozszerzona moja odpowiedź – ffeast

+0

Otwarcie biletu może być dobrym kierunkiem, przynajmniej po to, aby dowiedzieć się, czy istnieją techniczne powody, dla których zostało to zrobione w ten sposób. –