ADO.NET 死锁
我遇到了以下(简化的)代码的间歇性死锁情况。
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() 命令填充数据集不应在数据库上创建锁定。 并且,从错误消息中可以看出该锁由另一个进程拥有。 我正在查询的视图只有 select 语句,但它确实将几个表连接在一起。
- 仅执行 select 语句的视图会受到锁定记录的影响吗?
- ADO.Net .Fill() 可以/是否锁定记录?
- 假设我需要填充一个数据集,有没有办法避免潜在的数据锁定?
SQL Server 2005 (9.0.4035)
I'm experiencing an intermittent deadlock situation with following (simplified) code.
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();
The error I get is:
Transaction (Process ID 269) was
deadlocked on lock resources with
another process and has been chosen as
the deadlock victim. Rerun the
transaction.
As I understand it, simply filling a DataSet via the ADO.Net .Fill() command shouldn't create a lock on the database.
And, it would appear from the error message that the lock is owned by another process.
The View I'm querying against has select statements only, but it does join a few table together.
- Can a view that is only going a select statement be affected by locked records?
- Can/Does ADO.Net .Fill() Lock Records?
- Assuming I need to fill a DataSet, is there a way to do so that would avoid potential data locks?
SQL Server 2005 (9.0.4035)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
带有连接的选择查询确实会导致死锁。处理此问题的一种方法是使用快照隔离在 SqlTransaction 中执行查询。
可能会发生死锁,因为它会在执行连接之前锁定一个接一个地连接的每个表。如果另一个查询在另一个查询需要锁定的表上有锁,反之亦然,则存在死锁。使用快照隔离,仅从表中读取的查询不会锁定它们。由于读取实际上是从事务开始时的数据快照完成的,因此可以保持完整性。
但是,由于必须生成快照的开销,这可能会对性能产生负面影响。根据应用程序的不同,最好不要使用快照隔离,相反,如果查询失败并导致死锁,请稍等片刻然后重试。
最好尝试找出发生死锁的原因并更改数据库的结构和/或修改应用程序以防止死锁。此文章提供了更多信息。
A select query with joins can indeed cause a deadlock. One way to deal with this is to do the query in a SqlTransaction using Snapshot Isolation.
A deadlock can occur because it locks each table being joined one after another before performing the join. If another query has a lock on a table that the other query needs to lock, and vice versa, there is a dead lock. With Snapshot Isolation queries that just read from tables do not lock them. Integrity is maintained because the read is actually done from a snapshot of the data at the time the transaction started.
This can have a negative impact on performance, though, because of the overhead of having to produce the snapshots. Depending on the application, it may be better to not use snapshot isolation and instead, if a query fails do to a deadlock, wait a little while and try again.
It might also be better to try to find out why the deadlocks are occurring and change the structure of the database and/or modify the application to prevent deadlocks. This article has more information.
您可以尝试以下操作:
IsolationLevel.ReadUncommited
)。NOLOCK
提示。You may try this:
IsolationLevel.ReadUncommited
).NOLOCK
hint on you query.它可能离您的问题还很遥远,并且不是您问题的解决方案,请先检查其他解决方案 - 但是,我们遇到了类似的问题(锁定记录的选择!),经过大量努力,我们跟踪到文件/SMB 层。似乎在重负载下,从网络驱动器 (SAN) 读取文件被阻止,从而在实际数据库文件上创建等待读取锁定。这表示为对所包含记录的锁定。
但这是一种竞争条件,在驱动器没有负载的情况下无法重现。哦,这也是 SQL Server 2005。
您应该能够使用 SQL Server 包含的工具来确定哪些事务彼此陷入死锁。
It might be far off and not the solution to your problem, check other solutions first - but, we had a similar problem (a select that locks records!) that after much effort we tracked to the file/SMB layer. It seemed that under heavy load, reading files from the networked drive (SAN) got held up, creating a waiting read lock on the actual database files. This expressed as a lock on the records contained.
But this was a race condition and not reproducable without load on the drives. Oh, and it was SQL Server 2005, too.
You should be able to determine using the SQL Server included tools which transactions are deadlocking each other.