Czytelnicy tacy jak ty pomagają wspierać MUO. Kiedy dokonujesz zakupu za pomocą linków na naszej stronie, możemy otrzymać prowizję partnerską.

Tworzenie gotowej do produkcji aplikacji internetowej wymaga upewnienia się, że jest ona bezpieczna i skalowalna.

Jedną z najważniejszych rzeczy, które należy wiedzieć o bazach danych, jest zasada ACID, która oznacza niepodzielność, spójność, izolację i trwałość. Relacyjne bazy danych, takie jak MySQL, natywnie obsługują transakcje ACID. Ale MongoDB jest bazą danych NoSQL i domyślnie nie obsługuje transakcji ACID.

Jako programista powinieneś wiedzieć, jak wprowadzić właściwości ACID do swoich baz danych MongoDB.

Czym są transakcje bazy danych?

Transakcja bazy danych to sekwencja zapytań lub operacji bazy danych, które są wykonywane razem jako jedna jednostka w celu wykonania jednego zadania.

Transakcje bazodanowe są zgodne z koncepcjami charakterystyki ACID. Pomaga to zapewnić, że żadne zmiany nie wystąpią, chyba że wszystkie operacje zakończą się pomyślnie. Zapewnia również spójność bazy danych.

instagram viewer

Wyjaśnienie właściwości ACID

Cztery właściwości składające się na zasady ACID to:

  • Atomowość jest właściwością, która konceptualizuje transakcje jako małe jednostki programu. Oznacza to, że wszystkie zapytania działają pomyślnie lub kończą się niepowodzeniem.
  • Konsystencja stanowi, że rekordy bazy danych muszą pozostać spójne przed i po każdej transakcji.
  • Izolacja zapewnia, że ​​gdy wiele transakcji odbywa się jednocześnie, jedna nie wpływa na drugą.
  • Trwałość koncentruje się na awariach lub usterkach systemu. Zapewnia, że ​​w przypadku awarii systemu nie zostanie utracona zatwierdzona transakcja. Może to obejmować techniki niezbędne do automatycznego przywracania danych z kopii zapasowej po ponownym uruchomieniu systemu.

Jak zaimplementować transakcje bazy danych MongoDB w Node.js przy użyciu Mongoose

MongoDB stał się przez lata szeroko stosowaną technologią baz danych dzięki jego charakter NoSQL i elastyczny model oparty na dokumentach. Oferuje również możliwość lepszego i bardziej elastycznego organizowania danych niż w SQL czy relacyjnych bazach danych.

Aby zaimplementować transakcje bazy danych w MongoDB, możesz rozważyć przykładowy scenariusz w aplikacji do wystawiania ofert pracy, w której użytkownik może publikować, aktualizować lub usuwać oferty pracy. Oto prosty projekt schematu bazy danych dla tej aplikacji:

Aby kontynuować, ta sekcja wymaga podstawowej wiedzy na temat programowania Node.js i MongoDB.

Transakcje nie są obsługiwane w samodzielnych instalacjach MongoDB. Będziesz musiał użyć Zestaw replik MongoDB Lub Podzielony klaster MongoDB aby transakcje działały. Dlatego najłatwiejszym sposobem korzystania z transakcji jest utwórz instancję MongoDB hostowaną w chmurze (Atlas MongoDB). Domyślnie każda instancja bazy danych Atlas jest zestawem replik lub podzielonym na fragmenty klastrem.

Po skonfigurowaniu działającego projektu Node.js i MongoDB możesz skonfigurować połączenie z bazą danych Mongo w Node.js. Jeśli jeszcze tego nie zrobiłeś, zainstaluj mangustę, uruchamiając npm zainstaluj mangustę w twoim terminalu.

import mangusta z 'mangusta'

niech MONGO_URL = proces.env. MONGO_URL || 'URL-twojej-bazy-danych-mongo';

