MongoDB problem z transakcyjnością

MongoDB problem z transakcyjnością
AP
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 165
0

Mamy taki serwis

Kopiuj
class MyService {
	private MyRepository repository;
	
	public void update(String id) {
		MyDocument doc = repository.find(id);
		// logika modyfikujaca doc
		repository.save(doc);
	}
}

W 99.9% przypadków działa to tak jak powinno, niestety pozostałe przypadki to sytuację gdy w tym samym czasie dostajemy requesty do update'u tego samego obiektu na bazie. Wtedy jeden update nadpisuje poprzedni, w zależności który z nich wykona się jako drugi.
MyRepository to repo MongoDB, niestety skazani jesteśmy na starą wersje (spring-data-mongodb-1.5.6.RELEASE, spring-data-commons-1.8.6.RELEASE) w której nie ma możliwości obsługi transakcji.
Aplikacja działa w klastrze, więc synchronizacja tej metody nie pomoże.
Jakieś pomysły jak to rozwiązać?

danek
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Poznań
  • Postów: 797
1

Nic dziwnego, bo pobierasz równocześnie ten sam obiekt i pewnie zmieniasz mu różne pola. Jeśli jest to możliwe, możesz użyć drivera mongo dla javy i aktualizować tyle te pola które chcesz (u nas tak to jest robione i działa)

LU
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Gdańsk
jarekr000000
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: U krasnoludów - pod górą
  • Postów: 4712
4

Wbrew pozorom w bazach SQL możesz mieć dokładnie ten sam problem (wysyłasz dane do UI, a potem zapisujesz dane z UI).
I dokładnie - jakiś optimistic lock może ograniczyć skutki, albo robimy fail i użytkownik musi powtórzyć akcje, albo nawet może się dać naprawić problem. (w zależności co masz w logice).

danek
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Poznań
  • Postów: 797
0

Dodatkowo, nie wiem jak spring data to robi, ale tu na pewno problem jest z transakcyjnością? Jeśli masz taki obiekt

Kopiuj
class Foo{
   int a;
   int b;
}

Pobierasz go w 2 wątkach i w jednym zmieniasz a w drugim b i oba chcesz zapisać. Nie czy w tym momencie zamiast aktualizacji jednego pola, nie idzie do bazy polecenie aktualizacji obu pól i dlatego jeden wątek nadpisuje zmiany drugiego.

AP
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 165
0

Nie do końca rozumiem co chciałeś napisać :D

1 request:
pobiera stan obiektu
dodaje element X do tablicy
zapisuje obiekt

2 request
pobiera stan obiektu (stan gdy obiekt nie ma jeszcze elementu X)
dodaje element Y do tablicy
zapisuje obiekt

w efekcie, zamiast mieć obiekt który ma tablicę z elementem X i Y, zapytanie które zakończy się później nadpisuje całą tablicę i zostawia w środku albo element X albo Y.

W każdym razie, OptimisticLock wygląda obiecująco, jeżeli dobrze rozumiem operacja save rzuci OptimisticLockingFailureException?
Bez względu czy do zapisu użyje MongoRepository czy MongoTemplate?

RA
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 373
0

To na jakiej podstawie uważasz że po wykonaniu requestu 2 znajdą się w bazie jakiekolwiek inne dane niż zapisałeś w tym requescie? Zapis nie oznacza operacji merge.

danek
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Poznań
  • Postów: 797
0

No własnie o to mi chodzi ;)
W jednej sytuacji zapisujesz obiekt z X. Potem przychodzi drugi zapis który ma liste bez X ale za to ma Y. Wtedy baza nie wie, ze chcesz dodać Y i zostawić X tylko po prostu nadpisze ;)
tak jak mówią, OptimisticLock i na wyjątku powtórzyć całą operacje jeszcze raz

Charles_Ray
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 1909

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.