SQL Server 简单插入语句超时

Posted

技术标签:

【中文标题】SQL Server 简单插入语句超时【英文标题】:SQL Server simple Insert statement times out 【发布时间】:2010-10-01 14:58:53 【问题描述】:

我有一个有 6 列的简单表格。大多数情况下,任何插入语句都可以正常工作,但有时我会遇到 DB Timeout 异常: 超时已过。在操作完成之前超时时间已过或服务器没有响应。声明已终止。

超时设置为 10 秒。

我应该提到我正在使用 NHibernate,并且该语句还在插入本身之后包含一个“select SCOPE_IDENTITY()”。

我的想法是该表被锁定或其他什么,但当时该表上没有其他语句运行。

所有的插入都非常简单,在 sql profiler 中一切看起来都很正常,表没有索引,只有 PK(页面填充度:98.57 %)。

关于我应该寻找什么的任何想法?

谢谢。

【问题讨论】:

【参考方案1】:

查看表格的碎片,您可能会因此而出现页面拆分

【讨论】:

【参考方案2】:

当时没有其他语句在该表上运行。

作为事务的一部分针对其他表运行的语句呢?这可能会在问题表上留下锁。

还要检查当时发生的日志文件或数据文件增长情况,如果您运行的是 SQL2005,它会显示在 SQL 错误日志中。

【讨论】:

其实事务插入到3张表中,怎么会锁问题表呢? 这样,大致:0:开始交易; 1:更新问题表中的一条记录(运行快); 2:更新一些其他表(需要很长时间); 3:提交问题表会一直锁定到第3步;如果另一个作业尝试更新被锁定的记录,它将等待。【参考方案3】:

我认为您最有可能的罪魁祸首是来自另一个事务的阻塞锁(或者可能来自触发器或幕后的其他东西)。

最简单的判断方法是启动INSERT,当它挂起时,在同一服务器上的另一个窗口中运行EXEC SP_WHO2。这将列出所有当前的数据库活动,并有一个名为BLK 的列,它将显示当前是否有任何进程被阻止。检查挂起连接的SPID,看看BLK 列中是否有任何内容,如果有,那就是阻止你的进程。

即使您认为没有任何其他语句在运行,唯一确定的方法是使用类似的 SP 列出当前事务。

【讨论】:

如果超时偶尔发生,我无法“捕捉”运行调试命令的时间? 如何停止阻塞的进程? 我想如果您的超时时间为 10 秒,您可以在 8 或 9 秒后运行 SP_WHO2(请参阅其他答案),看看它是否捕捉到了什么。这可能很难实现,但可能是唯一的方法。当然,如果它成功了,你会在它开始之前取消它。【参考方案4】:

可能是表格需要很长时间才能增长。

如果您将表设置为大幅增长,并且没有启用即时文件初始化,那么查询肯定会每隔一段时间就会超时。

看看这个烂摊子:MSDN

【讨论】:

自动增长设置为 1MB,分配 1MB 需要这么长时间吗? @meidan 不,它不会花费那么长时间,但我会将其更改为以更大的块增长,否则随着时间的推移,如果文件系统不断增长,您最终会得到一个非常碎片化的文件系统。默认值为 10%,这适用于除了非常大的数据库之外的大多数情况。 @Eam - 坦克!它对插入大对象非常重要【参考方案5】:

我们的 QA 有一些返回大结果集的 Excel 连接,这些查询因 WaitType 为 ASYNC_NETWORK_IO 而暂停了一段时间。在此期间,所有其他查询都超时,因此特定插入与它无关。

【讨论】:

【参考方案6】:

这个问题似乎是一个代码 sn-p 的好地方,我用它来查看阻塞和阻塞查询的实际 SQL 文本。

下面的 sn-p 采用 SP_WHO2 返回“.”的约定。 BlockedBy 的文本用于非阻塞查询,因此它会将它们过滤掉并返回剩余查询的 SQL 文本(“受害者”和“罪魁祸首”):

--prepare a table so that we can filter out sp_who2 results
DECLARE @who TABLE(BlockedId INT, 
                   Status VARCHAR(MAX), 
                   LOGIN VARCHAR(MAX), 
                   HostName VARCHAR(MAX), 
                   BlockedById VARCHAR(MAX), 
                   DBName VARCHAR(MAX), 
                   Command VARCHAR(MAX), 
                   CPUTime INT, 
                   DiskIO INT, 
                   LastBatch VARCHAR(MAX), 
                   ProgramName VARCHAR(MAX), 
                   SPID_1 INT, 
                   REQUESTID INT)
INSERT INTO @who EXEC sp_who2

--select the blocked and blocking queries (if any) as SQL text
SELECT 
(
    SELECT TEXT 
    FROM sys.dm_exec_sql_text(
       (SELECT handle 
        FROM (
            SELECT CAST(sql_handle AS VARBINARY(128)) AS handle
            FROM sys.sysprocesses WHERE spid = BlockedId
        ) query)
    )
) AS 'Blocked Query (Victim)',
(
    SELECT TEXT 
    FROM sys.dm_exec_sql_text(
       (SELECT handle 
        FROM (
            SELECT CAST(sql_handle AS VARBINARY(128)) AS handle
            FROM sys.sysprocesses WHERE spid = BlockedById
        ) query)
    )
) AS 'Blocking Query (Culprit)'
FROM @who 
WHERE BlockedById != '  .'

【讨论】:

老鼠。在 SQL 2000 中,'MAX' 附近的语法不正确,插入表变量时不能将 EXECUTE 用作源等。此脚本需要什么版本的 SQL? 它确实适用于 SQL 2008 年,但那个数据库不是我的问题。 您是否尝试过使用临时表而不是表变量? 对完全无用的评论表示歉意,但是……干得好那个人:) 这是名人堂的剧本。帮助我解决了一个困扰我们一个系统很长时间的问题。 +1000 哇,这是一个地狱般的查询,魔术。一个我会永远坚持下去的sn-p。

以上是关于SQL Server 简单插入语句超时的主要内容,如果未能解决你的问题,请参考以下文章

sql server有批量插入和批量更新的sql语句吗

sql server而不是使用插入的变量和值触发插入语句

如何在sqlserver中用sql语句插入随机的大量的数据啊~求救。。

无法使用自动增量插入到 SQL Server CE

SQL Server插入数据和删除数据基础语句使用

sql server 中如何插入一条时间记录