pozwalać połączenie;
konst połączDb = asynchroniczny () => {
próbować {
czekać na mongoose.connect (MONGO_URL, {
useNewUrlParser: PRAWDA,
użyj ujednoliconej topologii: PRAWDA,
});

log konsoli ("PODŁĄCZONY DO BAZY DANYCH");
połączenie = połączenie.mangusta;
} złapać (błąd) {
błąd konsoli ("POŁĄCZENIE Z BAZĄ DANYCH NIE POWIODŁO SIĘ!");
konsola.błąd(błądzić.wiadomość);
proces.Wyjście(1); // zamknij aplikację, jeśli połączenie z bazą danych nie powiedzie się
}
};

Powinieneś zapisać połączenie w zmiennej, abyś mógł użyć go do zainicjowania transakcji później w programie.

Możesz zaimplementować kolekcje użytkowników i zadań w następujący sposób:

konst schemat użytkownika = nowy mangusta. Schemat({
nazwa: Strunowy,
e-mail: Strunowy,
Oferty pracy: [mangusta. Schemat. typy. Identyfikator obiektu]
});

konst schemat pracy = nowy mangusta. Schemat({
tytuł: Strunowy,
Lokalizacja: Strunowy,
wynagrodzenie: Strunowy,
plakat: mangusta.Schemat.Typy.Id obiektu
});

const userCollection = mongoose.model('użytkownik', schemat użytkownika);
const jobCollection = mongoose.model('stanowisko', schemat pracy);

Możesz napisać funkcję, aby dodać użytkownika do bazy danych w następujący sposób:


konst utwórz użytkownika = asynchroniczny (użytkownik) => {
konst nowyUżytkownik = czekać na userCollection.create (użytkownik);
konsola.log("Użytkownik dodany do bazy danych");
konsola.log (nowy użytkownik);
}

Poniższy kod ilustruje funkcję tworzenia zadania i dodawania go do listy zadań plakatu za pomocą transakcji bazy danych.


