【问题标题】:There is insufficient system memory in resource pool 'internal'资源池“内部”中的系统内存不足
【发布时间】:2009-10-08 13:30:17
【问题描述】:

SQL Server 2008 Linked Server 和 ad-hoc INSERT 会导致快速内存泄漏,最终导致服务器无响应并以以下错误结束:

Msg 701, Level 17, State 123, Server BRECK-PC\SQLEXPRESS, Line 2
There is insufficient system memory in resource pool 'internal' to run this 
query.

Location:        qxcntxt.cpp:1052
Expression:      cref == 0
SPID:            51
Process ID:      1880

在重新启动 SQL Server 之前,服务器保持无响应。

正在使用的软件:

  • Windows Vista Ultimate 64 位内部版本 6001 SP1

  • Microsoft SQL Server 2008 (SP1) - 10.0.2734.0 (X64) 2009 年 9 月 11 日 14:30:58 版权所有 (c) 1988-2008 Microsoft Corporation Express Edition,在 Windows NT 上具有高级服务(64 位) 6.0(内部版本 6001:Service Pack 1)

  • 来自 SQL Anywhere 11.0.1.2276 的 SAOLEDB.11 驱动程序

将最大服务器内存 (MB) 设置为 2048 没有帮助。

向服务器启动参数添加各种 -g 值(例如 -g256;)没有帮助。

使用 DBCC FREESYSTEMCACHE ('ALL')、DBCC FREESESSIONCACHE 和 DBCC FREEPROCCACHE 没有帮助。

将累积更新包 4 安装到 SQL Server 2008 Service Pack 1 并没有帮助,尽管它包含对涉及链接服务器使用的内存泄漏症状的修复。

将 SELECT ... ROW_NUMBER() OVER ... 查询与 INSERT 分开没有帮助。实验表明,复杂的 SELECT 不会导致内存泄漏,而 INSERT 会。

更改代码以使用临时“INSERT INTO OPENROWSET”语法而不是链接服务器没有帮助;下面的代码显示了链接服务器的使用情况。

sysinternals.com Process Explore 实用程序显示内存使用与 sqlserver.exe 相关,而不是与 SQL Anywhere OLEDB 驱动程序 SAOLEDB.11 使用的 DLL 相关。

请注意,SQL Anywhere 版本的链接服务器(代理表)工作正常,可以在单个事务中将 190 万行从 SQL Server 2008 表“拉”到 SQL Anywhere 11 数据库。此处显示的逻辑是尝试使用链接服务器功能“推送”行;相同的方向,不同的语法。

代码如下; EXECUTE copy_mss_t2 执行三四次后,4G RAM 耗尽:

EXEC sys.sp_configure 
   N'show advanced options',  
   N'1'
GO

RECONFIGURE WITH OVERRIDE
GO

EXEC sys.sp_configure
   N'max server memory (MB)',
   N'2048'
GO

RECONFIGURE WITH OVERRIDE
GO

EXEC sys.sp_configure
   N'show advanced options',
   N'0'
GO

RECONFIGURE WITH OVERRIDE
GO
EXEC master.dbo.sp_MSset_oledb_prop
   N'SAOLEDB.11',
   N'AllowInProcess',
   1
GO

sp_addlinkedserver
   @server = 'mem',
   @srvproduct = 'SQL Anywhere OLE DB Provider',
   @provider = 'SAOLEDB.11',
   @datasrc = 'mem_PAVILION2'
GO

EXEC master.dbo.sp_serveroption
   @server=N'mem',
   @optname=N'rpc',
   @optvalue=N'true'
GO

EXEC master.dbo.sp_serveroption
   @server=N'mem',
   @optname=N'rpc out',
   @optvalue=N'true'
GO

sp_addlinkedsrvlogin
   @rmtsrvname = 'mem',
   @useself = 'false',
   @locallogin = NULL,
   @rmtuser = 'dba',
   @rmtpassword = 'sql'
GO

CREATE PROCEDURE copy_mss_t2
   @from_row            BIGINT,
   @to_row              BIGINT,
   @rows_copied_count   BIGINT OUTPUT
