C# MySQL-DBUpdateException(';尝试获取锁时发现死锁;尝试重新启动事务';)

C# MySQL-DBUpdateException(';尝试获取锁时发现死锁;尝试重新启动事务';),c#,mysql,entity-framework-core,transactionscope,C#,Mysql,Entity Framework Core,Transactionscope,我有一个mvc应用程序。NET核心使用MySQL。我有一个下载函数,其中传递id以下载文件。然而,错误不断发生,似乎不知何故,该应用程序在服务器上的响应性变差,就好像它正在被回收一样。下面的代码显示负责下载该文件的部分。我正在使用TransactionScope来确保下载计数器已正确更新。我得到的错误与死锁有关。如果有人能指出问题所在,是否可能 using (var context = new MyDbContext()) using (TransactionScope scope = new

我有一个mvc应用程序。NET核心使用MySQL。我有一个下载函数,其中传递id以下载文件。然而,错误不断发生,似乎不知何故,该应用程序在服务器上的响应性变差,就好像它正在被回收一样。下面的代码显示负责下载该文件的部分。我正在使用TransactionScope来确保下载计数器已正确更新。我得到的错误与死锁有关。如果有人能指出问题所在,是否可能

using (var context = new MyDbContext())
using (TransactionScope scope = new TransactionScope())
{
    ProjectDownload download = context.ProjectDownload.Include(pd => pd.Project).Where(d => d.Id == downloadId).FirstOrDefault();

    if (download == null) throw new InvalidOperationException("Cannot find ProjectDownload.Id");

   download.DownloadCounter++;
   download.Project.DownloadCounter++;

   try
   {
       context.SaveChanges();
       scope.Complete();
       return (ProjectDownloadModel)download;
   }
   catch (DbUpdateException ex){
       throw;
   }
}
还尝试通过这种方式将以前的代码更改为:

