EF Core и блокировки при конкуренции

UPD

Переделал вопрос после 10 первых комментариев

Имею:

C# / EF Core / MySQL 5.7

Задача:

Есть таблица в базе с постоянно наполняемыми данными, эти данные нужно обрабатывать и сохранять в другие таблицы, обработанные удалить.

Сущность:

public class RawLink
{
    public int Id { get; set; }
    public string? Link { get; set; }
    public bool IsProcessing { get; set; }

    [Timestamp]
    public byte[]? Timestamp { get; set; }
}

Воркер:

  1. Получает до 100 записей из RawLinks.
  2. Обрабатывает их.
  3. Сохраняет результаты в DefinedLinks и NotDefinedLinks
  4. Удаляет из RawLinks обработынные

В моём методе воркера, если он не один, опирается всё на то что другие воркеры в конкуренции будут спотыкаться при первом await context.SaveChangesAsync(); за счёт оптимистической блокировки.

Напрягает ситуация, когда при налии 2х воркеров, второй будет только и спотыкаться, т.е. ничего не делать.

Метод воркера:

    private async Task<bool> UnitWorkAsync()
    {
        using var scope = _serviceScopeFactory.CreateScope();
        using var context = scope.ServiceProvider.GetRequiredService<DefinerDbContext>();

        await using var transaction = await context.Database.BeginTransactionAsync();

        try
        {
            var rawLinks = await context.RawLinks
                .Where(r => !r.IsProcessing)
                .OrderBy(r => r.Id)
                .Take(100)
                .ToListAsync();

            if (rawLinks.Count == 0)
            {
                await transaction.RollbackAsync();
                return false;
            }

            foreach (var rawLink in rawLinks) 
            {
                rawLink.IsProcessing = true;
            }

            await context.SaveChangesAsync(); // Тут спотыкаются

            var definerResult = Define(rawLinks);

            if (definerResult.DefinedLinks.Count != 0) 
            {
                await context.DefinedLinks.AddRangeAsync(definerResult.DefinedLinks);
            }

            if (definerResult.NotDefinedLinks.Count != 0)
            {
                await context.NotDefinedLinks.AddRangeAsync(definerResult.NotDefinedLinks);
            }

            context.RawLinks.RemoveRange(rawLinks);
            await context.SaveChangesAsync();
            await transaction.CommitAsync();
        }
        catch (DbUpdateConcurrencyException ex)
        {
            await transaction.RollbackAsync();
        }
        catch (Exception ex)
        {
            await transaction.RollbackAsync();
            _logger.LogError(ex, ex.Message);
        }

        return true;
    }

По сути эта часть, только и служит чтобы спотыкались воркеры и брали другие записи.

foreach (var rawLink in rawLinks) 
{
    rawLink.IsProcessing = true;
}
    
await context.SaveChangesAsync();

...

catch (DbUpdateConcurrencyException ex)
{
    await transaction.RollbackAsync();
}

введите сюда описание изображения

Вопрос:

Какие шаги можно предпринять чтобы улучшить ?

Может быть Пессимистическая блокировка ?

  • Если заблокировано, то брать другие записи и тогда по сути никакой Update() с IsProcessing и Timestamp не нужен даже.

UPD:

Пробовал аналогично, но брать по 1 записи. 1 воркер не успевает обрабатывать наполнение, более воркеров только и делают что спотыкаются друг об друга.

UPD

1 воркер при получение 100 записей на данный момент более чем справляется, но хочется предугадать момент с вызовом дополнительных вокреров на подмогу и исключить дублирование если вокер будет не 1.

UPD

Брать кем то одним и раздавать задачи другим для обработки, кажется как будто в 100 раз сложнее всем этим дережировать.

UPD

Время работы метода UnitWorkAsync():

Берём до 100 записей:

var rawLinks = await context.RawLinks
    .Where(r => !r.IsProcessing)
    .OrderBy(r => r.Id)
    .Take(100)
    .ToListAsync();

Сам лог:

