За оптимистично заключване трябва да дефинирате някакво средство за проверка дали даден ред се е променил, откакто сте го видели последния път. Например, нека просто добавим друг идентификатор:
alter table regions_indexes add version_id integer default 1 not null;
Сега приложението чете някакъв ред, показва данните на потребителя и чака, докато се щракне върху бутона. Трябва да запомним стойността на version_id
имаме.
След като натиснете бутона, извършвате всички необходими изчисления. Когато сте готови да актуализирате реда, заключвате реда и проверявате дали version_id
не се е променило. Ако не е, увеличете version_id
и се ангажирайте. Ако има, лош късмет --- трябва да кажете на потребителя да повтори операцията, защото някой го е изпреварил.
Може да изглежда така (в псевдокод):
-- 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;
Но оптимистичното заключване не работи добре в ситуация на висока едновременност. Когато конфликтите не са редки, ще трябва често да рестартирате транзакциите.