← Назад ко всем вопросам

Чем отличается optimistic от pessimistic locking

1️⃣ Как кратко ответить

Optimistic locking предполагает, что конфликтов при доступе к данным не будет, и проверяет наличие изменений только перед записью. Pessimistic locking блокирует данные на время транзакции, предотвращая доступ других транзакций к этим данным.

2️⃣ Подробное объяснение темы

Optimistic и pessimistic locking — это два подхода к управлению конкурентным доступом к данным в многопользовательских системах. Они помогают избежать конфликтов, когда несколько транзакций пытаются одновременно изменить одни и те же данные.

Optimistic Locking

Optimistic locking исходит из предположения, что конфликтов при доступе к данным будет мало или не будет вовсе. Этот подход позволяет транзакциям читать данные без блокировки, но перед записью проверяет, не изменились ли данные с момента последнего чтения. Если данные изменились, транзакция откатывается и может быть повторена.

Пример использования optimistic locking:

type Record struct {
    ID      int
    Version int
    Data    string
}
​
// Функция обновления записи
func updateRecord(db *sql.DB, record *Record) error {
    // Чтение текущей версии записи из базы данных
    var currentVersion int
    err := db.QueryRow("SELECT version FROM records WHERE id = ?", record.ID).Scan(&currentVersion)
    if err != nil {
        return err
    }
​
    // Проверка, не изменилась ли версия
    if currentVersion != record.Version {
        return fmt.Errorf("record has been modified by another transaction")
    }
​
    // Обновление записи с проверкой версии
    _, err = db.Exec("UPDATE records SET data = ?, version = version + 1 WHERE id = ? AND version = ?", record.Data, record.ID, record.Version)
    return err
}
  • Record — структура, представляющая запись с полем Version для отслеживания изменений.
  • updateRecord — функция, которая обновляет запись, проверяя, не изменилась ли версия.
  • db.QueryRow — чтение текущей версии записи.
  • db.Exec — обновление записи, если версия не изменилась.

Pessimistic Locking

Pessimistic locking предполагает, что конфликты при доступе к данным вероятны, и блокирует данные на время транзакции. Это предотвращает доступ других транзакций к заблокированным данным до завершения текущей транзакции. Такой подход может снизить производительность из-за увеличения времени ожидания.

Пример использования pessimistic locking:

func updateRecordWithLock(db *sql.DB, record *Record) error {
    // Начало транзакции
    tx, err := db.Begin()
    if err != nil {
        return err
    }
​
    // Блокировка записи для предотвращения изменений другими транзакциями
    var currentData string
    err = tx.QueryRow("SELECT data FROM records WHERE id = ? FOR UPDATE", record.ID).Scan(&currentData)
    if err != nil {
        tx.Rollback()
        return err
    }
​
    // Обновление данных
    _, err = tx.Exec("UPDATE records SET data = ? WHERE id = ?", record.Data, record.ID)
    if err != nil {
        tx.Rollback()
        return err
    }
​
    // Завершение транзакции
    return tx.Commit()
}
  • tx.Begin — начало транзакции.
  • tx.QueryRow — блокировка записи с помощью FOR UPDATE, предотвращающая изменения другими транзакциями.
  • tx.Exec — обновление данных в заблокированной записи.
  • tx.Commit — завершение транзакции и снятие блокировки.

Применение

  • Optimistic locking подходит для систем, где конфликты редки, и важна высокая производительность, например, в системах с большим количеством чтений и небольшим количеством записей.
  • Pessimistic locking используется в системах, где конфликты вероятны и недопустимы, например, в банковских системах, где важна целостность данных.

Оба подхода имеют свои плюсы и минусы, и выбор между ними зависит от специфики приложения и требований к производительности и целостности данных.

Тема: Базы данных и SQL
Стадия: Tech

🔒 Подпишись на бусти автора и стань Алигатором, чтобы получить полный доступ к функционалу сайта и отслеживать свой прогресс!

Твои заметки