konto usunięte

Temat: Poziom izolacji - nie działa ? Hibernate,PostgreSQL....

Mam pytanie.
Mam proces rejestracji ... przycisk zakończ uruchamia metodę serwisową.
Trasnsacional
createAccount(){
sprawdzczykontoJusIstnieje() - zapytanie do bazy (Transactional(readOnly)
jesli nie to wstaw dane do bazy - zapisz
}
Póki co mogę kilknąć w przycisk zapisz np 10 razy ... to wywołuje za każdym raze tę metodę
Ustawiełm poziom izolacji na READ_COMMITED transakcja może odczytywać tylko wiersze zapisane.

Ustawiłem propagioion na REQUIRES_NEW - ale to chyba zadziała tylko wtedy, kiedy wywoływałbym metodę z innej klasy, wtedy następuje propagacja.. Spring domyślnie tworzy logiczne transakcjje, a na bazie istnieje jedna fizyczna - REQUIRED

Teraz dzieje się coś dziwnego. Pierwsze wywołanie metody nie zdązy zapisac dane a drugie wywolanie już sprawdza czy takie konto istnieje i przechodzi dalej, Wtedy I wywołanie zapisało dane i drugie próbuje - ale że jako jest unique zalozany na adres email to leci wyjatek.
Nawet przy ustawieniu poziomu SERIALIZABLE tak sie dzieje...
Moze to dzieje sie dlatego, ze Spring zawiesza wywolanie pierwszej metody(transakcji) i rozpoczyna druga?

Spring 3.2.3
Hibernate 4.2.9
PostgreSql 9.2

REJESTRACJA:

REQUEST(POST) ---> Przycisk: Zakończ: x2

T1 : createAccount(User user)
T2: createAccount(User user) . Rozumiem, że T1 i T2 to logiczne transakcje Springa, a w BD jest jedna fizyczna?\

<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">

<property name="dataSource">
<ref bean="dataSource" />
</property>
<property name="packagesToScan" value="com.sharcs.models.database" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.max_fetch_depth">5</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>

<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.format_sql">true</prop>
<!-- <prop key="hibernate.generate_statistics">true</prop> -->

<prop key="hibernate.use_sql_comments">true</prop>

</props>
</property>
</bean>



@Transactional(isolation=Isloation.READ_COMMITTED)
public int createAccount(User user) {
if (isAccountCreated(user.getUserEmail()) == false) {



@Transactional(readOnly=true)
isAccountCreated(Streing email)

konto usunięte

Temat: Poziom izolacji - nie działa ? Hibernate,PostgreSQL....

Pierwsze primo spring robi proxy... Czyli masz swój obiekt, na nim proxy i to jest dostępne jak zrobisz np. getBean. Czyli jak zawołasz this.isAccountCreated() - zawołasz na swoim obiekcie, czyli nie przez proxy, czyli bez springowych adnotacji.
Drugie primo. W tym przypadku, chyba lepiej łapać wyjątek i np. powiadamiać użytkownika niż liczyć na to, że wszystko się ładnie zgra w czasie... Można oczywiście zrobić jakiegoś singletona, który będzie całość synchronizował, ale to jest tylko proszenie się o kłopoty. Można wreszcie zrobić application locka na bazie i zapewnić synchronizację - w sensie, żeby nikt się nie zapytał o to, czy konto jest utworzone jeżeli akurat ktoś tworzy konto. Jest taka możliwość, ale uważam, że to przerost formy nad treścią. Linki:
http://www.postgresql.org/docs/9.1/static/explicit-loc...
W szczególności:
http://www.postgresql.org/docs/9.1/static/explicit-loc...

http://www.postgresql.org/docs/9.1/static/functions-ad...
Table 9-62. Advisory Lock Functions - funkcje, którymi można operować na lockach.

Co ciekawe da się zdjąć takiego locka bez robienia commit / rollback. Zakończenie transakcji zdejmuje locka - tego, jak i każdego innego.

konto usunięte

Temat: Poziom izolacji - nie działa ? Hibernate,PostgreSQL....

"Pierwsze primo spring robi proxy... Czyli masz swój obiekt, na nim proxy i to jest dostępne jak zrobisz np. getBean. Czyli jak zawołasz this.isAccountCreated() - zawołasz na swoim obiekcie, czyli nie przez proxy, czyli bez springowych adnotacji. "

Dużo mi to nie mówi o moim problemie.
Jak zrobić tak aby zapewnić to po przez izolacje.

Service layer:
@Service
class AccountManager

accountManager.createAccount(User user). -

createAccount() - @Transactional

createAccount() woła isAccountCreated(String email) - @Transactional

Wszystkie metdoy z AccountManager.
Czemu drugir uruchomienie nie czeka az pierwsze zapisze pomimo dobrego poziomu izolacji ?Ten post został edytowany przez Autora dnia 27.09.14 o godzinie 15:13

konto usunięte

Temat: Poziom izolacji - nie działa ? Hibernate,PostgreSQL....

Kamil J.:
"Pierwsze primo spring robi proxy... Czyli masz swój obiekt, na nim proxy i to jest dostępne jak zrobisz np. getBean. Czyli jak zawołasz this.isAccountCreated() - zawołasz na swoim obiekcie, czyli nie przez proxy, czyli bez springowych adnotacji. "

Dużo mi to nie mówi o moim problemie.
A to już tylko do dokumentacji mogę odesłać.
Jak zrobić tak aby zapewnić to po przez izolacje.
Izolacja służy do czegoś innego.
Service layer:
@Service
class AccountManager

accountManager.createAccount(User user). -

createAccount() - @Transactional

createAccount() woła isAccountCreated(String email) - @Transactional

Wszystkie metdoy z AccountManager.
Czemu drugir uruchomienie nie czeka az pierwsze zapisze pomimo dobrego poziomu izolacji ?

Masz dwa requesty - każdy to osobny wątek. Skąd pomysł, że mają na siebie czekać? @Transactional oznacza, że będą transakcje, poziomy izolacji tyczą się tego co poszczególne transakcje będą wiedzieć o pracy innych...

Jak 100 użytkowników chce założyć konto - to mają na siebie czekać? No, mi się wydaje, że nie. Co najwyżej jak jeden kliknie 100 razy i wyśle 100 razy te same dane - wtedy ma się dodać 1 konto - reszta wywołań ma się zakończyć błędem. W każdym razie - takiej funkcjonalności bym się spodziewał...

konto usunięte

Temat: Poziom izolacji - nie działa ? Hibernate,PostgreSQL....

Wiem, dokładnie co to są beany, obiekty proxy, DI przez kontener Springa.
Chodzi mi o to, że to właśnie przez poziom izolacji mogę zapewnić, że jedna transakcja nie dostanie danych, ktore nie zostały zapisane przez inne .
Mam na myśli anomalie np. brudne odczyty. Tylko w moim przypadku pomimo, założenia odpowiedniego poziomu izolacji, to nie działa.

Ok w moim przypadku, zawsze się założy 1 konto.
Ale raz będzie tak, że metoda isAccountCreated będące w transakcji metody createAccount przeczyta, że taki wpis jest w bazie w sensie user o danym email, a drugi raz nie!!!!
Ale i tak nie będize dwóch kont bo na email jest unique założony . Wtedy leci wyjątek.
Chciałem to mieć zrobione w ten sposb skoro jedna transakcja zapisuje dane - a druga czyta to ta co czyta czeka az bedzie commit na tamtej i wtedy przeczyta ze email juz jest taki w bd .

konto usunięte

Temat: Poziom izolacji - nie działa ? Hibernate,PostgreSQL....

Kamil J.:
Wiem, dokładnie co to są beany, obiekty proxy, DI przez kontener Springa.
Chodzi mi o to, że to właśnie przez poziom izolacji mogę zapewnić, że jedna transakcja nie dostanie danych, ktore nie zostały zapisane przez inne .
Mam na myśli anomalie np. brudne odczyty.

Fajne
Tylko w moim przypadku pomimo, założenia odpowiedniego poziomu izolacji, to nie działa.
>
No właśnie - działa. Tak to działa. Jak jedna transakcja zrobi insert to druga tego nie zobaczy do commita - tak?
No a jak druga nie widzi - to też sobie rekord może dodać. Jak ta druga pierwsza zrobi commit - pierwsza się wywali na commicie. Tak jak to ze 3 razy w tym wątku napisałem.
Ok w moim przypadku, zawsze się założy 1 konto.
Ale raz będzie tak, że metoda isAccountCreated będące w transakcji metody createAccount przeczyta, że taki wpis jest w bazie w sensie user o danym email, a drugi raz nie!!!!
Ale i tak nie będize dwóch kont bo na email jest unique założony . Wtedy leci wyjątek.
No dokładnie. Mój pierwszy post w tym wątku są możliwe rozwiązania problemu...
Chciałem to mieć zrobione w ten sposb skoro jedna transakcja zapisuje dane - a druga czyta to ta co czyta czeka az bedzie commit na tamtej i wtedy przeczyta ze email juz jest taki w bd .

Rewelacja - w tym poście dałem zestaw linków. Problem jest dość dobrze znany. Sprowadza się do sytuacji, w której transakcja musi wiedzieć o stanie bazy... Generowanie klucza głównego jest problemem, z którym baza sobie radzi. No, ale np. numerowanie faktur? Nie może być tzw. dziur. To zakładanie kont użytkownikom można potraktować podobnie. Chodzi o to, że to isAccountCreated nie może zostać zawołane jeżeli ktoś akurat zakłada konto. Czyli stawiamy locka sprawdzamy co jest do zrobienia, robimy i kończymy zabawę. Jak ktoś w tzw. między czasie też chce - poczeka. Advisory Lock - linki w pierwszym poście. Dla mnie to jest EOT. Pomysły, żeby pisać o tym samym w inny sposób właśnie wyczerpałem.

konto usunięte

Temat: Poziom izolacji - nie działa ? Hibernate,PostgreSQL....

A nie dlatego, nie czeka, że jest OPTIMISTICK_LOCK ?
W sumie spróbuje inaczej to rozwiązać. po prostu robiąc inserta i łapiąc odpowiedni wyjątek. Musze się zastanwoić bo nie chec PESIMISTICK _LOCKA zakładać...

Następna dyskusja:

Spring+Hibernate+Liferay




Wyślij zaproszenie do