【问题标题】:Error when inserting large amount of rows to a table with rowversion/timestamp column (SQL Server 2016)向具有 rowversion/timestamp 列的表中插入大量行时出错 (SQL Server 2016)
【发布时间】:2017-01-23 13:27:31
【问题描述】:

我正在尝试使用 INSERT INTO / SELECT 语句将大量行插入到具有 rowversion/timestamp 列的表中。

INSERT 语句总是返回错误:

为数据库生成新的 DBTS 时发生内部错误。 请重试操作。

将单个事务中的数据插入到具有 rowversion/timestamp 列的表中时是否有大小限制?

我已经阅读了所有相关的 MSDN 页面,看来这应该可行。看起来很奇怪,像个虫子。我已经使用以下 SQL Server 版本(所有 Enterprise x64)在 3 个不同的服务器(所有 VMware 虚拟化)上尝试了相同的操作:

  • 13.0.4411.0
  • 13.0.4001.0
  • 13.0.2164.0

这是重现错误的脚本:

USE Db1
GO

DROP TABLE IF EXISTS [dbo].[TESTTABLE]
GO

-- insert 400 million dummy records 
SELECT 
    TOP 400000000 IDENTITY(int,1,1) AS Number 
INTO 
    [dbo].[TESTTABLE]
FROM 
    sys.columns s1       
CROSS JOIN 
    sys.columns s2 
CROSS JOIN 
    sys.columns s3 


USE Db2
GO

DROP TABLE IF EXISTS [dbo].[TESTTABLE]
GO

-- create table with a timestamp/rowversion column
CREATE TABLE [dbo].[TESTTABLE](
    [StageTimestamp] [timestamp] NOT NULL,
    [SomeNumber] [int] NOT NULL
)

GO

-- insert 400 million records into the table
INSERT INTO
    [dbo].[TESTTABLE] WITH (TABLOCK) (SomeNumber)
SELECT
    Number
FROM
    [db1].[dbo].[TESTTABLE]
GO 

【问题讨论】:

  • 您的 db1 testtable 包含 1 列,您的 db2 testtable 包含两个字段。也许您需要在插入中指定一个字段列表?
  • 列列表在 INSERT(“SomeNumber”列)中指定。应该自动填充另一列“StageTimestamp”(这就是它的重点) - 这就是它未在列列表中指定的原因。
  • 看起来 2016 年的 DBTS 可能存在问题。在 microsoft connect 上找到了这个:connect.microsoft.com/SQLServer/feedback/details/3118341/…
  • 似乎如此。我刚刚在 SQL Server 2014 上对此进行了测试,作为单独的实例安装在同一台服务器上,它可以在 SQL 2014 上运行。这很奇怪,但确实似乎是 SQL 2016 数据库引擎中的一个错误。
  • @saso 我希望您将此提交给 microsoft connect。 connect.microsoft.com/SQLServer/Feedback

标签: sql-server sql-server-2016


【解决方案1】:

这不是永久修复,但经过反复试验并提出了解决方法。插入较小的记录块时插入工作正常,用1000万和5000万块测试,插入没有失败。脚本的第二部分已更新为循环。

USE Db2
GO

DROP TABLE IF EXISTS [dbo].[TESTTABLE]
GO

-- create table with a timestamp/rowversion column
CREATE TABLE [dbo].[TESTTABLE](
    [StageTimestamp] [timestamp] NOT NULL,
    [SomeNumber] [int] NOT NULL
)

GO

DECLARE @rowcount INT = 1
DECLARE @LastNumber INT = 0
WHILE (@rowcount > 0)
BEGIN
    --insert 50 million blocks of records into the table
    INSERT INTO
        [dbo].[TESTTABLE] WITH (TABLOCK) (SomeNumber)
    SELECT TOP(50000000)
        Number
    FROM
        [db1].[dbo].[TESTTABLE]
    WHERE Number > @LastNumber

    --get insert rows, it will loop until no more rows is inserted
    SET @rowcount = @@ROWCOUNT

    --get the last number
    SELECT @LastNumber = MAX(SomeNumber) FROM [dbo].[TESTTABLE]
END
GO

【讨论】:

    【解决方案2】:

    我来到这里是因为这是用德语查找错误时的第一个结果。我做了更多的挖掘,并在这里找到了这篇博文: https://techcommunity.microsoft.com/t5/sql-server-support/an-internal-error-happened-while-generating-a-new-dbts-for/ba-p/334021

    它很好地解释了后台发生的事情,以便更好地理解问题。

    我通过捕获错误解决了我的问题,将任务设置为睡眠 0.5 秒,然后再次发送相同的命令。

    我设置了 10 次重试的限制,到目前为止还没有达到。

    【讨论】:

      猜你喜欢
      • 2023-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-08
      • 1970-01-01
      • 1970-01-01
      • 2012-03-01
      • 1970-01-01
      相关资源
      最近更新 更多