2009-10-08 14 views
13
Server 2008 server collegato

SQL e ad-hoc INSERT causano una perdita di memoria rapida che alla fine fa sì che il server a non rispondere e si conclude con il seguente errore:V'è memoria di sistema insufficiente nel pool di risorse 'interna'

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 

Il server rimane non reattivo fino al riavvio di SQL Server.

software in uso:

  • Windows Vista Ultimate a 64 bit di build 6001 SP1

  • Microsoft SQL Server 2008 (SP1) - 10.0.2734.0 (X64) 11 Set 2009 14:30:58 Copyright (c) 1988-2008 Microsoft Corporation Express Edition with Advanced Services (64-bit) in Windows NT 6.0 (Build 6001: service pack 1)

  • SAOLEDB.11 pilota di SQL Anywhere 11.0.1.2276

L'impostazione della memoria massima del server (MB) su 2048 non ha aiutato.

Aggiunta di vari valori -g (ad es. -g256;) al server I parametri di avvio non sono d'aiuto.

L'utilizzo di DBCC FREESYSTEMCACHE ('ALL'), DBCC FREESESSIONCACHE e DBCC FREEPROCCACHE non ha aiutato.

L'installazione del pacchetto di aggiornamento di Cumnulative 4 a SQL Server 2008 Service Pack 1 non ha aiutato, anche se conteneva una correzione a un problema di perdita di memoria che coinvolge l'utilizzo del server collegato.

Separare la query SELECT ... ROW_NUMBER() OVER ... dall'INSERT non ha aiutato. La sperimentazione ha dimostrato che il complesso SELECT non ha causato la perdita di memoria, ha fatto l'INSERT.

La modifica del codice per utilizzare la sintassi "INSERT INTO OPENROWSET" ad-hoc anziché un server collegato non è stata di aiuto; il codice seguente mostra l'utilizzo del server collegato.

L'utilità Process Process di sysinternals.com mostra che l'utilizzo della memoria è stato associato a sqlserver.exe, non alle DLL utilizzate dal driver OLEDB di SQL Anywhere SAOLEDB.11.

Si noti che la versione SQL Anywhere del server collegato (tabelle proxy) funziona correttamente, per "estrarre" 1,9 milioni di righe da una tabella SQL Server 2008 in un database SQL Anywhere 11 in un'unica transazione. La logica mostrata qui è un tentativo di utilizzare la funzionalità del server collegato per "spingere" le righe; stessa direzione, diversa sintassi.

Il codice segue; 4G di RAM è esaurita dopo tre o quattro esecuzioni del copy_mss_t2 eseguire:

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 

Ecco la tabella di origine di SQL Server, contenente circa 1G di dati in 1,9 milioni di righe:

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)) 

Ecco il tabella di destinazione in 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)); 
+0

ho aggiunto le istruzioni CREATE TABLE per le tabelle di origine e di destinazione. Ulteriori sperimentazioni indicano che la varietà dei tipi di dati potrebbe essere la causa della perdita di memoria; ad esempio, più colonne TEXT, DECIMAL a 30 cifre, colonne AS calcolate e così via. Le mie PROFOUND APOLOGIES per aver escluso il DDL dall'affermazione originale del problema ... sono ingiuste. –

+0

Le indicazioni preliminari indicano che la presenza di più colonne TEXT nella tabella di origine causa la perdita di memoria di SQL Server. Cambiare tutte le colonne tranne una TEXT in VARCHAR sembra fare il trucco. Un test completo è fino a 250.000 righe con zero aumento della RAM; Aspetterò che finisca, quindi mettere insieme un piccolo riproducibile. –

risposta

7

Non è necessario svuotare il tavolo temporaneo #t dopo ogni iterazione? Aggiungere un TRUNCATE TABLE #t alla fine della procedura? Penso che la tabella temporanea #t esista fino alla fine della sessione, non fino alla fine della stored procedure. SELECT INTO si accoda solo allo #t esistente, ma non lo sostituisce.

Un'altra cosa sarebbe utilizzare una tabella permanente non memorizzata in tempdb #tables.

+0

Un'ottima osservazione! FWIW lo spazio totale richiesto per tutte le 1,9 milioni di righe è di circa 1G, mentre la perdita di memoria consuma diversi G di RAM dopo che sono state elaborate solo poche migliaia di righe ... quindi non sono fiducioso che abbia qualcosa a che fare con la tabella temporanea (che è stato aggiunto * dopo * la perdita di memoria è stata notata per la prima volta). Tuttavia, come ho detto prima, a questo punto tutti i suggerimenti sono ben accetti. –

+0

Tra tutte le risposte, inclusa quella che è stata cancellata, mi piace di più la tua, quindi ti sto dando il bonus. –

+0

Ovviamente, non è la * reale * risposta (vedi la mia risposta sotto), ma è un po 'sciocco offrire un bonus, convincere tutti gli interessati al mio problema, e poi tirare via il bonus! –

0

Si potrebbe provare a eseguire l'inserto in batch invece dell'intero set di dati in una sola volta.

+0

"Si potrebbe provare a eseguire l'inserto in batch invece dell'intero set di dati contemporaneamente." - questo è esattamente ciò che sta facendo il codice, copiando lotti di sole 10.000 righe alla volta: EXECUTE copy_mss_t2 1110001, 1120000, ... - questo è esattamente il motivo per cui è stato utilizzato il complesso SELECT, per raccogliere piccoli gruppi. Ho preso in considerazione la scrittura di un ciclo FETCH e INSERT a riga singola, ma il Kludge Faktor è piuttosto estremo ... i database relazionali dovrebbero gestire i set. –

+0

Prova un batch più piccolo, non fino a uno solo. Continua a ridurre le dimensioni del batch finché non funziona. In alternativa, provare a spostare i record tramite un pacchetto SSIS anziché un server collegato. – HLGEM

+0

Gli esperimenti mostrano che la perdita di memoria non è correlata alla dimensione del batch; in particolare, la perdita di memoria è di ordini di grandezza superiore alla quantità di dati trasferiti. Inoltre, l'intero scopo di questo codice è di utilizzare la funzionalità del server collegato, ai fini di un articolo sull'argomento. Grazie per il suggerimento su SSIS, lo farò (ma, purtroppo, "In SQL Server Express, l'opzione per salvare il pacchetto che la procedura guidata crea non è disponibile.") –

0

Invece di utilizzare le tabelle temporanee, puoi provare a utilizzare le tabelle Variabile?

es.

DECLARE @ResultTable TABLE (TableId INT PRIMARY KEY, ... etc) 

INSERT INTO @ResultTable 
SELECT TableId, .... 
FROM mss_t2 

... etc. ... 
+0

La tabella temporanea è stata introdotta dopo che la perdita di memoria è emersa per la prima volta ... è stata aggiunta come soluzione alternativa. La sperimentazione mostra che la perdita non si verifica fino a quando non viene riempita la tabella temporanea, quando inizia l'INSERT alla tabella del server collegato. TUTTO QUANTO vale la pena provare, a questo punto! Grazie! –

2

Il problema sta usando un server collegato tramite SQL Anywhere 11.0.1 fornitore SAOLEDB.11 per inserire dati in una colonna di destinazione dichiarata come grande di VARCHAR (8000). Qui è un semplificata riproducibile:

-- 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 
0

ho avuto un problema simile, il mio codice contiene l'utilizzo di una semplice tabella #temp in un ciclo, che ha causato questo e ho sostituito con un tavolo permanente.

Sembra funzionare.

Grazie Naveen

Problemi correlati