Dziwne zachowanie transakcji postgress

0

Cześć, tworzę przykładową bazę danych dla szkoły językowej, mam dwie tabele 'kursy' oraz 'zajęcia', w tabeli kursy są podstawowe informacje o kursie tzn. język, poziom, id kursu itd., natomiast w tabeli zajęcia zapisuje poszczególne dni i godziny zajęć w ramach poszczególnych kursów z tabeli 'kursy', kurs jest tutaj identyfikowany na podstawie id kursu jako klucza obcego z tabeli 'kursy'
, na tabeli zajęcia działa trigger który w momencie dodawania wpisów do 'zajecia' sprawdza np czy zajęcia nie nachodzą na siebie, lub czy lektorzy nie prowadzą w tym samym czasie różnych zajęć, gdy któryś z tych warunków jest nie spełniony funkcja wyzwalana przez trigger zwraca NULL i teraz do sedna problemu, najpierw dodaje kurs do tabeli 'kursy' a potem zajecia do tabeli 'zajecia' może się jednak okazać że zajęcia nie zostaną dodane z wyżej wymienionych powodów więc w tym momencie również dodanie kursu musi zostać cofnięte i tak trigger działa na pewno porawnie a kod zapytania z transakcją wygląda następująco :

 
BEGIN ;
	INSERT INTO kursy(jezyk_id, poziom_id, liczba_miejsc, wolne_miejsca, cena, data_start, data_koniec)
	VALUES(1, 1, 10, 10,1000,'2011-06-08', '2011-06-25');
           INSERT INTO zajecia(kurs_id, lektor_id, dzien_id, godzina_start, godzina_koniec) VALUES(5, 1, 1,'07:00:00', '08:00:00') ;
COMMIT;

Dane zostały tak dobrane aby trigger zwrócił NULL ,problem w tym że transakcja kończy się COMMITem, a efektem tego jest dodanie wpisy do 'kursy' przy równoczesnym nie dodaniu 'zajec' gdyż uniemożliwia to funkcja wywołana przez trigger. Proszę o wszelkie sugestie, może nie dokońca rozumie działanie transakcji ?

1

działa dokładnie tak jak to sobie napisałeś. Żeby transakcję cofnąć to trzeba zamiast commit zrobić rollback

0

Pomimo tego ,że w zapytaniu jest Commit w przypadku nie wykonania się któregoś z insertów powinien wykonać się Rollback, dodam jeszcze że to zapytanie jest wykonywane prze funkcje pg_query w całosci, próbowałem go też rozbić na kawałki tzn, najpierw begin i te dwa inserty potem dopiero commit.

2

jeszcze raz powoli i dużymi literami
J E Ś L I C H C E S Z A B Y T R A N S A K C J A Z O S T A Ł A C O F N I Ę T A T O M U S I S Z W Y K O N A Ć R O L L B A C K A N I E C O M M I T. A u ciebie ZAWSZE wykonuje się commit. Dotarło?

0

Heh teraz już dotarło dzięki, ale powiedz czy jest możliwa sytuacja w której pomimo Commita wykonuje się Rollback, bo jestem pewien że miałem taki przypadek chyba że był to sen ..... ?

1

w prawidłowo działającej bazie nie ma takiej możliwości ponieważ commit jak i rollback kończą transakcję i jeśli zrobisz commit to kończy Ci się transakcja i rollback powinien rzucić błędem, że nie ma czego cofnąć.

Inna sprawa, że prawidłowo w kodzie powinno to (dodawanie danych w transakcji) wyglądać tak

//wystartowanie transakcji
try
  //wykonanie 1-go insert/update/delete
  //wykonanie 2-go insert/update/delete
  //wykonanie n-tego insert/update/delete
  //zatwierdzenie transakcji
except
  //cofnięcie transakcji
end;

U Ciebie po prostu nie masz nigdzie rollback. Poza tym aby to działało to Twój triger, w razie niepoprawnych danych, musiał by rzucić wyjątkiem, który przejdzie do delphi

0

Czyli w php sytuacja jest analogiczna tzn. w bloku try wykonać zapytanie no i oczywiście porawić triggera żeby zwracał wyjątek ?
bo jeszcze tak próbowałem to zrobić w ten sposób ,że ładuje do pq_query BEGIN; potem pierwszego inserta jesli się wykonał to pq_query z drugim insertem jeśli nie ROLLBACK, z kolei jesli ten drugi insert się wykonał to COMMIT jesli nie ROLLBACK, niestety nic z tego nie wyszło:D ma to w ogóle sens takie podejście ?

0

Hallo pepek89!

How to perform a mysql rollback in php?

Pozdrawiam
Markus

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