DataReader导致SQL Server泄漏可用内存

时间:2015-04-29 16:55:28

标签: sql-server powershell ado.net

我有一个PowerShell脚本,它从本地SQL Server Express 2014数据库读取数据并将其写入CSV文件。它工作正常,但它几乎占用了SQL Server的整个可用内存池,并且在脚本运行完毕后没有释放它。即使调用GC.Collect()也不会释放内存;我必须重新启动SQL Server服务才能将其恢复。

这是脚本的相关部分,我已经确定了泄漏事件:

try {
    $sqlConn = New-Object -TypeName System.Data.SqlClient.SqlConnection($sqlConnString);
    $sqlConn.Open();

    $sqlCmd = New-Object -TypeName System.Data.SqlClient.SqlCommand;
    $sqlCmd.Connection = $sqlConn;
    $sqlCmd.CommandType = [System.Data.CommandType]::Text;
    $sqlCmd.CommandText = "SELECT * FROM $exportReadings";

    #Write contents to a CSV file
    $line = New-Object -TypeName System.Text.StringBuilder;
    $out = New-Object -TypeName System.IO.StreamWriter -ArgumentList $csvFile, $false;
    $out.WriteLine("HEADER_ROW");        
    $reader = $sqlCmd.ExecuteReader();
    $cols = $reader.VisibleFieldCount;
    while ($reader.Read()) {
        $line.Clear();
        for ($i = 0; $i -lt $cols; $i++) {
            $val = $reader.GetValue($i);
            if ($val -like "*$delimiter*") {
                $line.Append('"').Append($val).Append('"');
            }
            else {
                $line.Append($val);
            }

            if ($i -ne ($cols - 1)) {
                $line.Append($delimiter);
            }
        }
        $out.WriteLine($line.ToString());
    }
}
catch {
    throw;
}
finally {
    if ($reader) { $reader.Dispose(); }
    if ($out) {
        $out.Close();
        $out.Dispose();
    }
    $sqlCmd.Dispose();
    $sqlConn.Dispose();
}

如果我在运行脚本之前查询SQL Server上的内存使用情况(我使用SELECT * FROM sys.dm_exec_query_resource_semaphores),我的“available_memory_kb”大约为750K。之后,即使脚本终止,它也会在150K左右。

我试图尽可能释放每一种资源,但我必须遗漏一些东西。有什么想法吗?

1 个答案:

答案 0 :(得分:1)

我根本不认为这是一个PowerShell问题。如果您发现SQL服务器的内存已经增加,那么这是正常的。 SQL Server将使用它可以使用的所有内存进行缓存。如果系统中的其他东西需要它,那么该内存将被释放,但是想法是,如果可能的话,它会将每个数据库带入内存并留在那里,以便将来访问非常快。

A Sysadmin’s Guide to Microsoft SQL Server Memory