Bosh sahifa Wiki Optimistic locking

Optimistic locking

Optimistic locking — bir nechta foydalanuvchi bir obyektni kamdan-kam bir vaqtda o‘zgartiradi degan taxmin bilan, o‘qish davomida database lockini ushlamasdan conflictni yozish paytida aniqlash usuli. U ko‘pincha version raqami, timestamp yoki oldingi qiymatni update shartiga qo‘shish orqali bajariladi.

Version ustuni

Jadvaldagi har satr version qiymatiga ega bo‘lishi mumkin. Application obyektni o‘qiganda versionni ham oladi. Update faqat joriy version o‘qilgan qiymatga teng bo‘lsa bajariladi:

UPDATE documents
SET content = :content,
    version = version + 1
WHERE id = :id AND version = :old_version;

Ta’sirlangan satrlar soni nol bo‘lsa satr o‘chirilgan yoki boshqa transaction versionni o‘zgartirgan. Application conflict deb javob beradi, yangi holatni o‘qiydi va biznes qoidasiga qarab merge yoki retry qiladi.

Lost update’ni cheklash

Version shartisiz ikki client bir xil obyektni o‘qib, keyin ketma-ket to‘liq update qilsa oxirgi yozuv birinchi o‘zgarishni yo‘qotadi. Optimistic check ikkinchi update’ni jim overwrite qilishdan saqlaydi. U faqat shartga kiritilgan row va version chegarasida ishlaydi.

Bir biznes invariant bir nechta satrga bog‘liq bo‘lsa har satr versionini alohida tekshirish yetmasligi mumkin. Aggregate root uchun umumiy version, serializable transaction yoki database constraint kerak bo‘ladi.

Token tanlash

Monoton integer tushunarli va ishonchli. Timestamp resolution yetarli bo‘lmasa bir vaqtdagi ikki update bir xil qiymat olishi mumkin; server clock farqi ham muammo keltiradi. Database-generated row version yoki opaque ETag platformaga xos yechim beradi.

Butun eski row qiymatini WHERE shartiga qo‘shish alohida version ustunisiz conflict topadi, lekin NULL semantikasi, katta ustun va trigger o‘zgarishi queryni murakkablashtiradi. Hash ishlatilsa collision ehtimoli va qaysi ustunlar qamralgani aniqlanadi.

HTTP va ETag

REST API resource versionini ETag sifatida beradi. Client update’da If-Match header bilan o‘qigan ETagni yuboradi. Server mos kelmasa 412 Precondition Failed qaytarishi mumkin. Bu database versionini transport protokoliga olib chiqadi, ammo ETag representationga yoki resource state’ga bog‘langanini API belgilaydi.

Retry va foydalanuvchi tajribasi

Counter increment kabi commutative amal yangi qiymat bilan avtomatik retry qilinishi mumkin. Matn tahririda ko‘r-ko‘rona retry boshqa foydalanuvchi o‘zgarishini yana bosib ketadi. UI oldingi, joriy va foydalanuvchi variantini ko‘rsatib merge talab qilishi mumkin.

Retry soni cheklanadi va jitter ishlatiladi. Yuqori conflict ko‘rsatkichi optimistic model workloadga mos emasligini bildiradi; pessimistic row lock, queue yoki data partitioning kerak bo‘lishi mumkin.

ORM va database

Ko‘p ORM version fieldni mapping qilib, update row count nol bo‘lsa concurrency exception chiqaradi. Bulk update ORM version tekshiruvini chetlab o‘tishi mumkin. Trigger versionni oshirsa ORM yangi qiymatni qayta olishi kerak.

Optimistic locking database transaction o‘rnini bosmaydi. Update statementning o‘zi atomar bajariladi, bog‘liq bir nechta yozuv esa transaction ichida commit qilinadi. Unique constraint va foreign key parallel writerlardan qat’i nazar invariantni oxirgi qatlamda himoya qiladi.

O‘chirish bilan conflict

Client obyektni o‘qigach boshqa transaction uni o‘chirishi mumkin. Versionli update nol satr qaytarganda “o‘zgargan” va “o‘chirilgan” holatni ajratish uchun yangi read kerak bo‘ladi. Soft delete ham versionni oshiradi, aks holda eski client satrni yangilab tasodifan qayta faol holatga keltirishi mumkin.

Bog‘liq tushunchalar

Concurrency control, Lost update, Version column, ETag, Conditional request, Pessimistic locking, Transaction, Compare-and-swap