AS

   SELECT *
     INTO #t
     FROM ( SELECT *,
                   ROW_NUMBER()
                      OVER ( ORDER BY sample_set_number,
                                      connection_number )
                   AS t2_row_number
             FROM mss_t2 ) AS ordered_mss_t2
    WHERE ordered_mss_t2.t2_row_number BETWEEN @from_row AND @to_row;

   SELECT @rows_copied_count = COUNT(*)
     FROM #t;

INSERT INTO mem..dba.sa_t2
SELECT sampling_id,
       sample_set_number,
       connection_number,
       blocker_owner_table_name,
       blocker_lock_type,
       blocker_owner_name,
       blocker_table_name,
       blocker_reason,
       blocker_row_identifier,
       current_engine_version,
       page_size,
       ApproximateCPUTime,
       BlockedOn,
       BytesReceived,
       BytesSent,
       CacheHits,
       CacheRead,
   "Commit",
   DiskRead,
   DiskWrite,
   FullCompare,
   IndAdd,
   IndLookup,
   Isolation_level,
   LastReqTime,
   LastStatement,
   LockCount,
   LockName,
   LockTableOID,
   LoginTime,
   LogWrite,
   Name,
   NodeAddress,
   Prepares,
   PrepStmt,
   QueryLowMemoryStrategy,
   QueryOptimized,
   QueryReused,
   ReqCountActive,
   ReqCountBlockContention,
   ReqCountBlockIO,
   ReqCountBlockLock,
   ReqCountUnscheduled,
   ReqStatus,
   ReqTimeActive,
   ReqTimeBlockContention,
   ReqTimeBlockIO,
   ReqTimeBlockLock,
   ReqTimeUnscheduled,
   ReqType,
   RequestsReceived,
   Rlbk,
   RollbackLogPages,
   TempFilePages,
   TransactionStartTime,
   UncommitOp,
   Userid,
   previous_ApproximateCPUTime,
   interval_ApproximateCPUTime,
   previous_Commit,
   interval_Commit,
   previous_Rlbk,
   interval_Rlbk
  FROM #t;

GO

DECLARE @rows_copied_count BIGINT
EXECUTE copy_mss_t2 1110001, 1120000, @rows_copied_count OUTPUT
SELECT @rows_copied_count
GO

EXECUTE create_linked_server
GO

DECLARE @rows_copied_count BIGINT
EXECUTE copy_mss_t2 1120001, 1130000, @rows_copied_count OUTPUT
SELECT @rows_copied_count
GO

EXECUTE create_linked_server
GO

这是 SQL Server 源表,包含大约 1G 的数据,190 万行:

CREATE TABLE mss_t2 (
   sampling_id                       BIGINT NOT NULL,
   sample_set_number                 BIGINT NOT NULL,
   connection_number                 BIGINT NOT NULL,
   blocker_owner_table_name          VARCHAR ( 257 ) NULL,
   blocker_lock_type                 VARCHAR ( 32 ) NULL,
   blocker_owner_name                VARCHAR ( 128 ) NULL,
   blocker_table_name                VARCHAR ( 128 ) NULL,
   blocker_reason                    TEXT NULL,
   blocker_row_identifier            VARCHAR ( 32 ) NULL,
   current_engine_version            TEXT NOT NULL,
   page_size                         INTEGER NOT NULL,
   ApproximateCPUTime                DECIMAL ( 30, 6 ) NULL,
   BlockedOn                         BIGINT NULL,
   BytesReceived                     BIGINT NULL,
   BytesSent                         BIGINT NULL,
   CacheHits                         BIGINT NULL,
   CacheRead                         BIGINT NULL,
   "Commit"                          BIGINT NULL,
   DiskRead                          BIGINT NULL,
   DiskWrite                         BIGINT NULL,
   FullCompare                       BIGINT NULL,
   IndAdd                            BIGINT NULL,
   IndLookup                         BIGINT NULL,
   Isolation_level                   BIGINT NULL,
   LastReqTime                       TEXT NOT NULL DEFAULT '1900-01-01',
   LastStatement                     TEXT NULL,
   LockCount                         BIGINT NULL,
   LockName                          BIGINT NULL,
   LockTableOID                      BIGINT NULL,
   LoginTime                         TEXT NOT NULL DEFAULT '1900-01-01',
   LogWrite                          BIGINT NULL,
   Name                              VARCHAR ( 128 ) NULL,
   NodeAddress                       TEXT NULL,
   Prepares                          BIGINT NULL,
   PrepStmt                          BIGINT NULL,
   QueryLowMemoryStrategy            BIGINT NULL,
   QueryOptimized                    BIGINT NULL,
   QueryReused                       BIGINT NULL,
   ReqCountActive                    BIGINT NULL,
   ReqCountBlockContention           BIGINT NULL,
   ReqCountBlockIO                   BIGINT NULL,
   ReqCountBlockLock                 BIGINT NULL,
   ReqCountUnscheduled               BIGINT NULL,
   ReqStatus                         TEXT NULL,
   ReqTimeActive                     DECIMAL ( 30, 6 ) NULL,
   ReqTimeBlockContention            DECIMAL ( 30, 6 ) NULL,
   ReqTimeBlockIO                    DECIMAL ( 30, 6 ) NULL,
   ReqTimeBlockLock                  DECIMAL ( 30, 6 ) NULL,
   ReqTimeUnscheduled                DECIMAL ( 30, 6 ) NULL,
   ReqType                           TEXT NULL,
   RequestsReceived                  BIGINT NULL,
   Rlbk                              BIGINT NULL,
   RollbackLogPages                  BIGINT NULL,
   TempFilePages                     BIGINT NULL,
   TransactionStartTime              TEXT NOT NULL DEFAULT '1900-01-01',
   UncommitOp                        BIGINT NULL,
   Userid                            VARCHAR ( 128 ) NULL,
   previous_ApproximateCPUTime       DECIMAL ( 30, 6 ) NOT NULL DEFAULT 0.0,
   interval_ApproximateCPUTime       AS ( COALESCE ( "ApproximateCPUTime", 0 ) - previous_ApproximateCPUTime ),
   previous_Commit                   BIGINT NOT NULL DEFAULT 0,
   interval_Commit                   AS  ( COALESCE ( "Commit", 0 ) - previous_Commit ),
   previous_Rlbk                     BIGINT NOT NULL DEFAULT 0,
   interval_Rlbk                     AS  ( COALESCE ( Rlbk, 0 ) - previous_Rlbk ) )

这是 SQL Anywhere 11 中的目标表:

CREATE TABLE sa_t2 (
   sampling_id                       BIGINT NOT NULL,
   sample_set_number                 BIGINT NOT NULL,
   connection_number                 BIGINT NOT NULL,
   blocker_owner_table_name          VARCHAR ( 257 ) NULL,
   blocker_lock_type                 VARCHAR ( 32 ) NULL,
   blocker_owner_name                VARCHAR ( 128 ) NULL,
   blocker_table_name                VARCHAR ( 128 ) NULL,
   blocker_reason                    TEXT NULL,
   blocker_row_identifier            VARCHAR ( 32 ) NULL,
   current_engine_version            TEXT NOT NULL,
   page_size                         INTEGER NOT NULL,
   ApproximateCPUTime                DECIMAL ( 30, 6 ) NULL,
   BlockedOn                         BIGINT NULL,
   BytesReceived                     BIGINT NULL,
   BytesSent                         BIGINT NULL,
   CacheHits                         BIGINT NULL,
   CacheRead                         BIGINT NULL,
   "Commit"                          BIGINT NULL,
   DiskRead                          BIGINT NULL,
   DiskWrite                         BIGINT NULL,
   FullCompare                       BIGINT NULL,
   IndAdd                            BIGINT NULL,
   IndLookup                         BIGINT NULL,
   Isolation_level                   BIGINT NULL,
   LastReqTime                       TEXT NOT NULL DEFAULT '1900-01-01',
   LastStatement                     TEXT NULL,
   LockCount                         BIGINT NULL,
   LockName                          BIGINT NULL,
   LockTableOID                      BIGINT NULL,
   LoginTime                         TEXT NOT NULL DEFAULT '1900-01-01',
   LogWrite                          BIGINT NULL,
   Name                              VARCHAR ( 128 ) NULL,
   NodeAddress                       TEXT NULL,
   Prepares                          BIGINT NULL,
   PrepStmt                          BIGINT NULL,
   QueryLowMemoryStrategy            BIGINT NULL,
   QueryOptimized                    BIGINT NULL,
   QueryReused                       BIGINT NULL,
   ReqCountActive                    BIGINT NULL,
   ReqCountBlockContention           BIGINT NULL,
   ReqCountBlockIO                   BIGINT NULL,
   ReqCountBlockLock                 BIGINT NULL,
   ReqCountUnscheduled               BIGINT NULL,
   ReqStatus                         TEXT NULL,
   ReqTimeActive                     DECIMAL ( 30, 6 ) NULL,
   ReqTimeBlockContention            DECIMAL ( 30, 6 ) NULL,
   ReqTimeBlockIO                    DECIMAL ( 30, 6 ) NULL,
   ReqTimeBlockLock                  DECIMAL ( 30, 6 ) NULL,
   ReqTimeUnscheduled                DECIMAL ( 30, 6 ) NULL,
   ReqType                           TEXT NULL,
   RequestsReceived                  BIGINT NULL,
   Rlbk                              BIGINT NULL,
   RollbackLogPages                  BIGINT NULL,
   TempFilePages                     BIGINT NULL,
   TransactionStartTime              TEXT NOT NULL DEFAULT '1900-01-01',
   UncommitOp                        BIGINT NULL,
   Userid                            VARCHAR ( 128 ) NULL,
   previous_ApproximateCPUTime       DECIMAL ( 30, 6 ) NOT NULL DEFAULT 0.0,
   interval_ApproximateCPUTime       DECIMAL ( 30, 6 ) NOT NULL COMPUTE ( COALESCE ( "ApproximateCPUTime", 0 ) - previous_ApproximateCPUTime ),
   previous_Commit                   BIGINT NOT NULL DEFAULT 0,
   interval_Commit                   BIGINT NOT NULL COMPUTE ( COALESCE ( "Commit", 0 ) - previous_Commit ),
   previous_Rlbk                     BIGINT NOT NULL DEFAULT 0,
   interval_Rlbk                     BIGINT NOT NULL COMPUTE ( COALESCE ( Rlbk, 0 ) - previous_Rlbk ),
   PRIMARY KEY ( sample_set_number, connection_number ) );

【问题讨论】:

  • 我已经为源表和目标表添加了 CREATE TABLE 语句。进一步的实验表明,数据类型的多样性可能是导致内存泄漏的原因;例如,多个 TEXT 列、30 位 DECIMAL、计算 AS 列等。我很抱歉从原始问题陈述中省略了 DDL……有点不公平。
  • 初步迹象表明,源表中有多个 TEXT 列会导致 SQL Server 内存泄漏。将除一个 TEXT 列之外的所有列更改为 VARCHAR 似乎可以解决问题。一个完整的测试是多达 250,000 行,而 RAM 增加为零;我会等它完成,然后拼凑出一个小的可复现。

标签: sql-server-2008 memory-leaks oledb linked-server


【解决方案1】:

您不需要在每次迭代后清空临时表#t 吗?即在程序结束时添加TRUNCATE TABLE #t?我认为临时表#t 存在直到您的会话结束,而不是直到存储过程结束。 SELECT INTO 只是附加到现有的#t,但不会替换它。

另一件事是使用永久表,而不是存储在 tempdb #tables 中的东西。

【讨论】:

  • 一个很好的观察! FWIW 所有 190 万行所需的总空间约为 1G,而内存泄漏在仅处理了几千行之后就用掉了几 G 的 RAM ......所以我不希望它与临时表有任何关系(这是在第一次发现内存泄漏之后添加的)。但是,就像我之前所说的,在这一点上,欢迎任何和所有建议。
  • 在所有答案中,包括被删除的答案,我最喜欢你的,所以我给你奖金。
  • 当然,这不是实际的答案(见下面我的答案),但是提供奖金,让每个人都对我的问题感兴趣,然后猛拉,这有点愚蠢奖金走了!
  • 如果有人想支持这个问题,那将不胜感激......这是 SQL Server 2008 中的一个真正的错误,需要硬重启。我认为投反对票很幼稚,但这就是我:)
  • 解决方法工作得很好。我正在写一篇关于将数据加载到内存数据库中的不同方法的文章,我可以顺便提一下,一种技术不适用于长字符串。或者三种技术:Linked Server、OPENROWSET 和 SSIS……我正在测试后两种来确认。其他三种技术也可以正常工作:带有 LOAD TABLE、MobiLink 和 SQL Anywhere 代理表的 BCP。