using (var context = new MyDbContext())
using (TransactionScope scope = new TransactionScope())
{
    ProjectDownload download = context.ProjectDownload.Where(d => d.Id == downloadId).FirstOrDefault();

   download.DownloadCounter++;

   Project proj = context.Project.Where(p => p.ProjectDownload.Any(pd => pd.Id == downloadId)).FirstOrDefault();
   proj.DownloadCounter++;
   ...
出现以下错误:

Exception has occurred: CLR/MySql.Data.MySqlClient.MySqlException
An exception of type 'MySql.Data.MySqlClient.MySqlException' occurred in Microsoft.EntityFrameworkCore.dll but was not handled in user code: 'Deadlock found when trying to get lock; try restarting transaction'
  at MySql.Data.MySqlClient.MySqlStream.ReadPacket()
  at MySql.Data.MySqlClient.NativeDriver.GetResult(Int32& affectedRow, Int64& insertedId)
  at MySql.Data.MySqlClient.Driver.NextResult(Int32 statementId, Boolean force)
  at MySql.Data.MySqlClient.MySqlDataReader.NextResult()
  at MySql.Data.MySqlClient.MySqlCommand.ExecuteReader(CommandBehavior behavior)
  at Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.Execute(IRelationalConnection connection, DbCommandMethod executeMethod, IReadOnlyDictionary`2 parameterValues)
  at Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.ExecuteReader(IRelationalConnection connection, IReadOnlyDictionary`2 parameterValues)    
  at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable`1.Enumerator.BufferlessMoveNext(DbContext _, Boolean buffer)    
  at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable`1.Enumerator.MoveNext()
  at System.Linq.Enumerable.SelectEnumerableIterator`2.MoveNext()    
  at System.Linq.Enumerable.TryGetFirst[TSource](IEnumerable`1 source, Boolean& found)    
  at Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider.ResultEnumerable`1.GetEnumerator()
  at Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider.<_TrackEntities>d__17`2.MoveNext()
  at Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider.ExceptionInterceptor`1.EnumeratorExceptionInterceptor.MoveNext()
  at System.Linq.Enumerable.TryGetFirst[TSource](IEnumerable`1 source, Boolean& found)    
  at System.Linq.Enumerable.First[TSource](IEnumerable`1 source)    
  at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<>c__DisplayClass15_1`1.<CompileQueryCore>b__0(QueryContext qc)    
  at System.Linq.Queryable.FirstOrDefault[TSource](IQueryable`1 source)    
  at ProjectProcess.DownloadProject(Int32 downloadId) in C:\Users\Projects\ProjectWebsite\BusinessLogic\ProjectProcess.cs:line 124    
  at ProjectController.DownloadProject(Int32 downloadID) in C:\Users\Projects\ProjectWebsite\Controllers\ProjectController.cs:line 33    
  at Microsoft.Extensions.Internal.ObjectMethodExecutor.Execute(Object target, Object[] parameters)    
  at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeActionMethodAsync>d__12.MoveNext()
发生异常:CLR/MySql.Data.MySqlClient.MySqlException Microsoft.EntityFrameworkCore.dll中出现“MySql.Data.MySqlClient.MySqlException”类型的异常,但未在用户代码中处理:“尝试获取锁时发现死锁;尝试重新启动事务' 位于MySql.Data.MySqlClient.MySqlStream.ReadPacket()处 位于MySql.Data.MySqlClient.NativeDriver.GetResult(Int32&affectedRow、Int64&insertedId) 位于MySql.Data.MySqlClient.Driver.NextResult(Int32 statementId,Boolean force) 在MySql.Data.MySqlClient.MySqlDataReader.NextResult()中 位于MySql.Data.MySqlClient.MySqlCommand.ExecuteReader(CommandBehavior) 在Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.Execute(IRelationalConnection连接、DbCommandMethod executeMethod、iRadonlyDictionary`2参数值) 位于Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.ExecuteReader(IRelationalConnection连接,IReadOnlyDictionary`2参数值) 位于Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable`1.Enumerator.BufferlessMovenText(DbContext),布尔缓冲区) 在Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable`1.Enumerator.MoveNext()中 在System.Linq.Enumerable.SelectEnumerableTerator`2.MoveNext()中 在System.Linq.Enumerable.TryGetFirst[TSource](IEnumerable`1 source,Boolean&found) 位于Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider.ResultEnumerable`1.GetEnumerator() 在Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider.d_u17`2.MoveNext()中 位于Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider.ExceptionInterceptor`1.EnumeratorExceptionInterceptor.MoveNext() 在System.Linq.Enumerable.TryGetFirst[TSource](IEnumerable`1 source,Boolean&found) 在System.Linq.Enumerable.First[TSource](IEnumerable`1 source)处 在Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.c__显示Class15_1`1.b__0(QueryContext qc) 位于System.Linq.Queryable.FirstOrDefault[TSource](IQueryable`1源) 在C:\Users\Projects\ProjectWebsite\BusinessLogic\ProjectProcess.cs中的ProjectProcess.DownloadProject(Int32 downloadId)中:第124行 在C:\Users\Projects\ProjectWebsite\Controllers\ProjectController.cs中的ProjectController.DownloadProject(Int32 downloaddid)处:第33行 位于Microsoft.Extensions.Internal.ObjectMethodExecutor.Execute(对象目标,对象[]参数) 在Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.d_u12.MoveNext()中
我不明白死锁是如何发生的以及如何解决它的问题是您没有锁定特定的记录。在mysql中,可以像这样锁定行

SELECT * FROM users WHERE name = 'name' FOR UPDATE;
但对于你的问题,你可以试试这个。我希望这能解决你的问题

using (var scope = new TransactionScope(TransactionScopeOption.RequireNew,
new TransactionOptions { 
    IsolationLevel = IsolationLevel.ReadUncommitted 
}))
{
  // your select and increment should go here  
}

问题是您没有锁定某些记录。在mysql中,可以像这样锁定行

SELECT * FROM users WHERE name = 'name' FOR UPDATE;
但对于你的问题,你可以试试这个。我希望这能解决你的问题

using (var scope = new TransactionScope(TransactionScopeOption.RequireNew,
new TransactionOptions { 
    IsolationLevel = IsolationLevel.ReadUncommitted 
}))
{
  // your select and increment should go here  
}

你能再试试吗。只是一个快速修复

//replace your line with this
if (download == null) {
    context.SaveChanges();
    scope.Complete();
    throw new InvalidOperationException("Cannot find ProjectDownload.Id");
}

你能再试试吗。只是一个快速修复

//replace your line with this
if (download == null) {
    context.SaveChanges();
    scope.Complete();
    throw new InvalidOperationException("Cannot find ProjectDownload.Id");
}
在使用事务作用域之前,请尝试执行以下操作:

ProjectDownload=context.ProjectDownload.Where(d=>d.Id==downloaddid.FirstOrDefault(); Project proj=context.Project.Where(p=>p.ProjectDownload.Any(pd=>pd.Id==downloaddid)).FirstOrDefault(); 在使用事务作用域之前,请尝试执行以下操作:

ProjectDownload=context.ProjectDownload.Where(d=>d.Id==downloaddid.FirstOrDefault(); Project proj=context.Project.Where(p=>p.ProjectDownload.Any(pd=>pd.Id==downloaddid)).FirstOrDefault();
可能重复的我以前读过但我只有一把钥匙可能重复的我以前读过但我只有一把钥匙。现在,我收到一个不同的错误:连接尝试失败是因为连接方在一段时间后没有正确响应,或者建立的连接失败是因为连接的主机在System.Net.Sockets.NetworkStream.Read(Byte[]buffer,Int32 offset,Int32 size)}消息[string]:无法从传输连接读取数据:连接尝试失败,因为连接方在一段时间后没有正确响应,或者建立的连接失败,因为连接的主机没有响应。“一个问题,为什么拥有一个默认的TransactionScope还不够?谢谢@mjwills,我想现在我知道Serializable是默认的隔离级别,它是最安全的级别,但并发能力最低。但是无论如何,为什么在我的查询中会出现死锁?很可能是隔离级别导致了死锁。可能是因为缺少了finally scope rollback部分。你从中间抛出异常。覆盖整个身体,并尝试添加最后一层。现在,我收到一个不同的错误:连接尝试失败是因为连接方在一段时间后没有正确响应,或者建立的连接失败是因为连接的主机在System.Net.Sockets.NetworkStream.Read(Byte[]buffer,Int32 offset,Int32 size)}消息[string]:无法从传输连接读取数据:连接尝试失败,因为连接方在一段时间后没有正确响应,或者建立了连接f