Untuk penguncian optimis, Anda perlu menentukan beberapa cara untuk memeriksa apakah suatu baris telah berubah sejak Anda melihatnya terakhir kali. Misalnya, mari tambahkan pengenal lain:
alter table regions_indexes add version_id integer default 1 not null;
Sekarang aplikasi membaca beberapa baris, menunjukkan data kepada pengguna dan menunggu sampai tombol diklik. Kita harus ingat nilai version_id
kami punya.
Setelah tombol diklik, Anda melakukan semua perhitungan yang diperlukan. Saat Anda siap untuk memperbarui baris, Anda mengunci baris dan memeriksa apakah version_id
belum berubah. Jika belum, tambahkan version_id
dan berkomitmen. Jika ya, nasib buruk --- Anda harus memberi tahu pengguna untuk mengulangi operasi karena seseorang berlari lebih cepat darinya.
Ini mungkin terlihat seperti ini (dalam pseudocode):
-- 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;
Tetapi penguncian optimis tidak berfungsi dengan baik dalam situasi konkurensi tinggi. Ketika konflik tidak jarang terjadi, Anda harus sering memulai kembali transaksi.