Oracle
 sql >> Baza danych >  >> RDS >> Oracle

Czy SELECT FOR UPDATE zapobiega wstawianiu innych połączeń, gdy wiersz nie jest obecny?

MySQL

WYBIERZ... DO AKTUALIZACJI za pomocą AKTUALIZACJI

Korzystanie z transakcji z InnoDB (automatyczne zatwierdzanie wyłączone), SELECT ... FOR UPDATE umożliwia jednej sesji tymczasowe zablokowanie określonego rekordu (lub rekordów), aby żadna inna sesja nie mogła go zaktualizować. Następnie, w ramach tej samej transakcji, sesja może faktycznie wykonać UPDATE w tym samym rekordzie i zatwierdź lub wycofaj transakcję. Umożliwiłoby to zablokowanie rekordu, aby żadna inna sesja nie mogła go zaktualizować, podczas gdy być może wykonasz inną logikę biznesową.

Osiąga się to za pomocą blokowania. InnoDB wykorzystuje indeksy do blokowania rekordów, więc blokowanie istniejącego rekordu wydaje się łatwe — po prostu zablokuj indeks dla tego rekordu.

WYBIERZ... DO AKTUALIZACJI za pomocą WSTAW

Jednak, aby użyć SELECT ... FOR UPDATE z INSERT , jak zablokować indeks dla rekordu, który jeszcze nie istnieje? Jeśli używasz domyślnego poziomu izolacji REPEATABLE READ , InnoDB będzie również wykorzystywać gap zamki. Tak długo, jak znasz id (lub nawet zakres identyfikatorów) do zablokowania, InnoDB może zablokować przerwę, aby żaden inny rekord nie mógł zostać wstawiony w tę przerwę, dopóki nie skończymy z tym.

Jeśli Twój id kolumna była kolumną z automatycznym przyrostem, a następnie SELECT ... FOR UPDATE z INSERT INTO byłoby problematyczne, ponieważ nie wiedziałbyś, jaki jest nowy id było, dopóki go nie włożysz. Jednak ponieważ znasz id który chcesz wstawić, SELECT ... FOR UPDATE z INSERT zadziała.

OSTRZEŻENIE

Na domyślnym poziomie izolacji SELECT ... FOR UPDATE na nieistniejącym rekordzie nie blokować inne transakcje. Tak więc, jeśli dwie transakcje wykonają SELECT ... FOR UPDATE w tym samym nieistniejącym rekordzie indeksu, oboje otrzymają blokadę i żadna transakcja nie będzie w stanie zaktualizować rekordu. W rzeczywistości, jeśli spróbują, zostanie wykryty impas.

Dlatego, jeśli nie chcesz radzić sobie z impasem, możesz po prostu wykonać następujące czynności:

WSTAW DO...

Rozpocznij transakcję i wykonaj INSERT . Wykonaj logikę biznesową i zatwierdź lub wycofaj transakcję. Jak tylko wykonasz INSERT na nieistniejącym indeksie rekordu przy pierwszej transakcji, wszystkie inne transakcje zostaną zablokowane, jeśli spróbują INSERT rekord z tym samym unikalnym indeksem. Jeśli druga transakcja spróbuje wstawić rekord o tym samym indeksie po tym, jak pierwsza transakcja zatwierdzi wstawienie, otrzyma błąd „duplikat klucza”. Postępuj odpowiednio.

WYBIERZ... ZABLOKUJ W TRYBIE UDOSTĘPNIANIA

Jeśli wybierzesz za pomocą LOCK IN SHARE MODE przed INSERT , jeśli poprzednia transakcja wstawiła ten rekord, ale jeszcze nie została zatwierdzona, SELECT ... LOCK IN SHARE MODE zostanie zablokowany do czasu zakończenia poprzedniej transakcji.

Aby zmniejszyć ryzyko zduplikowanych błędów kluczy, zwłaszcza jeśli przytrzymasz blokady na chwilę podczas wykonywania logiki biznesowej przed ich zatwierdzeniem lub wycofaniem:

  1. SELECT bar FROM FooBar WHERE foo = ? LOCK FOR UPDATE
  2. Jeśli nie zostaną zwrócone żadne rekordy,
  3. INSERT INTO FooBar (foo, bar) VALUES (?, ?)


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Tekst Oracle uciekający za pomocą nawiasów klamrowych i symboli wieloznacznych

  2. Korzystanie z kolumny Oracle XMLType w trybie hibernacji

  3. Witryna niedostępna i kanał na Twitterze

  4. Jak można stwierdzić, czy używany jest pakiet, procedura lub funkcja PL/SQL?

  5. Czy aktualizacja SQL wpłynie na jej podzapytanie podczas wykonywania aktualizacji?