gpt4 book ai didi

c# - 如何摆脱 SQL Server 2005 和 C# 应用程序中的死锁?

转载 作者:太空狗 更新时间:2023-10-30 00:25:42 24 4
gpt4 key购买 nike

我在 C# 中有一个用于 Windows 服务的代码,主要负责更新我数据库中表中的记录,但是我的日志中总是有很多错误,所有错误都是关于资源死锁的,

这是错误:

System.Data.SqlClient.SqlException (0x80131904): Transaction (Process ID 57) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction. at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action1 wrapCloseInAction) at
System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject
stateObj, Boolean callerHasConnectionLock, Boolean asyncClose) at
System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior,
SqlCommand cmdHandler, SqlDataReader dataStream,
BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject
stateObj, Boolean& dataReady) at
System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds,
RunBehavior runBehavior, String resetOptionsString) at
System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior
cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean
async, Int32 timeout, Task& task, Boolean asyncWrite) at
System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior
cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String
method, TaskCompletionSource
1 completion, Int32 timeout, Task& task, Boolean asyncWrite) at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource`1 completion, String methodName, Boolean sendToPipe, Int32 timeout, Boolean asyncWrite) at System.Data.SqlClient.SqlCommand.ExecuteNonQuery() at WheelTrackListener.DataAccess.SQLDBA.ExecuteNQuery(SqlCommand cmd, Boolean isShowError, ConnectionStringType CountryCode, String deviceID, Int32 retry, String functionCallName) ClientConnectionId:e45e4cf1-a113-46b7-b9b5-dc5ee8111406

现在我想问一下,我可以尝试一下或者检查资源是否被锁定了吗?如果锁定,如何等待更新直到发布?

这是我当前的代码:

public static int updateVehicleLastPosition(string UTCDate, string UTC_Time, 
string NS_Indicator, string Latitude, string EWIndicator,
string Longtitude, string Speed, string Processed,
string Near_ByLocation, string Near_ByLocation_AR,
string Gis_dataID, string address, string ar_adress, string Device_ID)
{
SQLMethods sql = new SQLMethods();
SqlCommand cmd = sql.cmdUpdateVehicleLastPosition(UTCDate, UTC_Time, NS_Indicator, Latitude, EWIndicator, Longtitude, Speed, Processed, Near_ByLocation, Near_ByLocation_AR, Gis_dataID, address, ar_adress, Device_ID);
SQLDBA sqlDBA = new SQLDBA();
return sqlDBA.ExecuteNQuery(cmd, true, ConnectionStringType.OMN, Device_ID, 10, "updateVehicleLastPosition");
}

public SqlCommand cmdUpdateVehicleLastPosition(string UTCDate, string UTC_Time,
string NS_Indicator, string Latitude, string EWIndicator,
string Longtitude, string Speed, string Processed,
string Near_ByLocation, string Near_ByLocation_AR,
string Gis_dataID, string address, string ar_adress,
string Device_ID)
{
string sql = "UPDATE CTS_VehicleLastPosition SET [UTCDate] = @UTCDate, [UTC_Time] = @UTC_Time, [NS_Indicator] = @NS_Indicator, [Latitude] = @Latitude, [EWIndicator] = @EWIndicator, [Longtitude] = @Longtitude, [Speed] = @Speed, [Processed] = @Processed, [Near_ByLocation] = @Near_ByLocation, [Near_ByLocation_AR] = @Near_ByLocation_AR, [Gis_dataID] = @Gis_dataID, [address] = @address, [ar_adress] = @ar_adress WHERE [Device_ID] = @Device_ID";

SqlCommand cmd = new SqlCommand(sql);
cmd.Parameters.AddWithValue("@UTCDate", UTCDate);
cmd.Parameters.AddWithValue("@UTC_Time", UTC_Time);
cmd.Parameters.AddWithValue("@NS_Indicator", NS_Indicator);
cmd.Parameters.AddWithValue("@Latitude", Latitude);
cmd.Parameters.AddWithValue("@EWIndicator", EWIndicator);
cmd.Parameters.AddWithValue("@Longtitude", Longtitude);
cmd.Parameters.AddWithValue("@Speed", Speed);
cmd.Parameters.AddWithValue("@Processed", Processed);
cmd.Parameters.AddWithValue("@Near_ByLocation", Near_ByLocation);
cmd.Parameters.AddWithValue("@Near_ByLocation_AR", Near_ByLocation_AR);
cmd.Parameters.AddWithValue("@Gis_dataID", Gis_dataID);
cmd.Parameters.AddWithValue("@address", address);
cmd.Parameters.AddWithValue("@ar_adress", ar_adress);
cmd.Parameters.AddWithValue("@Device_ID", Device_ID);
return cmd;
}

public int ExecuteNQuery(SqlCommand cmd, bool isShowError,
DataAccess.ConnectionStringType CountryCode, string deviceID,
int retry, string functionCallName)
{
ConnectionManager Connection = new ConnectionManager();
try
{
Connection.GetConnection(CountryCode);
if ((Connection.con == null) || (Connection.con.State != ConnectionState.Open))
{
if (retry <= 0) return 0;
else return ExecuteNQuery(cmd, isShowError, CountryCode, deviceID, retry - 1, functionCallName);
}
int rowsAffected = 0;
cmd.Connection = Connection.con;
rowsAffected = cmd.ExecuteNonQuery();
return rowsAffected;
}
catch (SqlException sqlexception)
{
if (isShowError)
LEAMRALogger.Logger.WriteByDate("Logs\\SQLDBA\\" + functionCallName + "\\" + String.Format("{0:dd-MM-yyyy}", DateTime.Now), "SQLDBA", "SQLDBA_ERROR", "ExecuteNQuery Function: [deviceID: " + deviceID + " | retry: " + retry + "] " + sqlexception.ToString());
}
catch (Exception ex)
{
if (isShowError)
LEAMRALogger.Logger.WriteByDate("Logs\\SQLDBA\\" + functionCallName + "\\" + String.Format("{0:dd-MM-yyyy}", DateTime.Now), "SQLDBA", "SQLDBA_ERROR", "ExecuteNQuery Function: [deviceID: " + deviceID + " | retry: " + retry + "] " + ex.ToString());
}
finally
{
if ((Connection.con != null) && (Connection.con.State == ConnectionState.Open))
{
Connection.con.Close();
Connection.con.Dispose();
}

GC.Collect();
}
if (retry <= 0) return 0;
else return ExecuteNQuery(cmd, isShowError, CountryCode, deviceID, retry - 1, functionCallName);
}

最佳答案

我在您的代码中看不到任何明确的事务范围,因此我不知道您在进行更新时已经设置了哪些锁;也不清楚您使用的是什么隔离级别。但在这种情况下最常见的情况是,在同一事务的早些时候,您已经在稍后尝试更新的相同行上发出了选择(读锁)。这将导致锁升级,如果两个事务试图做同样的事情,可能会导致死锁:

  1. 事务A:读锁选择
  2. 事务 B:选择和读取锁
  3. 事务 A:更新 - 想要将其读锁升级为写锁,但必须等待事务 B 释放其读锁锁
  4. 事务 B:更新 - 想要将其读锁升级为写锁,但必须等待事务 A 释放它的读锁锁。

宾果游戏!死锁,因为 A 和 B 都在等待对方释放现有的读锁,然后才能进行更新。

为了防止这种情况,您需要在您的选择中添加一个升级锁提示,例如,

select * from table with (updlock) where blah blah

这将确保您的选择使用写锁而不是读锁,这将防止并发事务之间的锁升级。

关于c# - 如何摆脱 SQL Server 2005 和 C# 应用程序中的死锁?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15927307/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com