ADO.NET DeadLock

时间:2010-11-03 19:28:14

标签: sql-server-2005 ado.net deadlock

我遇到了以下(简化)代码的间歇性死锁情况。

DataSet my_dataset = new DataSet()
SqlCommand sql_command = new SqlCommand();

sql_command.Connection = <valid connection>
sql_command.CommandType = CommandType.Text;
sql_command.CommandText = 'SELECT * FROM MyView ORDER BY 1'

SqlDataAdapter data_adapter = new SqlDataAdapter(sql_command);

sql_command.Connection.Open();

data_adapter.Fill(my_dataset);

sql_command.Connection.Close();

我得到的错误是:

  

交易(流程ID 269)是   锁定资源死锁   另一个过程并被选为   死锁的受害者。重新运行   事务。

据我了解,只需通过ADO.Net .Fill()命令填充DataSet不应该在数据库上创建锁。 并且,从错误消息中可以看出锁是由另一个进程拥有的。 我正在查询的View只有select语句,但它确实将几个表连接在一起。

  • 只有select语句的视图是否会受到锁定记录的影响?
  • 可以/可以ADO.Net .Fill()锁定记录吗?
  • 假设我需要填充DataSet,有没有办法可以避免潜在的数据锁?

SQL Server 2005(9.0.4035)

3 个答案:

答案 0 :(得分:2)

带有连接的选择查询确实会导致死锁。解决此问题的一种方法是使用快照隔离在SqlTransaction中执行查询。

using(SqlTransaction sqlTran = connection.BeginTransaction(IsolationLevel.Snapshot))
{
    // Query goes here.
}

可能会发生死锁,因为它会在执行连接之前一个接一个地锁定每个正在连接的表。如果另一个查询对另一个查询需要锁定的表具有锁定,反之亦然,则存在死锁。使用仅从表中读取的Snapshot Isolation个查询不会锁定它们。保持完整性是因为读取实际上是从事务开始时的数据快照完成的。

但是,这可能会对性能产生负面影响,因为必须生成快照的开销。根据应用程序的不同,最好不要使用快照隔离,相反,如果查询失败会导致死锁,请稍等片刻再试一次。

尝试找出死锁发生的原因并更改数据库的结构和/或修改应用程序以防止死锁也可能更好。这个article有更多信息。

答案 1 :(得分:1)

你可以试试这个:

  • 降低该查询的事务级别(例如,IsolationLevel.ReadUncommited)。
  • 在查询时使用NOLOCK提示。

答案 2 :(得分:0)

它可能是遥远的,而不是你的问题的解决方案,首先检查其他解决方案 - 但是,我们有一个类似的问题(一个锁定记录的选择!),经过大量努力,我们跟踪到文件/ SMB层。似乎在负载很重的情况下,从网络驱动器(SAN)读取文件被阻止,从而在实际数据库文件上创建等待读锁定。这表示锁定了所包含的记录。

但这是一种竞争条件,并且在没有负载的情况下无法重现。哦,它也是SQL Server 2005。

您应该能够确定使用SQL Server包含的工具,哪些事务相互死锁。