Servlet - kolej wykonywania

0

Witam,

mam pytanie czy servlety wykonują się w kolejności jakiej zostały wywołane czy w zalezności od np. prędkości łącza klienta ? Pytam, dlatego, że chciałbym stworzyc servlet który dodaje do bazy danych konkretne wpisy, jednocześnie do innej tabeli dodaje wpis powiązany (odpowiednią metodą pobieram numer id nadany ostatniemy wpisowi w pierwszej tabeli i chce go wykorzystać w innej). Generalnie chodzi o to czy nie będzie jakiegoś konfliktu, ze np. dwie osoby wywołają servlet i pomieszają się numery id dla konkretnych wpisów ?

0

Zdecydowana większość serwerów jest wielowątkowa.
Jak najbardziej możliwa jest sytuacja, w której kod serwletu jest wykonywany jednocześnie na wielu wątkach.

Wystarczy jednak, że po wstawieniu do pierwszej tabeli atomowo otrzymasz wstawione id.

Sposób, jak to zrobić zależy od zastosowanej technologii.
W JPA nie ma problemu - id będzie w encji.
W JDBC - patrz metoda getGeneratedKeys() z java.sql.PreparedStatement
Procedura składowana - zależy od bazy danych, np. @@IDENTITY w MSSQL

0

Jeżeli wywołają to dwie osoby to nic się nie stanie ponieważ serwlety są odseparowane od siebie (nie dotyczy to oczywiście pól statycznych).

0
Koziołek napisał(a)

Jeżeli wywołają to dwie osoby to nic się nie stanie ponieważ serwlety są odseparowane od siebie (nie dotyczy to oczywiście pól statycznych).

Ale baza jest wspólna.
Jeżeli zrobi się tak:

  1. insert do tabela1
  2. select max(id) FROM tabela1
  3. insert do tabela2, jako FK wynik z 2.

to, przy równoległym wywołaniu serwletu operacje 1. i 2. mogą się przepleść na obu wątkach, tzn.

  1. insert w wątku 1 do tabela1
  2. insert w wątku 2 do tabela1
  3. select max(id) FROM tabela1 w wątku 1
  4. select max(id) FROM tabela1 w wątku 2
  5. insert do tabela2 w wątku 1, jako FK wynik z 3 (z błędnym id)
  6. insert do tabela2 w wątku 2, jako FK wynik z 4.

Operacja 3. zwróci błędny wynik (id wstawione przez drugi wątek).

Rozwiązanie tego problemu podałem wcześniej.

0

Nie o ile wiesz jak zarządzać transakcjami. Operacje będą wzajemnie niewidoczne do czasu commitu. Co więcej jeżeli wątek 1 założy lock na tabeli1 w celu wykonania insertu to wątek 2 będzie mógł się do tej tabeli dobić dopiero po commicie.

0
Koziołek napisał(a)

Nie o ile wiesz jak zarządzać transakcjami. Operacje będą wzajemnie niewidoczne do czasu commitu. Co więcej jeżeli wątek 1 założy lock na tabeli1 w celu wykonania insertu to wątek 2 będzie mógł się do tej tabeli dobić dopiero po commicie.

Ten sposób zadziała tylko, jeżeli poziom transakcji to SERIALIZABLE.
W przeciwnym wypadku możliwy jest przeplot:

  1. insert w wątku 1 do tabela1
  2. insert w wątku 2 do tabela1
  3. select max(id) FROM tabela1 w wątku 2
  4. insert do tabela2 w wątku 2, jako FK wynik z 3. (tutaj wątek 2 commituje transakcję)
  5. select max(id) FROM tabela1 w wątku 1 (odczytuje wartość zapisaną przez poprzednią transakcję)
  6. insert do tabela2 w wątku 1, jako FK wynik z 5 (z błędnym id)

Sposób, który podałem jest lepszy, gdyż:
-nie wymaga transakcji na poziomie SERIALIZABLE (co zwykle jest nieakceptowalne)
-nie wymaga dodatkowego zapytania "select max(id) FROM tabela1"
-jest krótszy i bardziej zrozumiały

@Koziołek polecam lekturę http://en.wikipedia.org/wiki/Isolation_%28database_systems%29

0

@__krzysiek85 tak właśnie myślałem, że może powstać błąd z powodu wielowątkowości. Dzięki za dokładne wytłumaczenie i podanie metody.

1 użytkowników online, w tym zalogowanych: 0, gości: 1