← Каталог
Работа с базами данных из Ruby — Optimistic Locking
Фрагмент из «Работа с базами данных из Ruby»: Optimistic Locking.
Разбор:
- Фрагмент показывает конкретный сценарий, который стартует со строки `Поддерживаемые уровни зависят от СУБД:` и задаёт контекст выполнения.
- Ключевые элементы блока: `lock`, они определяют основную логику примера.
- По шагам код выполняется так: `Поддерживаемые уровни зависят от СУБД:` -> `- PostgreSQL: `read_uncommitted`, `read_committed` (по умолчанию), `` -> `- MySQL (InnoDB): `read_uncommitted`, `read_committed`, `repeatable_` -> `Важно: **Ruby не эмулирует уровни изоляции** — он просто передаёт ди`.
- Практически важно добавить обработку ошибок и явные проверки входа, чтобы исключить скрытые падения в рантайме.
- Типичная ошибка при развитии такого кода — смешивать бизнес-правила и инфраструктурные детали в одном месте; лучше разделять ответственность.
class Article < ActiveRecord::Base
# lock_version должен быть в таблице
end
# Поток 1 —
a1 = Article.find(1)
a1.title = "v1"
a1.save # → UPDATE ... SET title = 'v1', lock_version = 1 WHERE id = 1 AND lock_version = 0
# Поток 2 (одновременно) —
a2 = Article.find(1) # lock_version = 0
a2.title = "v2"
a2.save # пытается: UPDATE ... WHERE lock_version = 0 → 0 rows affected → выбрасывает ActiveRecord::StaleObjectError
Разбор:
- Фрагмент показывает конкретный сценарий, который стартует со строки `Поддерживаемые уровни зависят от СУБД:` и задаёт контекст выполнения.
- Ключевые элементы блока: `lock`, они определяют основную логику примера.
- По шагам код выполняется так: `Поддерживаемые уровни зависят от СУБД:` -> `- PostgreSQL: `read_uncommitted`, `read_committed` (по умолчанию), `` -> `- MySQL (InnoDB): `read_uncommitted`, `read_committed`, `repeatable_` -> `Важно: **Ruby не эмулирует уровни изоляции** — он просто передаёт ди`.
- Практически важно добавить обработку ошибок и явные проверки входа, чтобы исключить скрытые падения в рантайме.
- Типичная ошибка при развитии такого кода — смешивать бизнес-правила и инфраструктурные детали в одном месте; лучше разделять ответственность.
class Article < ActiveRecord::Base
# lock_version должен быть в таблице
end
# Поток 1 —
a1 = Article.find(1)
a1.title = "v1"
a1.save # → UPDATE ... SET title = 'v1', lock_version = 1 WHERE id = 1 AND lock_version = 0
# Поток 2 (одновременно) —
a2 = Article.find(1) # lock_version = 0
a2.title = "v2"
a2.save # пытается: UPDATE ... WHERE lock_version = 0 → 0 rows affected → выбрасывает ActiveRecord::StaleObjectError