Чем отличается 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(¤tVersion)
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(¤tData)
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 используется в системах, где конфликты вероятны и недопустимы, например, в банковских системах, где важна целостность данных.
Оба подхода имеют свои плюсы и минусы, и выбор между ними зависит от специфики приложения и требований к производительности и целостности данных.
🔒 Подпишись на бусти автора и стань Алигатором, чтобы получить полный доступ к функционалу сайта и отслеживать свой прогресс!
Подписаться