Inv*_*con 5 .net c# sql-server deadlock
我的.NET应用程序的事件日志显示它在从Sql Server读取时偶尔会出现死锁.这通常非常罕见,因为我们已经优化了查询以避免死锁,但它们有时仍会发生.在过去,我们在调用实例ExecuteReader
上的函数时发生了一些死锁SqlCommand
.为了解决这个问题,我们添加了重试代码,以便再次运行查询,如下所示:
//try to run the query five times if a deadlock happends
int DeadLockRetry = 5;
while (DeadLockRetry > 0)
{
try
{
return dbCommand.ExecuteReader();
}
catch (SqlException err)
{
//throw an exception if the error is not a deadlock or the deadlock still exists after 5 tries
if (err.Number != 1205 || --DeadLockRetry == 0)
throw;
}
}
Run Code Online (Sandbox Code Playgroud)
这对于在初始查询执行期间发生死锁的情况非常有效,但现在我们在使用Read()
返回的函数迭代结果时遇到死锁SqlDataReader
.
同样,我并不关心优化查询,而只是尝试在极少数情况下恢复发生死锁.我在考虑使用类似的重试过程.我可以创建自己的继承的类,SqlDataReader
只需Read
使用重试代码覆盖该函数.像这样:
public class MyDataReader : SqlDataReader
{
public override bool Read()
{
int DeadLockRetry = 5;
while (DeadLockRetry > 0)
{
try
{
return base.Read();
}
catch (SqlException ex)
{
if (ex.ErrorCode != 1205 || --DeadLockRetry == 0)
throw;
}
}
return false;
}
}
Run Code Online (Sandbox Code Playgroud)
这是正确的方法吗?我想确保读者不会跳过记录.Read
在死锁后重试是否会跳过任何行?此外,我应该Thread.Sleep
在重试之间调用以给数据库时间以摆脱死锁状态,或者这是否足够.这种情况不容易重现,所以我想在修改任何代码之前确定它.
编辑:
根据要求,更多关于我的情况的信息:在一个案例中,我有一个进程执行一个查询,加载需要更新的记录ID列表.然后,我使用该Read
函数遍历该id列表,并对该记录运行更新过程,最终将更新数据库中该记录的值.(不,没有办法在初始查询中执行更新,对于返回的每个记录,会发生许多其他事情).这段代码已经运行了一段时间,但我们为每条记录运行了相当多的代码,所以我可以想象其中一个进程正在读取初始表上的锁.
经过一番思考,Scottie建议使用数据结构存储结果可能会解决这种情况.我可以存储在a中返回的id List<int>
并循环遍历.这样就可以立即删除行上的锁.
但是,我仍然有兴趣知道是否有一种通用方法可以从读取死锁中恢复.
您的整个交易将在僵局中丢失。您必须从头开始,从高于您读取数据读取器的级别开始。你说你读取了一些记录,然后循环更新它们。您必须重新启动并再次读取记录:
function DoWork() {
using (TransactionScope scope = new TransactionScope(...)) {
cmd = new SqlCommand("select ...");
using (DataReader rdr = cmd.ExecuteReader ()) {
while(rdr.Read()) {
... process each record
}
}
scope.Complete ();
}
}
Run Code Online (Sandbox Code Playgroud)
您必须重试整个 DoWork
通话:
retries = 0;
success = false;
do {
try {
DoWork ();
success = true;
}
catch (SqlException e) {
if (can retry e) {
++retries;
}
else {
throw;
}
}
} while (!success);
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
5148 次 |
最近记录: |