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));
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. –
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. –