【解决方案2】:

问题是通过 SQL Anywhere 11.0.1 提供程序 SAOLEDB.11 使用链接服务器将数据插入到声明为大于 VARCHAR ( 8000 ) 的目标列中。这是一个简化的重现:

-- Overview: SQL Server 2008 suffers from a fatal memory leak
--    if an attempt is made to use a linked server and the 
--    SAOLEDB.11 provicer to copy data from SQL Server
--    to a SQL Anywhere 11.0.1 table that contains a single column
--    larger than VARCHAR ( 8000 ); i.e, a VARCHAR ( 8000 ) target
--    column is OK but VARCHAR ( 8001 ) is not. The actual string 
--    length is not an issue, nor is the fact that the SQL Server
--    column is declared as TEXT. The memory leak is faster if
--    there is more than one target column larger than VARCHAR ( 8000 ).
--    The server computer freezes and must be rebooted.
-- Msg 701, Level 17, State 123, Server BRECK-PC\SQLEXPRESS, Line 2
-- There is insufficient system memory in resource pool 'internal' to run this
-- query.
-- Location:        qxcntxt.cpp:1052
-- Expression:      cref == 0
-- SPID:            52
-- Process ID:      2044

---------------------------------------------------------
-- SQL ANYWHERE 11 on target computer
---------------------------------------------------------

-- Target:
-- HP Pavilion laptop, 4GHz Pentium 4, 2G RAM
-- Windows XP SP2
-- SQL Anywhere 11.0.1.2276

---------------------------------------------------------
-- Windows commands used to create and start in-memory database

/*
"%SQLANY11%\bin32\dbinit.exe"^
  mem.db

"%SQLANY11%\bin32\dbspawn.exe" -f^
  "%SQLANY11%\bin32\dbsrv11.exe"^
  -im nw^
  -o dbsrv11_log.txt^
  mem.db 

"%SQLANY11%\bin32\dbisql.com"^
  -c "ENG=mem;DBN=mem;UID=dba;PWD=sql;CON=mem-1"
*/

---------------------------------------------------------
-- Create target table with one single "long" column.

BEGIN
   DROP TABLE sa_target;
   EXCEPTION WHEN OTHERS THEN
END;

CREATE TABLE sa_target (
   primary_key      INTEGER NOT NULL PRIMARY KEY,
   string_column_1  VARCHAR ( 8001 ) NOT NULL );

---------------------------------------------------------
--- SQL SERVER 2008 on source (server) computer
---------------------------------------------------------

-- Server:
-- Desktop with Intel Core 2 Quad Q9450 2.66Ghz 4G RAM
-- Windows Vista Ultimate 64 bit build 6001 SP1
-- SQL Server 2008 Express 64 Service Pack 1 with cumulative update package 4:
--    Microsoft SQL Server 2008 (SP1) - 10.0.2734.0 (X64)   Sep 11 2009 14:30:58   
--    Copyright (c) 1988-2008 Microsoft Corporation  Express Edition with    
--    Advanced Services (64-bit) on Windows NT 6.0 <X64>    
--    (Build 6001: Service Pack 1) 
-- SAOLEDB.11 driver from SQL Anywhere 11.0.1.2276

---------------------------------------------------------
-- Windows command used to start osql.exe

/*
"c:\Program Files\Microsoft SQL Server\100\Tools\Binn\osql.exe"^
  -d main^
  -I^
  -l 10^
  -P j68Fje9#fyu489^
  -S BRECK-PC\SQLEXPRESS^
  -U sa
*/

---------------------------------------------------------
-- Create database.

USE master
GO

BEGIN TRY
   DROP DATABASE main;
END TRY
BEGIN CATCH
END CATCH;
GO

CREATE DATABASE main
ON PRIMARY
( NAME = main_dat,
   FILENAME = 'E:\data\main\main.mdf',
   SIZE = 2GB,
   FILEGROWTH = 200MB )
