TGStat
TGStat
Введите текст для поиска
Расширенный поиск каналов
  • flag Russian
    Язык сайта
    flag Russian flag English flag Uzbek
  • Вход на сайт
  • Каталог
    Каталог каналов и чатов Региональные подборки Тематические подборки Платные каналы Поиск каналов
    Добавить канал/чат
  • Рейтинги
    Рейтинг каналов Рейтинг чатов Рейтинг публикаций
    Рейтинги брендов и персон
  • Аналитика
  • Поиск по публикациям
  • Мониторинг Telegram
  • Продвижение
    Реклама через Яндекс Бизнес Реклама в каналах через TGStat Agency Реклама на сайте TGStat.ru
.NET Разработчик

11 Sep 2023, 08:10

Открыть в Telegram Поделиться Пожаловаться

День 1685. #ЗаметкиНаПолях
Решение Проблем Гонки с Помощью Оптимистической Блокировки EF Core. Начало
Как часто вы думаете о конфликтах параллелизма при написании кода? Вы пишете код новой функции, проверяете, что она работает, и всё. Но неделю спустя вы обнаруживаете, что допустили неприятную ошибку, потому что не подумали о параллелизме. Наиболее распространённой проблемой являются условия гонки, когда два конкурирующих потока выполняют одну и ту же функцию. Если вы не учтёте это во время разработки, вы рискуете оставить систему в повреждённом состоянии.

Рассмотрим пример.
Бизнес-требование: нельзя иметь два перекрывающихся бронирования на одни и те же даты. В следующем примере кода скрывается проблема состояния гонки:
public Result Handle(
ReserveBooking command,
AppDbContext ctx)
{
var user = ctx.Users.GetById(command.UserId);
var apart = ctx.Aparts.GetById(command.ApartId);
var (start, end) = command;

if (dbContext.Bookings
.IsOverlapping(apart, start, end))
return Result.Failure(Errors.Overlap);

var booking = Booking
.Reserve(apart, user, start, end);

ctx.Add(booking);
ctx.SaveChanges();

return booking.Id;
}
Вызов IsOverlapping — это оптимистичная проверка, существует ли бронирование на указанные даты. Если ответ true, это попытка конкурентного бронирования на те же даты, поэтому мы возвращаем ошибку. Но если возвращается false, мы бронируем и вызываем SaveChanges, чтобы сохранить изменения в БД.

Проблема в том, что существует вероятность того, что параллельный запрос пройдёт проверку IsOverlapping и попытается сделать бронирование. Без какого-либо контроля параллелизма оба запроса будут успешными, и в итоге мы получим несогласованное состояние БД.

При пессимистическом подходе обработки параллелизма данные в БД блокируются между чтением и изменением. Это медленно и приводит к блокировке конкурирующих транзакций до тех пор, пока блокировка не будет снята. EF Core не поддерживает этот подход «из коробки». Оптимистический параллелизм в EF Core не требует блокировок, но любые изменения данных не будут сохранены, если данные изменились с момента чтения.

Чтобы реализовать оптимистичный параллелизм в EF Core, необходимо настроить свойство как токен параллелизма. Оно загружается и отслеживается вместе с сущностью. Когда вы вызываете SaveChanges, EF Core сравнивает значение токена параллелизма со значением в базе данных.

Например, в SQL Server есть столбец rowversion, который автоматически меняется при обновлении строки, поэтому это отличный вариант для токена параллелизма. Можно настроить теневое свойство в EF Core, чтобы спрятать его от основного класса сущности:
protected override void OnModelCreating(
ModelBuilder mb)
{
mb.Entity()
.Property("Version")
.IsRowVersion();
}
* Точная конфигурация будет зависеть от типа вашей БД.

При загрузке сущности Apart EF также загрузит токен параллелизма.
SELECT a.Id, a.Version
FROM Aparts a
WHERE a.Id = @p0
А при вызове SaveChanges, запрос UPDATE сравнит его с текущим токеном в БД:
UPDATE Aparts a
SET a.LastBookedOnUtc = @p0
WHERE a.Id = @p1 AND a.Version = @p2;
Если версия в базе отличается, будет обновлено 0 строк, а EF Core ожидает обновления 1 строки, поэтому будет выброшено исключение DbUpdateConcurrencyException, которое надо обработать.

Окончание следует…

Источник:
https://www.milanjovanovic.tech/blog/solving-race-conditions-with-ef-core-optimistic-locking

1.7k 4 35 22
Каталог
Каталог каналов и чатов Подборки каналов Поиск каналов Добавить канал/чат
Рейтинги
Рейтинг каналов Telegram Рейтинг чатов Telegram Рейтинг публикаций Рейтинги брендов и персон
API
API статистики API поиска публикаций API Callback
Наши каналы
@TGStat @TGStat_Chat @telepulse @TGStatAPI
Почитать
Академия TGStat Исследование Telegram 2019 Исследование Telegram 2021 Исследование Telegram 2023
Контакты
Справочный центр Поддержка Почта Вакансии
Всякая всячина
Пользовательское соглашение Политика конфиденциальности Публичная оферта
Наши боты
@TGStat_Bot @SearcheeBot @TGAlertsBot @tg_analytics_bot @TGStatChatBot