För optimistisk låsning måste du definiera några sätt att kontrollera om en rad har ändrats sedan du såg den senast. Låt oss till exempel bara lägga till en annan identifierare:
alter table regions_indexes add version_id integer default 1 not null;
Nu läser applikationen någon rad, visar data för användaren och väntar tills knappen klickas. Vi måste komma ihåg värdet på version_id
vi fick.
Efter att knappen har klickats utför du alla nödvändiga beräkningar. När du är redo att uppdatera raden låser du raden och kontrollerar om version_id
har inte ändrats. Om den inte har det, öka version_id
och begå. Om den har det, otur --- du måste säga åt användaren att upprepa operationen eftersom någon kör ifrån honom.
Det kan se ut så här (i pseudokod):
-- 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;
Men optimistisk låsning fungerar inte bra i situationer med hög samtidighet. När konflikter inte är sällsynta måste du starta om transaktioner ofta.