【问题标题】:SQL conversion script causes System.OutOfMemoryExceptionSQL 转换脚本导致 System.OutOfMemoryException
【发布时间】:2012-02-14 13:48:54
【问题描述】:

当我运行下面的脚本时,我得到了这个异常。它在大约 20 分钟(+/- 几分钟)后坠毁。如何在不创建批次的情况下防止此异常?我想对所有需要它的客户记录执行此操作。

例外:

An error occurred while executing batch. Error message is: Exception of type 'System.OutOfMemoryException' was thrown.

SQL 转换脚本:

SELECT clientid 
INTO #Temp 
FROM client

DECLARE 
    @iteratorId INT, 
    @phone NVARCHAR(64), 
    @fax NVARCHAR(64),  
    @contactid INT

WHILE (SELECT Count(*) FROM #Temp) > 0 
BEGIN 

    SELECT TOP 1 @iteratorId = clientid FROM #Temp 
    SET @contactid = NULL

    --try and grab the first non null phone number in priority order
    SET @phone = ISNULL((
        SELECT TOP 1 
            dayphone
        FROM contact c 
        INNER JOIN dbo.clientcontact cc ON c.contactid = cc.contactid
        WHERE 
            clientid = @iteratorId
            AND cc.contacttypeid=2
            AND c.dayphone IS NOT NULL
        ORDER BY cc.parentclientcontactid, priority DESC
    ),'')

    --try and grab the first non null fax priority order
    SET @fax = ISNULL((
        SELECT TOP 1 
            fax 
        FROM contact c 
        INNER JOIN dbo.clientcontact cc ON c.contactid = cc.contactid
        WHERE 
            clientid = @iteratorId
            AND cc.contacttypeid=2
            AND c.fax IS NOT NULL
        ORDER BY cc.parentclientcontactid, priority DESC
    ),'')

    IF NOT EXISTS(SELECT * FROM clientcontact WHERE clientid=@iteratorId AND contacttypeid=3 AND priority=1)
    BEGIN       
        INSERT INTO dbo.contact
                ( versionnumber ,
                  createdate ,
                  firstname ,
                  lastname ,
                  title ,
                  middleinitial ,
                  dayphone ,
                  nightphone ,
                  mobilephone ,
                  fax ,
                  securefax ,
                  extranetusername ,
                  extranetpassword ,
                  email ,
                  active ,
                  testfaxpagereceived ,
                  ftpoptionid ,
                  testresultnotify
                )
        VALUES  ( 0 , -- versionnumber - int
                  GETDATE() , -- createdate - datetime
                  NULL , -- firstname - nvarchar(64)
                  NULL , -- lastname - nvarchar(64)
                  NULL , -- title - nvarchar(64)
                  NULL , -- middleinitial - nvarchar(64)
                  NULL , -- dayphone - nvarchar(64)
                  NULL , -- nightphone - nvarchar(64)
                  NULL , -- mobilephone - nvarchar(64)
                  NULL , -- fax - nvarchar(64)
                  '' , -- securefax - bit
                  NULL , -- extranetusername - nvarchar(64)
                  NULL , -- extranetpassword - nvarchar(64)
                  NULL , -- email - nvarchar(127)
                  0 , -- active - bit
                  0 , -- testfaxpagereceived - bit
                  NULL , -- ftpoptionid - int
                  NULL  -- testresultnotify - bit
                )
        SET @contactid = @@IDENTITY

        EXEC dbo.procContactSave 
            @contactid = @contactid, -- int
            @firstname = "General", -- nvarchar(64)
            @middleinitial = NULL, -- nvarchar(64)
            @nightphone = NULL, -- nvarchar(64)
            @lastname = "Info", -- nvarchar(64)
            @email = NULL, -- nvarchar(127)
            @fax = @fax, -- nvarchar(64)
            @testfaxpagereceived = 0, -- bit
            @mobilephone = NULL, -- nvarchar(64)
            @securefax = 0, -- bit
            @active = 1, -- bit
            @extranetpassword = NULL, -- nvarchar(64)
            @extranetusername = NULL, -- nvarchar(64)
            @title = NULL, -- nvarchar(64)
            @ftpoptionid = NULL, -- int
            @dayphone = @phone, -- nvarchar(64)
            @testresultnotify = 0, -- bit
            @audituserid = 0 -- int

        EXEC dbo.procClientContactSave 
            @clientcontactid = NULL, -- int
            @priority = 1, -- int
            @clientid = @iteratorId, -- int
            @contacttypeid = 3, -- int
            @contactid = @contactid, -- int
            @audituserid = 0 -- int
    END 

    DELETE #Temp Where clientid = @iteratorId -- delete row so we don't loop over it again 
END
DROP TABLE #Temp

【问题讨论】:

  • dbo.procContactSavedbo.procClientContactSave 是做什么的 - 他们是否使用了一些 CLR 功能?
  • 只是存储过程..主要执行 INSERT 命令
  • 这些存储过程都在 SQL 窗口中输出 1 个结果集。您认为这会导致 SSMS 内存不足吗? SQL-Server-2008 内存不足似乎很奇怪。我认为它可以在一个脚本中处理 11,000 条记录。
  • An OutOfMemoryException 无法在普通的 .NET 应用程序中被捕获和处理,因此 SMSS 会完全崩溃,据我了解,情况并非如此。因此,我不怀疑 SMSS 会崩溃,而是某些 CLR 汇编代码正在您的 SP 中的某处执行,这使用了比 SQL Server 允许的 CLR 代码更多的内存。
  • 它首先显示了该错误,但并没有立即使 SSMS 崩溃。只有当我在几分钟后尝试运行另一个查询时,它才会崩溃。我愿意赌它显示的数据量。结果中的窗口滚动条是微型的。

标签: sql sql-server-2008 exception memory


【解决方案1】:

在我的 cmets 中提到的 2 个存储过程中,我调用了标准的 Web 应用程序存储过程,它插入了一条记录,但还在脚本中的每次迭代的结果集中返回了该记录(只有 1 条记录)。当我在这两个存储过程中评论 SELECT 语句时,脚本运行了 1.5 分钟,所以我想它是因为 SSMS 从这些结果集中显示的数据量而崩溃。这防止了内存崩溃,更不用说减少运行时间(从 20+ 分钟到 1.5 分钟)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-28
    • 2020-08-09
    • 2018-09-28
    相关资源
    最近更新 更多