info: LinkProcessor.Program[0]
      Приложение запущено.
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance 1 | Время выполнения: 00:00:07.7469070
warn: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance 2 | The database operation was expected to affect 1 row(s), but actually affected 0 row(s); data may have been modified or deleted since entities were loaded. See https://go.microsoft.com/fwlink/?LinkId=527962 for information on understanding and handling optimistic concurrency exceptions.
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance 2 | Время выполнения: 00:00:07.0955795
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance 1 | Время выполнения: 00:00:05.5986849
warn: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance 2 | The database operation was expected to affect 1 row(s), but actually affected 0 row(s); data may have been modified or deleted since entities were loaded. See https://go.microsoft.com/fwlink/?LinkId=527962 for information on understanding and handling optimistic concurrency exceptions.
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance 2 | Время выполнения: 00:00:05.6116070
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance 1 | Время выполнения: 00:00:05.4930604
warn: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance 2 | The database operation was expected to affect 1 row(s), but actually affected 0 row(s); data may have been modified or deleted since entities were loaded. See https://go.microsoft.com/fwlink/?LinkId=527962 for information on understanding and handling optimistic concurrency exceptions.
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance 2 | Время выполнения: 00:00:05.4732192
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance 1 | Время выполнения: 00:00:05.5077854
warn: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance 2 | The database operation was expected to affect 1 row(s), but actually affected 0 row(s); data may have been modified or deleted since entities were loaded. See https://go.microsoft.com/fwlink/?LinkId=527962 for information on understanding and handling optimistic concurrency exceptions.
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance 2 | Время выполнения: 00:00:05.5124799
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance 1 | Время выполнения: 00:00:05.5070659
warn: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance 2 | The database operation was expected to affect 1 row(s), but actually affected 0 row(s); data may have been modified or deleted since entities were loaded. See https://go.microsoft.com/fwlink/?LinkId=527962 for information on understanding and handling optimistic concurrency exceptions.
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance 2 | Время выполнения: 00:00:05.5044509

Берём по 1 записи:

var rawLink = await context.RawLinks
        .Where(r => !r.IsProcessing)
        .OrderBy(r => r.Id)
        .FirstOrDefaultAsync();

Сам лог:

info: LinkProcessor.Program[0]
      Приложение запущено.
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance 1 | Время выполнения: 00:00:05.2309966
warn: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance 2 | The database operation was expected to affect 1 row(s), but actually affected 0 row(s); data may have been modified or deleted since entities were loaded. See https://go.microsoft.com/fwlink/?LinkId=527962 for information on understanding and handling optimistic concurrency exceptions.
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance 2 | Время выполнения: 00:00:04.5280009
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance 1 | Время выполнения: 00:00:03.7889567
warn: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance 2 | The database operation was expected to affect 1 row(s), but actually affected 0 row(s); data may have been modified or deleted since entities were loaded. See https://go.microsoft.com/fwlink/?LinkId=527962 for information on understanding and handling optimistic concurrency exceptions.
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance 2 | Время выполнения: 00:00:03.7585818
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance 1 | Время выполнения: 00:00:03.8031755
warn: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance 2 | The database operation was expected to affect 1 row(s), but actually affected 0 row(s); data may have been modified or deleted since entities were loaded. See https://go.microsoft.com/fwlink/?LinkId=527962 for information on understanding and handling optimistic concurrency exceptions.
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance 2 | Время выполнения: 00:00:03.8160380
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance 1 | Время выполнения: 00:00:03.8049081
warn: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance 2 | The database operation was expected to affect 1 row(s), but actually affected 0 row(s); data may have been modified or deleted since entities were loaded. See https://go.microsoft.com/fwlink/?LinkId=527962 for information on understanding and handling optimistic concurrency exceptions.
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance 2 | Время выполнения: 00:00:03.7819628
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance 1 | Время выполнения: 00:00:03.7207133
warn: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance 2 | The database operation was expected to affect 1 row(s), but actually affected 0 row(s); data may have been modified or deleted since entities were loaded. See https://go.microsoft.com/fwlink/?LinkId=527962 for information on understanding and handling optimistic concurrency exceptions.
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance 2 | Время выполнения: 00:00:03.7379248
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance 1 | Время выполнения: 00:00:03.8344333
warn: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance 2 | The database operation was expected to affect 1 row(s), but actually affected 0 row(s); data may have been modified or deleted since entities were loaded. See https://go.microsoft.com/fwlink/?LinkId=527962 for information on understanding and handling optimistic concurrency exceptions.
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance 2 | Время выполнения: 00:00:03.8175757
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance 1 | Время выполнения: 00:00:03.7773384
warn: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance 2 | The database operation was expected to affect 1 row(s), but actually affected 0 row(s); data may have been modified or deleted since entities were loaded. See https://go.microsoft.com/fwlink/?LinkId=527962 for information on understanding and handling optimistic concurrency exceptions.
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance 2 | Время выполнения: 00:00:03.8173221
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance 1 | Время выполнения: 00:00:03.7549174
warn: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance 2 | The database operation was expected to affect 1 row(s), but actually affected 0 row(s); data may have been modified or deleted since entities were loaded. See https://go.microsoft.com/fwlink/?LinkId=527962 for information on understanding and handling optimistic concurrency exceptions.
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance 2 | Время выполнения: 00:00:03.7168629
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance 1 | Время выполнения: 00:00:03.7918706
warn: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance 2 | The database operation was expected to affect 1 row(s), but actually affected 0 row(s); data may have been modified or deleted since entities were loaded. See https://go.microsoft.com/fwlink/?LinkId=527962 for information on understanding and handling optimistic concurrency exceptions.
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance 2 | Время выполнения: 00:00:03.8058457

