2011-07-24 12 views
6

mam 2 kolekcje: A (3,8 Docs) i B (1,7 docs)MongoDB - PHP - MongoCursorException 'Kursor nie znaleziono'

Mam skrypt PHP, który biegnę z powłoki, które:

  1. iteruje każdego rekordu w
  2. ~ 60% czasu, to robi findOne o B (za pomocą _id)
  3. ma podstawowe matematyki, tworząc tablicę php

gdy pętla wszystkich Dokumenty w A odbywa:

4) pętli nad php tablicy

5) upsert do zbierania C

w (1), to konsekwentnie uzyskać: praca błąd krytyczny: Uncaught wyjątek „MongoCursorException” z komunikatem „Kursor nie znaleziono” Ostatnia pozycja przetwarzany był # 8187 z 3872494.

real 1m25.478s 
user 0m0.076s 
sys  0m0.064s 

uruchomienie go ponownie, bez zmian w kodzie, wyjątek został rzucony w punkcie # 19826/3872495

real 3m19.144s 
user 0m0.120s 
sys  0m0.072s 

I znowu, # 8181/387249

real 1m31.110s 
user 0m0.036s 
sys  0m0.048s 

Tak, zdaję sobie sprawę, że mogę (i zapewne należy) połowu wyjątek ... ale ... dlaczego jest nawet wyrzucane? Zwłaszcza w tak różnym czasie/głębokości w bazie danych.

Jeśli to pomaga, moja konfiguracja to zestaw replik 3-węzłowy (2 + arb). Wziąłem wtórny tryb offline i spróbowałem z podstawowym uruchomieniem. Takie same wyniki (różna liczba wyników przetworzonych i razy, ale zawsze generuje wyjątek Cursor Not Found).

+0

Czy to był ostatecznie problem z przekroczeniem limitu czasu kursora? Dzięki – mils

Odpowiedz

0

To może być problem z limitem pamięci. Spróbuj eksperymentować z zapewnieniem większej ilości pamięci i sprawdź, czy wyniki różnią się, co możesz zrobić za pomocą opcji -d: php -d memory_limit = 256M yourscript.php

To dużo dokumentów i wygląda na to, że jesteś tworząc całkiem dużą liczbę obiektów. Istnieją również różne funkcje php, takie jak memory_get_usage(), które możesz wykorzystać do profilowania alokacji pamięci w czasie wykonywania, a także do debugowania rozszerzeń, takich jak xdebug lub tego, co zapewnia zend.

9

Yes, I realize that I can (and probably should) catch the exception...

Tak, to zdecydowanie pierwsza rzecz. Istnieją dziesiątki uzasadnionych powodów wyjątku? Jak myślisz, co się dzieje, gdy podstawowy nie działa i staje się nieosiągalny?

... why is it even being thrown?

Istnieje kilka potencjalnych przyczyn, ale niech cięte prosto do kodu błędu widzisz.

  • Oficjalne dokumenty PHP to here.
  • Cytat z tej strony: Sterownik próbował pobrać więcej wyników z bazy danych, ale baza danych nie miała rekordu zapytania. Zwykle oznacza to, że kursor przekroczył limit czasu po stronie serwera ...

Kierowca MongoDB PHP ma dwie różne limity czasu:

  • limit czasu połączenia
  • Timeout Kursor

Ty trafienia timeout kursora. Możesz połączyć się z bazą danych, ale zapytanie "kończy się z czasem".

Ewentualne poprawki:

  1. przedłużyć kursor timeout. Możesz też ustawić go na zero i sprawić, by trwał on wiecznie.
  2. Wykonuj tę pracę partiami. Uzyskaj pierwsze 1000 _ids od A, przetwórz je, a następnie zaznacz, że to zrobiłeś. Następnie uzyskaj następny 1000 _ids większy niż twój ostatni bieg i tak dalej.

Sugerowałbym # 2 wraz z obsługą wyjątku. Nawet jeśli nie rozwiąże to całkowicie problemu, pomoże to w odizolowaniu i złagodzeniu problemu.

+1

limit czasu kursora rozwiązał mój problem (limit czasu po pobraniu 2k rekordów) –

4

Wiem, że jest późno i to nie może być twoje rozwiązanie, ale możesz spróbować użyć nieśmiertelnego(). Jak zauważył Gates VP, this page opisuje wyjątek.

The driver was trying to fetch more results from the database, but the database did not have a record of the query. This usually means that the cursor timed out on the server side: after a few minutes of inactivity, the database will kill a cursor (see MongoCursor::immortal() for information on preventing this).

Pomyślałem, że pisać całego opisu dla innych idących tę stronę i od limitu czasu() i nieśmiertelne() są różne. timeout() określa czas oczekiwania na odpowiedź. immortal() zaprzecza kursorowi od śmierci z powodu nieaktywności.

Powiązane problemy