我有一个PowerShell脚本,用于循环SQL Server列表并从这些服务器中提取扩展事件数据。它在95%的SQL Server上工作得很好但是我的SQL Server大约有5%我得到了这个错误:
写数据表:System.Management.Automation.MethodInvocationException: 使用“1”参数调用“WriteToServer”的异常:
“读取器关闭时无法尝试调用FieldCount。” System.InvalidOperationException:无效尝试调用FieldCount 当读者关闭时。
at System.Data.SqlClient.SqlDataReader.get_FieldCount()at System.Data.SqlClient.SqlBulkCopy.WriteToServer(IDataReader reader)at CallSite.Target(Closure,CallSite,Object,Object) ---内部异常堆栈跟踪结束---在System.Management.Automation.ExceptionHandlingOps.CheckActionPreference(FunctionContext) funcContext,异常异常)at System.Management.Automation.Interpreter.ActionCallInstruction`2.Run(InterpretedFrame 框架) System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame 框架) System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame 帧).Message
我不明白为什么我的脚本可以在大多数SQL Server上运行,但不是全部。
我的PowerShell脚本:
#Create your SQL connection string to your central collection database
$ServerAConnectionString = "Data Source=SourceServer;Initial Catalog=SourceDatabase;Integrated Security=True;" $ServerAConnection = new-object system.data.SqlClient.SqlConnection($ServerAConnectionString);
#Create a Dataset to hold the DataTable from DBServers
$dataSet = new-object "System.Data.DataSet" "DBServers" $query = "SET NOCOUNT ON;" $query = $query + " SELECT ServerName, FilePath " $query = $query
+ " FROM dbo.SourceTable " $query = $query + " WHERE Domain = 'domain' " $query = $query + " AND XEventQueryEnabled = 1 "
#write-host $query;
#Create a DataAdapter which youll use to populate the DataSet with the instances to collect from
$dataAdapter = new-object "System.Data.SqlClient.SqlDataAdapter" ($query, $ServerAConnection) $dataAdapter.Fill($dataSet) #| Out-Null $ServerAConnection.Open() $sourceConnection = New-Object System.Data.SqlClient.SQLConnection($SourceConnectionString)
$CollectionTime = date; foreach($a in $dataSet.Tables[0].Rows) { write-host "DBServer: " $a.ServerName; # set connection string for the remote server
$SourceConnectionString = "Server="+$a.Servername+"; Initial Catalog = master; integrated security = true" # set connection string for the central collection server
$DestinationConnectionString = "Data Source=RepositoryServer;Initial Catalog=RepositoryDatabase;Integrated Security=True"
try
{
$sql = " WITH cte (event_data) as "
$sql = $sql + " (SELECT CAST(event_data AS XML) AS event_data "
$sql = $sql + " FROM sys.fn_xe_file_target_read_file(N'"+$a.FilePath+"MyXevents*.xel', NULL, NULL, NULL)) "
$sql = $sql + " SELECT @@SERVERNAME, * FROM cte "
$sql = $sql + " WHERE SWITCHOFFSET(event_data.value('(event/@timestamp)[1]', 'datetimeoffset'),DATEPART(Tzoffset, SYSDATETIMEOFFSET())) > '2/1/16' "
try{
write-host "Collecting XEvent XML Data from Remote SQL Server.";
$tableName = "RepositoryTable"
$sourceConnection.ConnectionString = $SourceConnectionString
$sourceConnection.open()
$commandSourceData = New-Object system.Data.SqlClient.SqlCommand($sql,$sourceConnection)
$reader = $commandSourceData.ExecuteReader()
$commandSourceData.CommandTimeout = '300'
}
Catch
{
$ex1 = $_.Exception.Message
} # end CATCH block for bad file/offset
write-host "Inserting XEvent XML Data to Repository.";
$bulkCopy = new-object ("Data.SqlClient.SqlBulkCopy") $DestinationConnectionString
$bulkCopy.DestinationTableName = $tableName
$bulkCopy.BatchSize = 5000
$bulkCopy.BulkCopyTimeout = 0
$bulkCopy.WriteToServer($reader)
$reader.Close() }
catch
{
$ex = $_.Exception
Write-Host "Write-DataTable$($connectionName):$ex.Message"
}
finally
{
write-host "Finished Collecting XEvent XML Data.";
# $reader.close()
}
$sourceConnection.close() }
#Close the connection as soon as you are done with it $ServerAConnection.Close()
答案 0 :(得分:0)
问题是在Execute Reader之后指定了SQL Command Timeout属性。
之前:
foreach($a in $dataSet.Tables[0].Rows)
{
write-host "DBServer: " $a.ServerName;
# set connection string for the remote server
$SourceConnectionString = "Server="+$a.Servername+"; Initial Catalog = master; integrated security = true"
# set connection string for the central collection server
$DestinationConnectionString = "Data Source=;Initial Catalog=;Integrated Security=True"
try
{
$sql = " WITH cte (event_data) as "
$sql = $sql + " (SELECT CAST(event_data AS XML) AS event_data "
$sql = $sql + " FROM sys.fn_xe_file_target_read_file(N'"+$a.FilePath+"*.xel', NULL, NULL, NULL)) "
$sql = $sql + " SELECT @@SERVERNAME, * FROM cte "
$sql = $sql + " WHERE SWITCHOFFSET(event_data.value('(event/@timestamp)[1]', 'datetimeoffset'),DATEPART(Tzoffset, SYSDATETIMEOFFSET())) between '2/1/16' and '2/2/16' "
try{
write-host "Collecting XEvent XML Data from Remote SQL Server.";
$tableName = "XEventXMLData"
$sourceConnection.ConnectionString = $SourceConnectionString
$sourceConnection.open()
$commandSourceData = New-Object system.Data.SqlClient.SqlCommand($sql,$sourceConnection)
$reader = $commandSourceData.ExecuteReader()
$commandSourceData.CommandTimeout = '300'
}
Catch
{
$ex1 = $_.Exception.Message
} # end CATCH block for bad file/offset
write-host "Inserting XEvent XML Data to Repository.";
$bulkCopy = new-object ("Data.SqlClient.SqlBulkCopy") $DestinationConnectionString
$bulkCopy.DestinationTableName = $tableName
$bulkCopy.BatchSize = 5000
$bulkCopy.BulkCopyTimeout = 0
$bulkCopy.WriteToServer($reader)
$reader.Close()
}
catch
{
$ex = $_.Exception
Write-Host "Write-DataTable$($connectionName):$ex.Message"
}
finally
{
write-host "Finished Collecting XEvent XML Data.";
# $reader.close()
}
$sourceConnection.close()
}
后:
foreach($a in $dataSet.Tables[0].Rows)
{
write-host "DBServer: " $a.ServerName;
# set connection string for the remote server
$SourceConnectionString = "Server="+$a.Servername+"; Initial Catalog = master; integrated security = true"
# set connection string for the central collection server
$DestinationConnectionString = "Data Source=;Initial Catalog=;Integrated Security=True"
try
{
$sql = " WITH cte (event_data) as "
$sql = $sql + " (SELECT CAST(event_data AS XML) AS event_data "
$sql = $sql + " FROM sys.fn_xe_file_target_read_file(N'"+$a.FilePath+"*.xel', NULL, NULL, NULL)) "
$sql = $sql + " SELECT @@SERVERNAME, * FROM cte "
$sql = $sql + " WHERE SWITCHOFFSET(event_data.value('(event/@timestamp)[1]', 'datetimeoffset'),DATEPART(Tzoffset, SYSDATETIMEOFFSET())) > '2/1/16' "
write-host "Collecting XEvent XML Data from Remote SQL Server.";
$sourceConnection.ConnectionString = $SourceConnectionString
$sourceConnection.open()
$commandSourceData = New-Object system.Data.SqlClient.SqlCommand
$commandSourceData.CommandText = $sql
$commandSourceData.Connection = $sourceConnection
$commandSourceData.CommandTimeout = 0
$reader = $commandSourceData.ExecuteReader()
write-host "Inserting XEvent XML Data to Repository.";
$bulkCopy = new-object ("Data.SqlClient.SqlBulkCopy") $DestinationConnectionString
$bulkCopy.DestinationTableName = $tableName
$bulkCopy.BatchSize = 5000
$bulkCopy.BulkCopyTimeout = 0
$bulkCopy.WriteToServer($reader)
$reader.Close()
}
catch
{
$ex = $_.Exception
Write-Host "Write-DataTable$($connectionName):$ex.Message"
}
finally
{
write-host "Finished Collecting XEvent XML Data.";
# $reader.close()
}
$sourceConnection.close()
}