For optimistisk låsning skal du definere nogle midler til at kontrollere, om en række har ændret sig, siden du så den sidst. Lad os f.eks. bare tilføje en anden identifikator:
alter table regions_indexes add version_id integer default 1 not null;
Nu læser applikationen en række, viser dataene til brugeren og venter, indtil der trykkes på knappen. Vi skal huske værdien af version_id
vi fik.
Når knappen er klikket, udfører du alle de nødvendige beregninger. Når du er klar til at opdatere rækken, låser du rækken og kontrollerer, om version_id
har ikke ændret sig. Hvis det ikke er tilfældet, skal du øge version_id
og forpligte sig. Hvis det er tilfældet, uheld --- du er nødt til at bede brugeren om at gentage operationen, fordi nogen løber forbi ham.
Det kan se sådan ud (i pseudokode):
-- 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 fungerer ikke godt i situationer med høj samtidighed. Når konflikter ikke er sjældne, bliver du nødt til at genstarte transaktioner ofte.