我运行一个用C#.Net 4.6.1构建的进程来访问SQL Server数据库。该过程在Windows Server 2012 R2 Standard上运行。 SQL Server数据库位于另一台具有SQL Server版本11.0.6567.0
的服务器上该过程执行以下代码:
01 var readStatement = “select * from TableA order by ColumnX,ColumnY, ColumnZ offset 0 rows”; // TableA has 13 million rows
02 var readCommand = new SqlCommand(readStatement, myConnection) { CommandTimeout = 72000 };
03 var reader = readCommand.ExecuteReader();
04 while (reader.Read())
05 {
06 foreach (var columnName in columnNames)
07 {
08 Console.WriteLine(“Checkpoint 1”);
09 var value = reader[columnName];
10 Console.WriteLine(“Checkpoint 2”);
11 }
12 }
此过程通常完成没有问题。有时,它进入第09行(对SqlDataReader.GetValue的调用)并且永远不会返回。我在数据库上运行跟踪时能够见证这个问题。这个过程大约有800万行(在1300万行中),但从未返回。在挂起时,数据库跟踪报告“Batch Completed”,然后是“Audit Logout”。我无法在调试器中复制问题,以查看进程挂起的SqlDataReader.GetValue有多深。它不会遇到内存问题或其他资源限制
以下是进程挂起的调用堆栈:
System.Data.dll!SNINativeMethodWrapper.SNIReadSyncOverAsync正常
[管理到原生过渡]
System.Data.dll!SNINativeMethodWrapper.SNIReadSyncOverAsync(System.Runtime.InteropServices.SafeHandle pConn,ref System.IntPtr packet,int timeout)
System.Data.dll中!System.Data.SqlClient.TdsParserStateObject.ReadSniSyncOverAsync()
System.Data.dll中!System.Data.SqlClient.TdsParserStateObject.TryReadNetworkPacket()
System.Data.dll中!System.Data.SqlClient.TdsParserStateObject.TryPrepareBuffer()
System.Data.dll!System.Data.SqlClient.TdsParserStateObject.TryReadByteArray(byte [] buff,int offset,int len,out int totalRead)
System.Data.dll!System.Data.SqlClient.TdsParserStateObject.TryReadDouble(out double value)
System.Data.dll!System.Data.SqlClient.TdsParser.TryReadSqlValueInternal(System.Data.SqlClient.SqlBuffer value,byte tdsType,int length,System.Data.SqlClient.TdsParserStateObject stateObj)
System.Data.dll!System.Data.SqlClient.TdsParser.TryReadSqlValue(System.Data.SqlClient.SqlBuffer value,System.Data.SqlClient.SqlMetaDataPriv md,int length,System.Data.SqlClient.TdsParserStateObject stateObj,System.Data。 SqlClient.SqlCommandColumnEncryptionSetting columnEncryptionOverride,string columnName)
System.Data.dll!System.Data.SqlClient.SqlDataReader.TryReadColumnInternal(int i,bool readHeaderOnly)
System.Data.dll!System.Data.SqlClient.SqlDataReader.TryReadColumn(int i,bool setTimeout,bool allowPartiallyReadColumn)
System.Data.dll!System.Data.SqlClient.SqlDataReader.GetValueInternal(int i)
System.Data.dll!System.Data.SqlClient.SqlDataReader.GetValue(int i)