.NET Core 使用者 Kafka 错误死锁 SQL Server

.NET Core Consumer Kafka error deadlock SQL Server

提问人:Firman Alam 提问时间:11/14/2023 最后编辑:Firman Alam 更新时间:11/15/2023 访问量:52

问:

我是 .NET 的新手。我有使用 .NET Core 的微服务。此服务用于成为 Kafka 使用者。在使用者函数中,有一个要插入到 SQL Server 数据库中的函数。此函数经常遇到错误,但有时当流量较低时,此代码不会出错。我附上了函数代码。这个函数很简单,只需使用事务插入数据库即可。如果有人经历过这样的事情,请提供帮助。错误如下所示。deadlockset identity insert on

An exception occurred in the database while saving changes for context type 'Entities.RepositoryContext'.
      Microsoft.EntityFrameworkCore.DbUpdateException: An error occurred while updating the entries. See the inner exception for details.
       ---> Microsoft.Data.SqlClient.SqlException (0x80131904): Transaction (Process ID 414) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.
    private async Task insertData(Dto data)
    {
        var dataFromDB = _repository.myRepo.FirstOrDefaultWithNoLock(p => p.ID.Equals(data.ID));

        if (dataFromDB == null)
        {
            dataFromDB = _mapper.Map<Model>(data);
            _repository.myRepo.Create(dataFromDB);
            _repository.myRepo.SaveChangesWithIdentityInsert();
            return;
        }

        return;
    }

我在里面附上了代码SaveChangesWithIdentityInsert

        public static void EnableIdentityInsert<T>(this DbContext context) => SetIdentityInsert<T>(context, true);
        public static void DisableIdentityInsert<T>(this DbContext context) => SetIdentityInsert<T>(context, false);

        private static void SetIdentityInsert<T>([NotNull] DbContext context, bool enable)
        {
            if (context == null) throw new ArgumentNullException(nameof(context));
            var entityType = context.Model.FindEntityType(typeof(T));
            var value = enable ? "ON" : "OFF";
            context.Database.ExecuteSqlRaw($"SET IDENTITY_INSERT dbo.{entityType.GetTableName()} {value}");
        }

        public static void SaveChangesWithIdentityInsert<T>([NotNull] this DbContext context)
        {
            if (context == null) throw new ArgumentNullException(nameof(context));
            var strategy = context.Database.CreateExecutionStrategy();
            strategy.Execute(
            () =>
            {
                using var transaction = context.Database.BeginTransaction(isolationLevel: System.Data.IsolationLevel.ReadUncommitted);
                context.EnableIdentityInsert<T>();
                context.SaveChanges();
                context.DisableIdentityInsert<T>();
                transaction.Commit();
            });
            context.ChangeTracker.Clear();
        }

我尝试使用.我正在搜索在发生死锁时自动重试消费者,但没有找到任何东西。with no lock

.NET SQL-Server 微服务 kafka-consumer-api asp.net-core-5.0

评论

0赞 Denis Micheal 11/14/2023
这个方法是什么?还要发布此死锁错误/异常。SaveChangesWithIdentityInsert()
0赞 AlwaysLearning 11/14/2023
这是一个不需要锁的神话——至少它需要并持有 Sch-M 锁。WITH (NOLOCK)
0赞 Firman Alam 11/14/2023
@DenisMicheal我编辑了问题,我附加了 savechangeswithidentityinsert
0赞 Panagiotis Kanavos 11/14/2023
@FirmanAlam问题都是由所有这些不必要的代码引起的。DbContext 不需要名为“repository”的 CRUD 类,它是一个更高级别的抽象,一个工作单元。 尝试执行 SaveChanges 本身对所有修改的对象执行的操作,并且以一种非常错误的方式执行此操作,通过显式包装另一个事务来导致阻塞SaveChangesWithIdentityInsertSaveChanges
0赞 Panagiotis Kanavos 11/14/2023
FirstOrDefaultWithNoLock也毫无意义,因为 DbContext 不是数据库连接。除非它必须读取或写入数据,否则它甚至不会打开连接。

答: 暂无答案