2010-05-11 11 views
5

Rozważmy taką sytuację:Czy transakcja zatrzymuje wszystkie problemy z kondycją wyścigu w MySQL?

  1. rozpocząć transakcji
  2. Insert 20 rekordów do tabeli z auto_increment klucza
  3. Uzyskaj identyfikator pierwsza wkładka (powiedzmy to 153)
  4. zaktualizować wszystkie rekordy w tej tabeli gdzie id >= 153
  5. Commit

Czy krok 4 jest bezpieczny?

Oznacza to, że jeśli kolejne żądanie przychodzi prawie dokładnie w tym samym czasie i wstawia kolejne 20 rekordów po kroku 2 powyżej, ale przed krokiem 4, czy wystąpi warunek wyścigu?

+0

Dlaczego miałbyś mieć osobny krok aktualizacji, a nie tylko wstawianie poprawnych danych? To raczej dziwne. Nie musisz martwić się o "warunki wyścigu", jeśli włożyłeś poprawne dane w pierwszej kolejności. Aktualizacja "WHERE id> 153" jest również bardzo dziwnym zapytaniem. Identyfikatory automatyczne inkrementacji nie mają dla nich żadnej logiki, więc nigdy nie powinieneś (o ile mi wiadomo) aktualizować wyłącznie na podstawie identyfikatora. I na koniec nie znam żadnej funkcji "first insert id". –

+0

@ButtleButkus http://dev.mysql.com/doc/refman/5.0/en/information-functions.html#function_last-insert-id "Jeśli wstawisz wiele wierszy za pomocą pojedynczej instrukcji INSERT, funkcja LAST_INSERT_ID() zwróci wartość wygenerowany dla pierwszego wstawionego wiersza " – nickf

+0

Masz rację co do LAST_INSERT_ID(), ale nie zmienia to faktu, że pytanie wydaje się być hipotetyczną sytuacją, która nigdy nie istniałaby, gdyby przestrzegano podstawowej struktury i procedury bazy danych. Dlaczego kryterium aktualizacji byłoby kiedykolwiek wartością bezsensownego identyfikatora? Nie mogę wymyślić żadnego powodu. Nie nazwałbym tego "warunkiem wyścigu", ponieważ jest to bezsensowne. Dlaczego miałbyś aktualizować natychmiast po wstawieniu, kiedy mógłbyś po prostu wstawić poprawne wartości na początek?To są prawdziwe powody, dla których to pytanie nie ma sensu. –

Odpowiedz

5

Oznacza to, że jeśli inne żądanie pojawi się niemal dokładnie w tym samym czasie i wstawi kolejne 20 rekordów po kroku 2 powyżej, ale przed krokiem 4, czy wystąpi warunek wyścigu?

Tak, będzie.

Zapisy 21 na 40 zostaną zablokowane przez transakcję 2.

Transakcja 1 zostanie zablokowana i zaczekaj, aż transakcja 2 zostanie zatwierdzona lub wycofana.

Jeśli transakcja 2 zobowiązuje, wtedy transakcja 1 zaktualizuje 40 rekordy (w tym te, wprowadzone przez transakcji 2)

+1

Czy możesz wyjaśnić? Czy mówisz, że jest jakiś problem, czy nie? – nickf

+0

@nickf: zobacz aktualizację postu. – Quassnoi

0

I nie sądzę, że to może być skatalogowana jako warunek wyścigu, ale raczej jako DMBS określonego zachowania. Zasadniczo, jeśli DBMS zablokuje nowo wstawione rekordy, pierwsza transakcja nie zobaczy rekordów od drugiej, dopóki druga transakcja nie zostanie zatwierdzona.

I oczywiście jest kwestia blokowania stołu, jeśli pierwsza transakcja zapisuje - blokuje stół, a druga zostanie zablokowana przy zapisywaniu, aż do ukończenia pierwszego. Nie wiem jednak, czy standardowy mysql oferuje taką funkcję. Znam serwer MSSQL, który robi.