W PostgreSQL wiersze zostaną zablokowane podczas ich aktualizacji - tak naprawdę to działa tak, że każda krotka (wersja wiersza) ma pole systemowe o nazwie xmin
, które wskazuje, która transakcja spowodowała powstanie tej krotki (przez wstawienie lub aktualizację) i pole systemowe o nazwie xmax
wskazujące, która transakcja wygasła, która jest krotka (przez aktualizację lub usunięcie). Po uzyskaniu dostępu do danych sprawdza każdą krotkę, aby określić, czy jest ona widoczna dla transakcji, sprawdzając aktywny "zrzut" w odniesieniu do tych wartości.
Jeśli wykonywana jest aktualizacja, a krotka odpowiadająca warunkom wyszukiwania ma wartość xmin, która będzie widoczna dla migawki i xmax aktywnej transakcji, blokuje ona oczekiwanie na zakończenie tej transakcji. Jeśli transakcja, która po raz pierwszy zaktualizowała krotkę, transakcja zostanie wznowiona i przetworzony zostanie wiersz; jeśli pierwsza transakcja zostanie zatwierdzona, twoja transakcja zostanie pobudzona i podejmie działania w zależności od poziomu izolacji obecnej transakcji.
Oczywiście, impas jest wynikiem tego, że dzieje się to w wierszach w innej kolejności. W pamięci RAM nie ma blokad na poziomie wiersza, którą można uzyskać dla wszystkich wierszy w tym samym czasie, ale jeśli wiersze są aktualizowane w tej samej kolejności, nie można mieć blokady kołowej. Niestety sugerowana składnia IN(1, 2)
nie gwarantuje tego. Różne sesje mogą mieć różne czynniki kosztu aktywne, zadanie "analiza" tła może zmienić statystyki dla tabeli pomiędzy generowaniem jednego planu a drugim, lub może wykorzystywać seqscan i być zależne od optymalizacji PostgreSQL, która powoduje nowy seqscan dołączyć do już trwającego i "zapętlać się", aby zmniejszyć dyskowe operacje we/wy.
Jeśli wykonujesz aktualizacje pojedynczo w tej samej kolejności, w kodzie aplikacji lub przy użyciu kursora, będziesz miał tylko proste blokowanie, a nie zakleszczenia. Ogólnie rzecz biorąc, relacyjne bazy danych są podatne na awarie serializacji i najlepiej jest uzyskać do nich dostęp za pośrednictwem architektury, która rozpozna je na podstawie SQLSTATE i automatycznie ponawia całą transakcję od samego początku. W PostgreSQL błąd serializacji zawsze będzie miał wartość SQLSTATE 40001 lub 40P01.
http://www.postgresql.org/docs/current/interactive/mvcc-intro.html
Dzięki! Mój powyższy przykład może spowodować zakleszczenie (ponieważ nie znamy kolejności, w której wiersze są przetwarzane w obu transakcjach)? – vyakhir
Może to spowodować impas, choć byłoby to rzadkie; w przeciwieństwie do pierwszego przykładu (wyraźnie wybierając różne zamówienia), w którym byłby on powszechny. Można wykluczyć zakleszczenia, biorąc blokadę o odpowiedniej wysokości na czas trwania każdej transakcji, która aktualizuje tabelę, ale to leczenie może być gorsze niż choroba. Więcej informacji na ten temat znajduje się w sekcji dokumentu, do której się odwołałem. – kgrittn
Ale czy blokada wydania PostgreSQL po aktualizacji wiersza, ale cała instrukcja UPDATE jeszcze się nie zakończyła? Innymi słowy, jeśli mamy takie oświadczenie jak UPDATE ... WHERE id IN (1,2,3,4,5) po aktualizacji postgresql, powiedzmy, wiersz o id = 1 i kontynuuje z wierszem o id = 2, czy zwolni identyfikator rzędu = 1? jeśli tak, to w jaki sposób zwinie wiersze, jeśli będzie to konieczne? – vyakhir