LOG ON
( NAME = 'main_log',
   FILENAME = 'E:\data\main\main.ldf',
   SIZE = 2GB,
   FILEGROWTH = 200MB )
GO

----------------------------------------------------------------------------
-- Configure SAOLEDB.11 provider.

USE master
go 

-- SAOLEDB.11 provider dlls registered via these Windows commands:
--    regsvr32 dboledb11.dll
--    regsvr32 dboledba11.dll

EXEC master.dbo.sp_MSset_oledb_prop N'SAOLEDB.11', N'AllowInProcess', 1
GO

-- If the following statement produces this message, it probably means 
-- that 'DisallowAdHocAccess' is already set to zero for SAOLEDB.11:
--
-- RegDeleteValue() returned error 2, 'The system cannot find the file specified.'

EXEC master.dbo.sp_MSset_oledb_prop N'SAOLEDB.11', N'DisallowAdHocAccess', 0
GO

----------------------------------------------------------------------------
-- THIS SECTION WAS NOT RUN.
-- Set up for OPENROWSET usage.
-- NOT REQUIRED for required for Linked Server usage.

USE master
GO

sp_configure 'show advanced options', 1
GO

RECONFIGURE
GO

sp_configure 'Ad Hoc Distributed Queries', 1
GO

RECONFIGURE
GO

----------------------------------------------------------------------------
-- Set up Linked Server usage.

USE main
GO

BEGIN TRY
   EXEC sp_droplinkedsrvlogin 
      @rmtsrvname = 'mem',
      @locallogin = NULL  
END TRY
BEGIN CATCH
END CATCH 
GO

BEGIN TRY
   EXEC sp_dropserver
      @server = 'mem'
END TRY
BEGIN CATCH
END CATCH 
GO

EXEC sp_addlinkedserver
   @server = 'mem',
   @srvproduct = 'SQL Anywhere OLE DB Provider',
   @provider = 'SAOLEDB.11',
   @datasrc = 'mem_PAVILION2' 
GO

EXEC master.dbo.sp_serveroption 
   @server=N'mem', 
   @optname=N'rpc', 
   @optvalue=N'true' 
GO

EXEC master.dbo.sp_serveroption 
   @server=N'mem', 
   @optname=N'rpc out', 
   @optvalue=N'true' 
GO

EXEC sp_addlinkedsrvlogin 
   @rmtsrvname = 'mem', 
   @useself = 'false', 
   @locallogin = NULL, 
   @rmtuser = 'dba', 
   @rmtpassword = 'sql' 
GO

----------------------------------------------------------------------------
-- Create and fill source table with 1 million rows.

USE main
GO

BEGIN TRY
   DROP TABLE mss_source; 
END TRY
BEGIN CATCH
END CATCH 
GO

CREATE TABLE mss_source ( 
   primary_key      INTEGER NOT NULL PRIMARY KEY,
   string_column_1  TEXT NOT NULL )
GO

BEGIN
   DECLARE @primary_key INTEGER 
   SELECT @primary_key = 1
   BEGIN TRANSACTION
   WHILE @primary_key <= 1000000 
   BEGIN
      INSERT mss_source VALUES (
         @primary_key,
         REPLICATE ( 'Some test data. ', 2 ) )
      SELECT @primary_key = @primary_key + 1
   END
   COMMIT
END
GO

SELECT COUNT(*) FROM mss_source
GO

-- 1000000

---------------------------------------------------------
-- Copy data to target table.

SELECT CURRENT_TIMESTAMP
GO

INSERT INTO mem..dba.sa_target 
SELECT * 
  FROM mss_source
GO

SELECT CURRENT_TIMESTAMP
GO

---------------------------------------------------------
-- Test 1 - Code as shown above.
-- FAILED
-- 
-- Started at 2009-10-12 10:06:33.393
-- 
-- A slow server memory leak began immediately.
-- The initial target insert rate was about 2000 rows per second.
-- Server RAM usage reached 3.82 GB, Physical Memory: 95%, Page File 16236M / 16288M
-- The server display became frozen.
-- The server became unresponsive to mouse input.
-- The target insert rate dropped below 1000 rows per second, but inserts continued.
-- The copy process reached 937,817 rows inserted on the target.
-- This dialog box appeared on the server: "Your computer is low on memory"
-- Eventually, the process failed, and this message appeared in the osql.exe window:
-- 
-- Msg 701, Level 17, State 123, Server BRECK-PC\SQLEXPRESS, Line 2
-- There is insufficient system memory in resource pool 'internal' to run this
-- query.
-- Location:        qxcntxt.cpp:1052
-- Expression:      cref == 0
-- SPID:            52
-- Process ID:      2044
-- 
-- Failed at 2009-10-12 10:22:21.817
-- The server disk I/O light remained lit without interruption.
-- The server required a hard reboot.

