Multi-collection, multi-document „transakcje” w MongoDB
Zdaję sobie sprawę, że MongoDB, ze względu na swoją naturę, nie obsługuje i prawdopodobnie nigdy nie będzie obsługiwać tego rodzaju transakcji. Jednak odkryłem, że muszę ich używać w nieco ograniczony sposób, więc wymyśliłem następujące rozwiązanie i zastanawiam się:czy jest to najlepszy sposób na zrobienie tego i czy można go ulepszyć? (zanim przejdę do implementacji w mojej aplikacji!)
Oczywiście transakcja jest kontrolowana przez aplikację (w moim przypadku jest to aplikacja internetowa Pythona). Dla każdego dokumentu w tej transakcji (w dowolnej kolekcji) dodawane są następujące pola:
'lock_status': bool (true = locked, false = unlocked),
'data_old': dict (of any old values - current values really - that are being changed),
'data_new': dict (of values replacing the old (current) values - should be an identical list to data_old),
'change_complete': bool (true = the update to this specific document has occurred and was successful),
'transaction_id': ObjectId of the parent transaction
Ponadto istniejetransaction
kolekcja przechowująca dokumenty opisujące każdą trwającą transakcję. Wyglądają na:
{
'_id': ObjectId,
'date_added': datetime,
'status': bool (true = all changes successful, false = in progress),
'collections': array of collection names involved in the transaction
}
A oto logika tego procesu. Mam nadzieję, że działa w taki sposób, że jeśli zostanie przerwany lub ulegnie awarii w inny sposób, może zostać poprawnie przywrócony.
1: Ustawićtransaction
dokument
2: Dla każdego dokumentu, na który ma wpływ ta transakcja:
Zestawlock_status
dotrue
(aby „zablokować” dokument przed modyfikacją)Zestawdata_old
idata_new
do ich starych i nowych wartościZestawchange_complete
dofalse
Zestawtransaction_id
do celutransaction
dokument, który właśnie zrobiliśmy3: Przeprowadź aktualizację. Dla każdego dokumentu, którego dotyczy problem:
Zastąp wszystkie pola w tym dokumencie za pomocądata_new
wartościZestawchange_complete
dotrue
4: Ustawtransaction
dokumentstatus
dotrue
(ponieważ wszystkie dane zostały pomyślnie zmodyfikowane)
5: Dla każdego dokumentu objętego transakcją wykonaj kilka czynności porządkowych:
usunąćdata_old
idata_new
, ponieważ nie są już potrzebnezestawlock_status
dofalse
(aby odblokować dokument)6: Usunąćtransaction
dokument skonfigurowany w kroku 1 (lub zgodnie z sugestią zaznacz jako kompletny)
Myślę, że logicznie działa w taki sposób, że jeśli zawiedzie w dowolnym momencie, wszystkie dane mogą być albo wycofane, albo transakcja może być kontynuowana (w zależności od tego, co chcesz zrobić). Oczywiście wszystkie rollback / recovery / etc. jest wykonywane przez aplikację, a nie przez bazę danych, przy użyciutransaction
dokumenty i dokumenty w innych kolekcjach z tym identyfikatorem transakcji.
Czy w tej logice jest jakiś rażący błąd, który przeoczyłem lub przeoczyłem? Czy istnieje skuteczniejszy sposób na to (np. Mniej pisania / czytania z bazy danych)?