使用 SqlTransaction 处理数千个 SqlCommand 会导致内存异常
-
12-12-2019 - |
题
我使用 SQL Server 2008 Express 数据库在标准 C# Windows 窗体应用程序中编写了自定义复制函数。它基本上会拉取一组需要针对订阅者数据库执行的 SQL 语句。完全刷新后,最多可以运行 200k+ 条需要执行的语句。
我在代码块内处理这些语句,如下所示:
using (SqlConnection connection = ConnectionManager.GetConnection())
{
connection.Open();
SqlTransaction transaction = connection.BeginTransaction();
// Process 200k+ Insert/Update/Delete statements using SqlCommands
transaction.Commit
}
我发现我的应用程序的前 30k 语句的内存使用量保持在 40mb 左右,非常稳定。之后它似乎突然跳到 300mb 左右,然后不断增长,直到遇到 OutOfMemory 异常。
我使用的方法是否可能,我可以在单个事务中处理那么多语句吗?我想我应该能够做到这一点。如果有更好的方法我很乐意在这里。我需要它是事务性的,否则部分复制将导致数据库损坏。
谢谢。
编辑:
重新启动计算机后,我成功完成了 200k+ 的完整复制。尽管在复制完成后内存使用量一度增长到 1.4Gb,但内存使用量一路下降到 40mb。这让我得出结论,我的循环中处理命令的某些东西可能导致了内存的增长。
解决方案
你是 Disposing
关闭前您的表格和一次性控制装置?
将所有 Disposable 对象包装在 using 语句中。点击这里了解更多详情
不要一遍又一遍地打开/关闭连接,而是在单个事务中将数据发送到数据库。点击这里了解更多详情
尽管如此,您的应用程序仍然占用太多内存,那么您需要像 Red Gate Ants Memory Profiler 这样的 Doctor。单击此处查看有关它的更多详细信息
我可以在单个事务中处理那么多语句吗?
您有以下选项可以执行此操作...
- 批量插入并操作记录
Stored Proc
. - 准备
XML
并将字符串发送到Database
. - 发送只读
DataTable
通过存储过程在 Sql Server 中
示例存储过程
Begin Try
Set NoCount ON
Set XACT_Abort ON
Begin TRan
--Your queries
Commit Tran
Begin Tran
Begin Catch
Rollback Tran
End Catch
确保 Dispose
对象一旦不使用。
应该是这样的
using (SqlConnection connection = new SqlConnection())
{
connection.Open();
using (SqlTransaction transaction = connection.BeginTransaction())
{
transaction.Commit();
}
}
您是否验证了 SqlCommand
还?
using (SqlCommand cmd = new SqlCommand())
{
}
不隶属于 StackOverflow