MongoDB problem z transakcyjnością

0

Mamy taki serwis

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ć?

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)

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).

0

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

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.

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?

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.

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

1 użytkowników online, w tym zalogowanych: 0, gości: 1