我遇到了以下(简化)代码的间歇性死锁情况。
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语句,但它确实将几个表连接在一起。
SQL Server 2005(9.0.4035)
答案 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包含的工具,哪些事务相互死锁。