← головнаПрограмування

Pessimistic Lock у Rails: що це таке і коли застосовувати. Які є альтернативи?

Дізнайтесь, як використовувати pessimistic lock у Rails для захисту від одночасних змін записів. Порівнюємо з optimistic locking і atomic updates.

ЗмістНатисність на посилання, щоб перейти до потрібного місця
Якщо ви працюєте з Rails і вам потрібно уникнути одночасної зміни одного запису декількома процесами, варто звернути увагу на механізм блокування записів у базі даних. Один із найнадійніших способів зробити це — pessimistic locking.

Що таке pessimistic lock?

Pessimistic lock (песимістичне блокування) означає, що запис у базі даних фізично блокується для змін з інших потоків або процесів, поки поточна операція не завершиться. Тобто якщо один процес отримав блокування на запис, інші мусять чекати, поки він його звільнить.
У ActiveRecord песимістичне блокування реалізується через метод lock, який додає SELECT ... FOR UPDATE, що утримує блокування до кінця транзакції.

Використання в Rails

Ось простий приклад використання lock у Rails:
ActiveRecord::Base.transaction do
  order = Order.lock.find(order_id)
  order.status = "processed"
  order.save!
end
У цьому випадку, якщо інший процес спробує отримати Order із тим самим order_id, він змушений буде чекати, поки поточний процес завершить транзакцію.

Навіщо це потрібно?

Уявімо, що ми обробляємо замовлення. Коли користувач натискає кнопку "Оплатити", нам потрібно зменшити кількість товару на складі. Якщо кілька людей одночасно намагаються купити останню одиницю товару, без блокування можливий race condition:
  1. Процес 1 читає кількість товару (1 одиниця).
  2. Процес 2 читає ту ж саму кількість (1 одиниця).
  3. Обидва процеси намагаються записати нове значення (0 одиниць).
  4. Один з процесів втрачає оновлення іншого.
Якщо ж використати lock, другий процес буде змушений дочекатися завершення першого і вже потім вирішувати, що робити.

Альтернативи pessimistic lock

Pessimistic locking не завжди найкращий вибір, оскільки він може блокувати інші процеси, уповільнюючи роботу застосунку. Іноді краще використовувати:
  1. Optimistic Locking — перевіряє, чи змінився запис між читанням і записом.
  2. Atomic операції — використовує UPDATE ... WHERE або increment! без читання значень у Ruby.
  3. Queue-based підхід — розподіляє оновлення через чергу (Sidekiq, RabbitMQ).

Optimistic Locking у Rails

Optimistic locking працює через колонку lock_version. Якщо два процеси читають запис, то при спробі записати зміни система перевіряє, чи не змінився запис за цей час:
class Order < ApplicationRecord
  attr_accessor :lock_version
end
Тоді, якщо один процес внесе зміни, а інший спробує записати застарілу версію, він отримає ActiveRecord::StaleObjectError.
Якщо простими словами:
  • Pessimistic locking блокує запис, щоб уникнути конфліктів.
  • Optimistic locking дозволяє працювати без блокування, але потребує обробки конфліктів.
  • Atomic операції зменшують ризик race condition без блокувань.
Обирайте правильний підхід залежно від задачі. Якщо критично уникнути конфліктів за будь-яку ціну — використовуйте lock. Якщо важлива продуктивність і можна дозволити конфлікти — краще lock_version або atomic updates.

🔥 Більше дописів

Всі публікації
Що таке CFB (Cipher Feedback)?
Програмування21 бер. '25, 16:53

Що таке CFB (Cipher Feedback)?

CFB (Cipher Feedback) – це режим шифрування, де кожен блок залежить від попереднього, що забезпеч...

Що таке XOR і як він працює?
Програмування21 бер. '25, 17:05

Що таке XOR і як він працює?

XOR (виключне АБО) – це логічна операція, що використовується у шифруванні, зміні бітів та переві...