sql server management studio 2008 内存不足,导致 .net 运行时失败

exp*_*ix' 3 sql-server ssms timestamp

问题 sql server management studio 2008 占用内存,导致 .net 运行时错误。它崩溃并在错误对话框中显示一条空消息,但可以找到一个小的事件日志条目,内容如下:

<EventData>
  <Data>.NET Runtime version 2.0.50727.5446 - Fatal error in the execution engine (7269AECA) (0).</Data> 
</EventData>
Run Code Online (Sandbox Code Playgroud)

原始事件日志条目(德语):

<EventData>
  <Data>.NET Runtime version 2.0.50727.5446 - Schwerwiegender Fehler im Ausführungsmodul (7269AECA) (0).</Data> 
</EventData>
Run Code Online (Sandbox Code Playgroud)

重现错误

在针对 SQL Server 2005 的远程实例在循环中执行大约每 1000 万次 Insert-Statement Management Studio 2008 后,我的开发工作站上的 4GB 内存已启动,这导致上述错误。为什么我在循环中执行插入语句?- 由于 SQL Server 不允许手动设置数据库的实际 TIMESTAMP,因此需要使用 dummy-data-manipulation-statements 来帮助解决(TIMESTAMP-manipulation-lock 不是坏主意,但有时在开发环境中需要)。

CREATE TABLE __DUMMY (I INT, TS TIMESTAMP)
DECLARE @FROM INT
DECLARE @TO INT
SET @FROM = 666
SET @TO = 666666666
WHILE (@FROM < @TO)
BEGIN
    INSERT INTO __DUMMY (I) VALUES(@FROM)
    SET @FROM = @FROM +1
END
Run Code Online (Sandbox Code Playgroud)

在与 SQL Server 的另一个会话中,我不时截断 __DUMMY 表:

SELECT @@DBTS, CONVERT(INT, @@DBTS), 'SERVER'
UNION
SELECT CONVERT(TIMESTAMP, 666666666), 666666666, 'CLIENT'

EXEC sp_spaceused '__DUMMY'
TRUNCATE TABLE __DUMMY

--writes    ~10.000 Tuple/Second
--allocates ~100.000 Byte/10.000 Tuple
--      ==> ~10 Byte/Tuple (are "roughly" made up of: INT = 4 BYTE, TIMESTAMP = 8 BYTE)
--insert/truncate is ~100.000 times more performant than doing a insert/delete in the loop or a permanent update on one tuple (haven't tried indices yet)
Run Code Online (Sandbox Code Playgroud)

请参阅http://www.flickr.com/photos/74806161@N03/6732847259/in/photostream查看显示吸盘过程描述的图像和http://www.flickr.com/photos/74806161@N03/6732846981/in /photostream用于显示吸盘进程的内存消耗的图像

任何人有任何想法吗?

Mar*_*ith 5

看起来直到 SQL Server 2000 有一个未记录的命令DBCC CHECKDBTS可以完全按照您的要求执行,但现在已经没有了。看起来它存储在数据库启动页面上,没有(安全,见下文)手动设置它的方式。

我不确定你为什么要这样做,我建议你不要打扰,但如果你必须这样做,那么你可能会更快地找到基于集合的插入。

(注意:下面可能需要调整以避免超出目标,因为我发现每插入一百万行@@DBTS都会增加,1003921但应该是一个改进......)

CREATE TABLE __DUMMY (I TINYINT, TS TIMESTAMP)

DECLARE @Target INT, @Batch INT
SET @Target = 666666666

WHILE @Target >  CONVERT(INT, @@DBTS)
BEGIN
RAISERROR ('@@DBTS = %d',0,1,@@DBTS) WITH NOWAIT;

SET @Batch = @Target - CONVERT(INT, @@DBTS);

IF @Batch > 1000000 
    SET @Batch = 1000000;

   WITH E00(N) AS (SELECT 1 UNION ALL SELECT 1),
        E02(N) AS (SELECT 1 FROM E00 a, E00 b),
        E04(N) AS (SELECT 1 FROM E02 a, E02 b),
        E08(N) AS (SELECT 1 FROM E04 a, E04 b),
        E16(N) AS (SELECT 1 FROM E08 a, E08 b),
        E32(N) AS (SELECT 1 FROM E16 a, E16 b),
   cteTally(N) AS (SELECT ROW_NUMBER() OVER (ORDER BY N) FROM E32)
 INSERT INTO __DUMMY (I) 
  SELECT 1
   FROM cteTally
  WHERE N <= @Batch;


TRUNCATE TABLE __DUMMY
END


DROP TABLE __DUMMY
Run Code Online (Sandbox Code Playgroud)

或者,如果这只是一个开发数据库,​​你有备份,如果一切都出错,你不会来向我抱怨,你可以对未记录的和高度警告的DBCC WRITEPAGE命令进行一些试验。

USE tempdb;

IF DB_ID('TestDBTS') IS NOT NULL
    DROP DATABASE TestDBTS;

CREATE DATABASE TestDBTS;

USE TestDBTS;

DBCC WRITEPAGE(TestDBTS, 1, 9, 412, 8, 0xAA86BC2700000000);

ALTER DATABASE TestDBTS SET OFFLINE WITH ROLLBACK IMMEDIATE;

ALTER DATABASE TestDBTS SET ONLINE WITH ROLLBACK IMMEDIATE;

USE TestDBTS;
SELECT @@DBTS;

DBCC TRACEON (3604);
DBCC DBINFO ('TestDBTS');
DBCC TRACEOFF (3604);
Run Code Online (Sandbox Code Playgroud)