多个客户端同一时刻执行相同的数据库操作,发生死锁
halo 我们做了一组客户端(大约三十个),第天凌晨同一时刻按城市更新当天的数据,这时候经常报一个死锁的异常,我们解决了这个问题,但感觉不保险,如果客户端的量大到一定程序,这个问题还是会出现的,所以向各个求助有没有更好好的解决办法。
using (SqlConnection conn = new SqlConnection("..."))
{
SqlTransaction tran = null;
try
{
conn.Open();
tran = conn.BeginTransaction();
ExecuteNonQuery("update tabA set ...");// 按主键更新一行数据
StringBuilder sb = new StringBuilder();
sb.Append("delete from tab4 where city=@City;");
sb.Append("delete from tab3 where city=@City;");
sb.Append("delete from tab2 where city=@City;");
sb.Append("delete from tab1 where city=@City;");
ExecuteNonQuery(tran, sb.ToString(), parameter);// 这里异常
SqlBulkCopyData(tran, datatable1, "tab1");
SqlBulkCopyData(tran, datatable2, "tab2");
SqlBulkCopyData(tran, datatable3, "tab3");
SqlBulkCopyData(tran, datatable4, "tab4");
tran.Commit();
return true;
}
catch (Exception ex)
{
if (tran != null)
tran.Rollback();
LogHelper.RecordErrorLog(ex);
return false;
}
}
记录时间:2013-10-31 03:00:10
- 程序集名称:.Net SqlClient Data Provider
- 发生异常的方法:Void OnError(System.Data.SqlClient.SqlException, Boolean)
- 错误信息:事务(进程 ID 78)与另一个进程被死锁在 锁 资源上,并且已被选作死锁牺牲品。请重新运行该事务。
- 堆栈信息:
在 System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection)
在 System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning()
在 System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)
在 System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)
在 System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async)
在 System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result)
在 System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(DbAsyncResult result, String methodName, Boolean sendToPipe)
在 System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
[解决办法]
首先确定是那种锁。
造成死锁的原因是什么。
对数据的操作最合理的是单进程的线程执行(终级目标)。你得想办法使用统一的操作接口。
[解决办法]
对数据的操作最合理的是单进程的线性执行(终级目标)。你得想办法使用统一的操作接口。
[解决办法]
tran.BeginTransaction();
和
tran.Commit();之间你分别执行 ExecuteNonQuery()两次,一般一次就够了.应该把两个语句放到一起一次执行
[解决办法]
“多个客户端同一时刻执行相同的数据库操作”
这本身看起来就很可怕。