UPD:

Струтктура таблицы введите сюда описание изображения

UPD:

Психанул и покрыл кажду строчку таймером:

info: LinkProcessor.Program[0]
      Приложение запущено.
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 1 | CreateScope(): 00:00:00.0001086
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 1 | GetRequiredService<DefinerDbContext>(): 00:00:01.4378422
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 2 | CreateScope(): 00:00:00.0000037
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 2 | GetRequiredService<DefinerDbContext>(): 00:00:01.0532273
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 1 | BeginTransactionAsync(): 00:00:02.0351968
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 1 | LINQ с FirstOrDefaultAsync(): 00:00:00.4973495
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 2 | BeginTransactionAsync(): 00:00:01.5191721
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 2 | LINQ с FirstOrDefaultAsync(): 00:00:00.2527437
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 1 | SaveChangesAsync(): 00:00:00.8887138
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 1 | Define(rawLink): 00:00:00.0004086
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 1 | DefinedLinks.Add(definedLink): 00:00:00.0204946
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 1 | Remove(rawLink): 00:00:00.0013226
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 1 | SaveChangesAsync(): 00:00:00.7778729
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 1 | CommitAsync(): 00:00:00.2615952
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 1 | Время выполнения метода: 00:00:05.9472927
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 1 | CreateScope(): 00:00:00.0000017
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 2 | RollbackAsync(): 00:00:00.2552390
warn: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance 2 | The database operation was expected to affect 1 row(s), but actually affected 0 row(s); data may have been modified or deleted since entities were loaded. See https://go.microsoft.com/fwlink/?LinkId=527962 for information on understanding and handling optimistic concurrency exceptions.
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 2 | Время выполнения метода: 00:00:04.8687420
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 2 | CreateScope(): 00:00:00.0000018
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 1 | GetRequiredService<DefinerDbContext>(): 00:00:01.2619197
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 1 | BeginTransactionAsync(): 00:00:00.8215310
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 2 | GetRequiredService<DefinerDbContext>(): 00:00:01.2151521
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 1 | LINQ с FirstOrDefaultAsync(): 00:00:00.2586529
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 2 | BeginTransactionAsync(): 00:00:00.7639143
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 1 | SaveChangesAsync(): 00:00:00.7590106
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 1 | Define(rawLink): 00:00:00.0000068
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 1 | DefinedLinks.Add(definedLink): 00:00:00.0010776
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 1 | Remove(rawLink): 00:00:00.0000148
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 2 | LINQ с FirstOrDefaultAsync(): 00:00:00.2551783
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 1 | SaveChangesAsync(): 00:00:00.7537565
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 1 | CommitAsync(): 00:00:00.2511257
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 1 | Время выполнения метода: 00:00:04.1079049
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 1 | CreateScope(): 00:00:00.0000022
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 2 | RollbackAsync(): 00:00:00.2483743
warn: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance 2 | The database operation was expected to affect 1 row(s), but actually affected 0 row(s); data may have been modified or deleted since entities were loaded. See https://go.microsoft.com/fwlink/?LinkId=527962 for information on understanding and handling optimistic concurrency exceptions.
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 2 | Время выполнения метода: 00:00:04.0264614
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 2 | CreateScope(): 00:00:00.0000022
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 1 | GetRequiredService<DefinerDbContext>(): 00:00:01.0457158
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 2 | GetRequiredService<DefinerDbContext>(): 00:00:00.9927741
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 1 | BeginTransactionAsync(): 00:00:00.7571436
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 1 | LINQ с FirstOrDefaultAsync(): 00:00:00.2536234
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 2 | BeginTransactionAsync(): 00:00:00.7491910
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 2 | LINQ с FirstOrDefaultAsync(): 00:00:00.2487510
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 1 | SaveChangesAsync(): 00:00:00.7480924
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 1 | Define(rawLink): 00:00:00.0000072
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 1 | DefinedLinks.Add(definedLink): 00:00:00.0002159
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 1 | Remove(rawLink): 00:00:00.0000112
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 1 | SaveChangesAsync(): 00:00:00.7514422
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 1 | CommitAsync(): 00:00:00.2484457
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 1 | Время выполнения метода: 00:00:03.8053971
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 1 | CreateScope(): 00:00:00.0000027
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 2 | RollbackAsync(): 00:00:00.2497942
warn: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance 2 | The database operation was expected to affect 1 row(s), but actually affected 0 row(s); data may have been modified or deleted since entities were loaded. See https://go.microsoft.com/fwlink/?LinkId=527962 for information on understanding and handling optimistic concurrency exceptions.
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 2 | Время выполнения метода: 00:00:03.8014147
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 2 | CreateScope(): 00:00:00.0000046
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 1 | GetRequiredService<DefinerDbContext>(): 00:00:00.9929112
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 1 | BeginTransactionAsync(): 00:00:00.7474057
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 2 | GetRequiredService<DefinerDbContext>(): 00:00:01.0762522
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 1 | LINQ с FirstOrDefaultAsync(): 00:00:00.2502469
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 2 | BeginTransactionAsync(): 00:00:00.7649033
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 1 | SaveChangesAsync(): 00:00:00.7482216
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 1 | Define(rawLink): 00:00:00.0000073
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 1 | DefinedLinks.Add(definedLink): 00:00:00.0002198
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 1 | Remove(rawLink): 00:00:00.0000205
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 2 | LINQ с FirstOrDefaultAsync(): 00:00:00.2491666
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 1 | SaveChangesAsync(): 00:00:00.7469235
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 1 | CommitAsync(): 00:00:00.2473850
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 1 | Время выполнения метода: 00:00:03.7339543
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 1 | CreateScope(): 00:00:00.0000035
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 2 | RollbackAsync(): 00:00:00.2486930
warn: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance 2 | The database operation was expected to affect 1 row(s), but actually affected 0 row(s); data may have been modified or deleted since entities were loaded. See https://go.microsoft.com/fwlink/?LinkId=527962 for information on understanding and handling optimistic concurrency exceptions.
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 2 | Время выполнения метода: 00:00:03.7570627
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 2 | CreateScope(): 00:00:00.0000030
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 1 | GetRequiredService<DefinerDbContext>(): 00:00:01.0188976
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 1 | BeginTransactionAsync(): 00:00:00.7528139
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 2 | GetRequiredService<DefinerDbContext>(): 00:00:01.0038930
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 1 | LINQ с FirstOrDefaultAsync(): 00:00:00.2517207
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 2 | BeginTransactionAsync(): 00:00:00.7738376
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 1 | SaveChangesAsync(): 00:00:00.7773834
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 1 | Define(rawLink): 00:00:00.0000066
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 1 | DefinedLinks.Add(definedLink): 00:00:00.0002918
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 1 | Remove(rawLink): 00:00:00.0000204
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 2 | LINQ с FirstOrDefaultAsync(): 00:00:00.2500788
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 1 | SaveChangesAsync(): 00:00:00.7469620
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 1 | CommitAsync(): 00:00:00.2487339
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 1 | Время выполнения метода: 00:00:03.7972754
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 1 | CreateScope(): 00:00:00.0000028
info: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance: 2 | RollbackAsync(): 00:00:00.2516977
warn: LinkProcessor.BL.Services.DefinerRawLinksService.DefinerRawLinksService[0]
      Instance 2 | The database operation was expected to affect 1 row(s), but actually affected 0 row(s); data may have been modified or deleted since entities were loaded. See https://go.microsoft.com/fwlink/?LinkId=527962 for information on understanding and handling optimistic concurrency exceptions.

Ответы (1 шт):

Автор решения: Glebka

Мои варианты:

  1. Разделить воркеров, чтобы данные с которыми они работают не пересекались. Например: один берёт все записи у которых id начинается с цифры 1, а другой с 2... и т.д.
  2. Использовать ReadCommited режим изоляции. Пусть они перезаписывают совпадающие. Если, конечно, позволяет бизнес-логика.
  3. Получить все записи сразу (без .Take(100)), а уже в коде их поделить на чанки и раздать воркерам. Далее дождаться выполнение всех Task.WaitAll и так по-кругу.
→ Ссылка