系统数据.EntityException: 提交时基础提供程序失败

22

使用Entity Framework,在我的一个应用程序中,昨晚我收到了以下异常信息:

System.Data.EntityException: The underlying provider failed on Commit. ---> 
System.Data.SqlClient.SqlException: Timeout expired.  The timeout period elapsed prior 
to completion of the operation or the server is not responding.     
    at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection) 
    at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning()     
    at System.Data.SqlClient.TdsParserStateObject.ReadSniError(TdsParserStateObject stateObj, UInt32 error)
    at System.Data.SqlClient.TdsParserStateObject.ReadSni(DbAsyncResult asyncResult, TdsParserStateObject stateObj)
    at System.Data.SqlClient.TdsParserStateObject.ReadNetworkPacket()     
    at System.Data.SqlClient.TdsParserStateObject.ReadBuffer()     
    at System.Data.SqlClient.TdsParserStateObject.ReadByte()     
    at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler,SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)     
    at System.Data.SqlClient.TdsParser.TdsExecuteTransactionManagerRequest(Byte[] buffer, TransactionManagerRequestType request, String transactionName, TransactionManagerIsolationLevel isoLevel, Int32 timeout, SqlInternalTransaction transaction, TdsParserStateObject stateObj, Boolean isDelegateControlRequest)
    at System.Data.SqlClient.SqlInternalConnectionTds.ExecuteTransactionYukon(TransactionRequest transactionRequest, String transactionName, IsolationLevel iso, SqlInternalTransaction internalTransaction, Boolean isDelegateControlRequest)     
    at System.Data.SqlClient.SqlInternalConnectionTds.ExecuteTransaction(TransactionRequest transactionRequest, String name, IsolationLevel iso, SqlInternalTransaction internalTransaction, Boolean isDelegateControlRequest)
    at System.Data.SqlClient.SqlInternalTransaction.Commit()     
    at System.Data.SqlClient.SqlTransaction.Commit()
    at System.Data.EntityClient.EntityTransaction.Commit()     
    --- End of inner exception stack trace ---     
    at System.Data.EntityClient.EntityTransaction.Commit()     
    at System.Data.Objects.ObjectContext.SaveChanges(SaveOptions options)     
    at System.Data.Entity.Internal.InternalContext.SaveChanges()     
    at System.Data.Entity.Internal.LazyInternalContext.SaveChanges()
这个错误的有趣之处在于数据实际上已经写入数据库。我在MS网站上找到了一篇相关的帖子,似乎表明这是一个与网络有关的错误。
以下是我需要帮助的几个问题:
  1. 我有哪些选项可以解决这个错误?
  2. 这更可能是与网络相关还是数据库有问题?
  3. 如何从代码中确定事务是否真正完成?
  4. 如果出现此错误,应查询数据库以检查是否成功,还是简单地重试事务?
  5. 如果我要重试事务,Entity Framework 应该如何自动完成此操作,还是只需捕获并重试?
  6. 我还应该关注哪些方面?
提前感谢您。
更新:
使用 Ignite for SQL,我们能够确定另一个团队的辅助SQL进程独占了CPU,导致我们的应用程序无法正常运行。简而言之,我们将添加第二个服务器以防止两个团队之间产生进一步的冲突。
仍然有趣的是,事务实际上成功了,而不是失败了。

我知道过去很长时间了,但你能详细说明一下你如何使用 Ignite 进行 SQL 吗?在我的情况下,它并不总是发生,所以很难知道何时监视服务器。 - gitsitgo
我不能说我是一个ignite大师;我们有一个处理这些事情的DB性能团队。当我遇到性能问题时,我通常会寻找顶部SQL语句(如ignite所述的“大条形图”)。那些通常是占用所有资源的查询。从那里开始,就是调整这些查询的问题。很抱歉我不能提供更多你要求的具体信息。祝你好运。 - Randy
2个回答

2
我的猜测是事务提交命令的成功响应没有被发送(或者发送得不够快),导致了代码中的异常。这是一种有点疯狂的边缘情况。这种异常并不一定意味着命令的实际执行失败,只表示存在某种失败。
同样地,如果在调用web服务时出现响应发送问题,也不一定意味着该调用的任何副作用未被应用。

Luke,感谢您的评论。您肯定有正确的想法。我在WS代码中也看到了同样的情况,其中WS处理了请求,但响应超时了。当发生这种情况时,让我感到非常疯狂,因为您无法“知道”事情是否实际上起作用;除非您想编写可以调用以验证事情是否实际上确实起作用的服务。;-) - Randy
1
@Randy,这实际上与计算机网络中的TCP非常相似。原则是,如果我们没有收到消息已传递的确认,我们会重试该消息,直到收到确认。但是,这意味着消息(在本例中为数据库事务)必须是幂等的(即可重放的),而数据库事务并非如此。 - undefined

1

+1给Luke,解释得很好。错误的措辞很不幸。

System.Data.EntityException: **The underlying provider failed on Commit.** ---> 
System.Data.SqlClient.SqlException: Timeout expired.  The timeout period elapsed prior 

应该阅读。
System.Data.EntityException: **The underlying provider failed to respond to Commit**
System.Data.SqlClient.SqlException: Timeout expired.  The timeout period elapsed prior 

可能的原因是网络或服务器问题,例如100%的CPU占用率或其他服务器延迟都是合理的。但是,如果这是超时情况,您不知道是否已提交。如果响应失败,则DB应该已回滚。当然,如果没有发生这种情况,则DB可能已经崩溃并导致潜在的损坏。希望这种情况很少发生。
我曾在一个10亿+行的表中看到这种情况...在增长期间进行空间分配时,由于需要扩展索引和数据区域,需要超过30秒。但是提交确实已经完成了。客户端已超时。在线重新组织也可能会导致此类延迟(至少我在DB2上见过)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接