Dla optymistycznego blokowania musisz zdefiniować pewne środki, aby sprawdzić, czy wiersz się zmienił od ostatniego razu. Na przykład dodajmy kolejny identyfikator:
alter table regions_indexes add version_id integer default 1 not null;
Teraz aplikacja odczytuje jakiś wiersz, pokazuje dane użytkownikowi i czeka na kliknięcie przycisku. Musimy zapamiętać wartość version_id
mamy.
Po kliknięciu przycisku wykonujesz wszystkie niezbędne obliczenia. Gdy jesteś gotowy do aktualizacji wiersza, blokujesz wiersz i sprawdzasz, czy version_id
nie zostało zmienione. Jeśli nie, zwiększ version_id
i zobowiąż się. Jeśli tak, pech --- musisz powiedzieć użytkownikowi, aby powtórzył operację, ponieważ ktoś go wyprzedził.
Może to wyglądać tak (w pseudokodzie):
-- remember version_id
select *
from regions_indexes
where id = ... and resource_type = ...;
-- wait for user click
-- you can wait for a long time, because no lock is yet acquired
...
update regions_indexes
set current_resource = current_resource - ..., version_id = version_id + 1
where id = ... and resource_type = ...
returning version_id;
if new_version_id = old_version_id + 1 then
-- success, commit
else
-- fail, rollback
end if;
Ale optymistyczne blokowanie nie działa dobrze w sytuacji wysokiej współbieżności. Gdy konflikty nie są rzadkie, będziesz musiał często wznawiać transakcje.