---------------------------------------------------------
-- Test 2 - Code as shown above, except for VARCHAR ( 8000 ).
-- SUCCESSFUL 

BEGIN
   DROP TABLE sa_target;
   EXCEPTION WHEN OTHERS THEN
END;

CREATE TABLE sa_target (
   primary_key      INTEGER NOT NULL PRIMARY KEY,
   string_column_1  VARCHAR ( 8000 ) NOT NULL );

-- Started at 2009-10-12 10:41:46.427
-- There was some slight initial growth in RAM usage on the server.
-- Server RAM usage stabilized at 1.40 GB, Physical Memory: 35%, Page File 1560M / 8352M
-- The target insert rate remained about 2000 rows per second throughout.
-- Finished OK at 2009-10-12 10:50:52.240

---------------------------------------------------------
-- Test 3 - Repeat Test 2
-- SUCCESSFUL 

-- Started at 2009-10-12 10:53:38.350
-- No further RAM usage growth on the server.
-- Finished OK at 2009-10-12 11:02:10.457

【讨论】:

    【解决方案3】:

    您可以尝试分批运行插入,而不是一次运行整个数据集。

    【讨论】:

    • "您可以尝试分批运行插入,而不是一次运行整个数据集。" - 这正是代码正在做的事情,一次只复制 10,000 行的批次:EXECUTE copy_mss_t2 1110001, 1120000, ... - 这正是使用复杂 SELECT 来收集小批量的原因。我考虑过编写单行 FETCH 和 INSERT 循环,但 Kludge Faktor 相当极端……关系数据库应该处理集合。
    • 尝试小批量,而不是一直到一个。继续降低批量大小,直到它起作用。或者尝试通过 SSIS 包而不是链接服务器移动记录。
    • 实验表明内存泄漏与batch size无关;特别是,内存泄漏比正在传输的数据量大几个数量级。此外,此代码的全部目的是使用链接服务器功能,以撰写有关该主题的文章。感谢有关 SSIS 的建议,我会试一试(但遗憾的是,“在 SQL Server Express 中,保存向导创建的包的选项不可用。”)
    • @HLGEM:我不会打扰:如果他们没有解决问题,即使他们没有错,答案也会被标记
    • SSIS 在少于 3000 行之后失败得更快。谷歌搜索表明 0x8007000E 可能意味着内存耗尽,并且任务管理器支持这一点(从 1G 到 4G RAM 在几秒钟内使用)。我怀疑 SSIS 使用与链接服务器相同的逻辑。错误 0xc0202009:数据流任务 1:SSIS 错误代码 DTS_E_OLEDBERROR。发生 OLE DB 错误。错误代码:0x8007000E。
    【解决方案4】:

    您可以尝试使用变量表来代替临时表吗?

    例如。

    DECLARE @ResultTable TABLE (TableId INT PRIMARY KEY, ... etc)
    
    INSERT INTO @ResultTable
    SELECT TableId, ....
    FROM mss_t2 
    
    ... etc. ...
    

    【讨论】:

    • 临时表是在内存泄漏首次浮出水面后引入的......它是作为一种解决方法尝试添加的。实验表明,直到临时表被填满,即开始插入到链接服务器表时,才会发生泄漏。但是,在这一点上,任何事情都值得尝试!谢谢!
    【解决方案5】:

    我遇到了类似的问题,我的代码在循环中包含了一个简单的#temp 表的使用,这导致了这个问题,我用一个永久表替换了。

    似乎工作正常。

    谢谢 纳文

    【讨论】:

      猜你喜欢
      • 2016-12-31
      • 1970-01-01
      • 1970-01-01
      • 2022-01-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多