Môi trường:ADO.Net SQLCommand.ExecuteReader() chậm hoặc treo
ứng dụng (viết bằng C# cho Net 4) có lên đến 10 bài, mỗi thread chạy trong AppDomain riêng của mình. Mỗi thread sử dụng một DataReader ADO.Net có được kết quả từ thủ tục lưu sẵn trên SQL-Server 2008. Ngoài ra một thread có thể sử dụng ADO.Net để thực hiện một hoạt động ghi (Bulk Insert). Mọi thứ đều chạy trên máy cục bộ.
Sự cố # 1:
Thỉnh thoảng (mỗi lần chạy 30 lần) thực hiện một luồng chậm lại đáng kể. Điều đó xảy ra khi DataReader nhận được các kết quả thủ tục lưu sẵn - SqlCommand.ExecuteReader(). Thông thường hoạt động đọc được thực hiện trong 10 giây. Khi nó chậm lại, nó thực hiện trong 10-20 phút. SQLProfiler cho thấy dữ liệu đang được truy vấn, mặc dù rất chậm.
callstack của suy thoái (xin lưu ý rằng không có trường hợp ngoại lệ):
at SNIReadSync(SNI_Conn* , SNI_Packet** , Int32)
at SNINativeMethodWrapper.SNIReadSync(SafeHandle pConn, IntPtr& packet, Int32 timeout)
at System.Data.SqlClient.TdsParserStateObject.ReadSni(DbAsyncResult asyncResult, TdsParserStateObject stateObj)
at System.Data.SqlClient.TdsParserStateObject.ReadNetworkPacket()
at System.Data.SqlClient.TdsParserStateObject.ReadBuffer()
at System.Data.SqlClient.TdsParserStateObject.ReadByteArray(Byte[] buff, Int32 offset, Int32 len)
at System.Data.SqlClient.TdsParserStateObject.ReadString(Int32 length)
at System.Data.SqlClient.TdsParser.ReadSqlStringValue(SqlBuffer value, Byte type, Int32 length, Encoding encoding, Boolean isPlp, TdsParserStateObject stateObj)
at System.Data.SqlClient.TdsParser.ReadSqlValue(SqlBuffer value, SqlMetaDataPriv md, Int32 length, TdsParserStateObject stateObj)
at System.Data.SqlClient.SqlDataReader.ReadColumnData()
at System.Data.SqlClient.SqlDataReader.ReadColumnHeader(Int32 i)
at System.Data.SqlClient.SqlDataReader.ReadColumn(Int32 i, Boolean setTimeout)
at System.Data.SqlClient.SqlDataReader.GetValueInternal(Int32 i)
at System.Data.SqlClient.SqlDataReader.GetValue(Int32 i)
at System.Data.SqlClient.SqlDataReader.get_Item(String name)
at ****.Core.TableDataImporter.ImportDataFromExcel(Int32 tableId, ExcelEntityLocation location, Boolean& updateResult) in …
Vấn đề # 2:
Thay vì một chậm lại một sợi có thể treo.
callstack:
at SNIReadSync(SNI_Conn* , SNI_Packet** , Int32)
at SNINativeMethodWrapper.SNIReadSync(SafeHandle pConn, IntPtr& packet, Int32 timeout)
at System.Data.SqlClient.TdsParserStateObject.ReadSni(DbAsyncResult asyncResult, TdsParserStateObject stateObj)
at System.Data.SqlClient.TdsParserStateObject.ReadNetworkPacket()
at System.Data.SqlClient.TdsParserStateObject.ReadBuffer()
at System.Data.SqlClient.TdsParserStateObject.ReadByte()
at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)
at System.Data.SqlClient.SqlDataReader.ConsumeMetaData()
at System.Data.SqlClient.SqlDataReader.get_MetaData()
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)
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result)
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method)
at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method)
at System.Data.SqlClient.SqlCommand.ExecuteReader()
Callstacks đã được mua lại sử dụng công cụ gỡ lỗi trong thread nền. Không có trường hợp ngoại lệ nào xảy ra, hoặc chậm lại hoặc treo lên.
SNIReadSync là một cơ chế hoạt động trên cấp độ mạng và hoạt động với việc truyền các gói trên mạng. Chúng tôi đã sao chép vấn đề này trên máy địa phương, loại bỏ các vấn đề về mạng khỏi phương trình.
Chúng tôi đang tìm kiếm bất kỳ đầu vào và giải pháp hoặc cách giải quyết nào cho sự cố chậm/treo này. Bây giờ chúng tôi lập kế hoạch để phát hiện sự chậm lại khi chạy lại thao tác. Cảm ơn trước.
Tôi đang phụ đang đơn giản hóa cho phương pháp theo yêu cầu:
public void ImportDataFromExcel()
{
try
{
var _сonnectionBuilk = ... ; // singleton connection (at the app level)
var spName = ... ; // stored procedure name
var сonnectionToRead = new SqlConnection(connectionStirng);
сonnectionToRead.Open();
var sqlCommand = new SqlCommand(spName);
sqlCommand.CommandType = CommandType.StoredProcedure;
sqlCommand.Parameters.Add(param1Name, SqlDbType.Int).Value = ...;
sqlCommand.Parameters.Add(param2Name, SqlDbType.Int).Value = ...;
sqlCommand.Parameters.Add(param2Name, SqlDbType.Int).Value = ...;
sqlCommand.Connection = сonnectionToRead;
sqlCommand.CommandTimeout = timeout; // 120 sec
using (var dataReader = sqlCommand.ExecuteReader())
{
dataReader.Read();
.....
int pos1 = dataReader.GetOrdinal(columnName1);
int pos2 = dataReader.GetOrdinal(columnName2);
int pos3 = dataReader.GetOrdinal(columnName3);
int pos4 = dataReader.GetOrdinal(columnName4);
.....
// reading data from sqldatareader
int val1 = dataReader.GetInt32(pos1);
int val2 = dataReader.GetInt32(pos2);
int val3 = dataReader.GetInt32(pos3);
var val4 = dataReader.GetDateTime(pos4);
.....
// append read data into bulkTable
bulkTable.AddCellValue(val1, val2, val3, val4); // bulkTable wraps DataTable, and appends DataRow inside.
if(bulkTable.DataTable.Rows > MaxRowsCount)
{
using (var bulkCopy = new SqlBulkCopy(_сonnectionBuilk))
{
bulkCopy.DestinationTableName = _fullTableName;
bulkCopy.WriteToServer(bulkTable.DataTable);
}
var sqlCommandTransfer = new SqlCommand(spName);
sqlCommandTransfer.CommandType = CommandType.StoredProcedure;
sqlCommandTransfer.Parameters.Add(param1Name, SqlDbType.Int).Value = ...;
sqlCommandTransfer.Connection = _сonnectionBuilk;
....
sqlCommandTransfer.ExecuteNonQuery(); // transfering data from temp bulk table into original table
}
}
}
finally
{
bulkTable.Dispose();
сonnectionToRead.Close();
}
}
Bạn có thể hiển thị mã không? Đặc biệt là nơi bạn đang tạo, mở, đóng kết nối và thực hiện trình đọc. –
Điều đó nghe giống như một vấn đề ở phía bên trái. Có một số quá trình công nhân trên sql chạy định kỳ? Một Đồng bộ hoặc một số hành động gây ra khóa hàng/bảng? Các bảng có liên quan như thế nào? loại chỉ mục/ràng buộc nào, v.v. – Brian
@TimSchmelter - Tôi đã thêm mã bị treo. – Cortlendt