konst utwórzZadanie = asynchroniczny (praca) => {
konst { userEmail, tytuł, lokalizacja, wynagrodzenie } = praca;

// pobierz użytkownika z bazy danych
konst użytkownik = czekać na userCollection.findOne({ e-mail: E-mail użytkownika });

// rozpocznij sesję transakcyjną
konst sesja = czekać na połączenie.rozpocznijSesję();

// uruchamia wszystkie zapytania do bazy danych w bloku try-catch
próbować {
czekać na sesja.startTransakcja();

// utwórz zadanie
konst nowa praca = czekać na jobCollection.create(
[
{
tytuł,
Lokalizacja,
wynagrodzenie,
plakat: user._id,
},
],
{ sesja }
);
konsola.log("Utworzono nowy pomyślnie!”);
konsola.log (noweZadanie[0]);

// dodaj ofertę pracy do listy użytkowników opublikowanych ofert pracy
konst nowyJobId = nowyPraca[0]._ID;
konst dodany do użytkownika = czekać na userCollection.findByIdAndUpdate(
identyfikator użytkownika,
{ $addToSet: { Oferty pracy: nowyJobId } },
{ sesja }
);

konsola.log("Pomyślnie dodano zadanie do listy zadań użytkownika");
konsola.log (dodany do użytkownika);

czekać na sesja.commitTransakcja();

konsola.log("Pomyślnie przeprowadzona transakcja DB");
} złapać (e) {
konsolabłąd (e);
konsola.log("Nie udało się zakończyć operacji na bazie danych");
czekać na session.abortTransaction();
} Wreszcie {
czekać na sesja.endSesja();
konsola.log("Zakończona sesja transakcji");
}
};

A tworzyć zapytanie uruchamiane w ramach transakcji zwykle przyjmuje i zwraca tablicę. Możesz to zobaczyć w powyższym kodzie, gdzie tworzy Nowa praca i przechowuje jego _ID nieruchomość wnowy JobId zmienny.

Oto przykład działania powyższych funkcji:

konst fałszywy użytkownik = {
imię: "Timmy Omolana",
e-mail: „[email protected]”,
};

konst mockJob = {
tytuł: "Kierownik Sprzedaży",
lokalizacja: „Lagos, Nigeria”,
wynagrodzenie: „$40,000",
userEmail: "[email protected]", // e-mail utworzonego użytkownika
};

konst serwer startowy = asynchroniczny () => {
czekać na połączDb();
czekać na utwórz użytkownika (pozorny użytkownik);
czekać na utwórzZadanie (mockJob);
};

startSerwer()
.Następnie()
.catch((błąd) => konsola.log (błąd));

Jeśli zapiszesz ten kod i uruchomisz go za pomocą np start albo węzeł polecenie, powinno wygenerować takie wyjście:

Innym sposobem implementacji transakcji ACID w MongoDB przy użyciu Mongoose jest użycie z transakcją() funkcjonować. Takie podejście zapewnia niewielką elastyczność, ponieważ uruchamia wszystkie zapytania wewnątrz funkcji wywołania zwrotnego, które przekazujesz jako argument do funkcji.

Możesz użyć refaktoryzacji powyższej transakcji bazy danych z transakcją() lubię to:

konst utwórzZadanie = asynchroniczny (praca) => {
konst { userEmail, tytuł, lokalizacja, wynagrodzenie } = praca;

// pobierz użytkownika z bazy danych
konst użytkownik = czekać na userCollection.findOne({ e-mail: E-mail użytkownika });

// rozpocznij sesję transakcyjną
konst sesja = czekać na połączenie.rozpocznijSesję();

// uruchamia wszystkie zapytania do bazy danych w bloku try-catch
próbować {
konst transakcjaSukces = czekać na sesja.z transakcją(asynchroniczny () => {
konst nowa praca = czekać na jobCollection.create(
[
{
tytuł,
Lokalizacja,
wynagrodzenie,
plakat: user._id,
},
],
{ sesja }
);

konsola.log("Utworzono nowy pomyślnie!”);
konsola.log (noweZadanie[0]);

// dodaj ofertę pracy do listy użytkowników opublikowanych ofert pracy
konst nowyJobId = nowyPraca[0]._ID;
konst dodany do użytkownika = czekać na userCollection.findByIdAndUpdate(
identyfikator użytkownika,
{ $addToSet: { Oferty pracy: nowyJobId } },
{ sesja }
);

konsola.log("Pomyślnie dodano zadanie do listy zadań użytkownika");
konsola.log (dodany do użytkownika);
});

Jeśli (sukces transakcji) {
konsola.log("Pomyślnie przeprowadzona transakcja DB");
} w przeciwnym razie {
konsola.log("Transakcja nie powiodła się");
}
} złapać (e) {
konsolabłąd (e);
konsola.log("Nie udało się zakończyć operacji na bazie danych");
} Wreszcie {
czekać na sesja.endSesja();
konsola.log("Zakończona sesja transakcji");
}
};

Dałoby to taki sam wynik jak poprzednia implementacja. Możesz swobodnie wybrać styl, którego chcesz użyć podczas implementacji transakcji bazodanowych w MongoDB.

Ta implementacja nie używa zatwierdz Transakcja() I przerwanie transakcji() Funkcje. To dlatego, że z transakcją() funkcja automatycznie zatwierdza udane transakcje i przerywa nieudane. Jedyną funkcją, którą należy wywoływać we wszystkich przypadkach, jest funkcja sesja.endSesja() funkcjonować.

Implementacja transakcji bazy danych ACID w MongoDB

Transakcje bazy danych są łatwe w użyciu, jeśli są wykonywane poprawnie. Powinieneś teraz zrozumieć, jak działają transakcje Database w MongoDB i jak możesz je zaimplementować w aplikacjach Node.js.

Aby dokładniej zbadać ideę transakcji ACID i sposób ich działania w MongoDB, rozważ zbudowanie portfela fintech lub aplikacji do blogowania.