【问题标题】:How to prevent 'query timeout expired'? (SQLNCLI11 error '80040e31')如何防止“查询超时过期”? (SQLNCLI11 错误“80040e31”)
【发布时间】:2014-03-18 21:19:28
【问题描述】:

我已连接到经典 ASP (VBScript) 中的 MS SQL Server 2012 数据库。这是我的连接字符串:

Provider=SQL Server Native Client 11.0;Server=localhost;
Database=databank;Uid=myuser;Pwd=mypassword;

当我执行这条 SQL 命令时:

UPDATE [info] SET [stamp]='2014-03-18 01:00:02',
[data]='12533 characters goes here',
[saved]='2014-03-18 01:00:00',
[confirmed]=0,[ip]=0,[mode]=3,[rebuild]=0,
[updated]=1,[findable]=0 
WHERE [ID]=193246;

我收到以下错误:

Microsoft SQL Server Native Client 11.0 
error '80040e31'
Query timeout expired   
/functions.asp, line 476

SQL 查询很长,数据字段更新为 12533 个字符。 ID 列已编入索引,因此查找 ID 为 193246 的帖子应该很快。

当我在 SQL Server Management Studio 上执行完全相同的 SQL 表达式(复制和粘贴)时,它立即成功完成。没问题。所以 SQL 本身没有问题。我什至尝试过使用 ADODB.Recordset 对象并通过它进行更新(没有自写 SQL),但我仍然遇到相同的超时错误。

如果我转到 Management Studio 中的工具 > 选项 > 查询执行,我会看到执行超时设置为 0(无限)。在工具 > 选项 > 设计器下,我看到事务超时设置为 30 秒,这应该足够了,因为脚本和数据库位于同一台计算机上(“localhost”在连接字符串中)。

这里发生了什么?为什么我可以在 Management Studio 中执行 SQL,但不能在我的 ASP 代码中执行?


编辑:尝试将“设计器”选项卡中的 30 秒超时设置为 600 秒以确保,但我仍然遇到同样的错误(顺便说一句,在页面加载 30 秒后发生)。

这是我用来在 ASP 页面上执行 SQL 的代码:

Set Conn = Server.CreateObject("ADODB.Connection")
Conn.Open "Provider=SQL Server Native Client 11.0;
Server=localhost;Database=databank;Uid=myuser;Pwd=mypassword;"
Conn.Execute "UPDATE [info] SET [stamp]='2014-03-18 01:00:02',
[data]='12533 characters goes here',[saved]='2014-03-18 01:00:00',
[confirmed]=0,[ip]=0,[mode]=3,[rebuild]=0,[updated]=1,[findable]=0 
WHERE [ID]=193246;"

编辑 2: 使用Conn.CommandTimeout = 0 为查询提供无限的执行时间没有任何作用,它只会让查询永远执行。等了 25 分钟,它仍在执行。

然后我尝试将 SQL 分成两个 SQL 语句,一个是长数据更新,另一个是另一个更新。它仍然不会更新长数据字段,只是超时。

我用两个额外的连接字符串尝试了这个:

Driver={SQL Server};Server=localhost;Database=databank;Uid=myuser;Pwd=mypassword;
Driver={SQL Server Native Client 11.0};Server=localhost;Database=databank;Uid=myuser;Pwd=mypassword;

没用。我什至尝试将数据更改为 12533 A,以查看实际数据是否导致问题。不,同样的问题。

然后我发现了一些有趣的事情:我尝试先执行短 SQL,然后再执行数据字段的长更新。它也有查询超时异常...

但是为什么呢?它的更新内容很少(整个 SQL 语句不到 200 个字符)。将进一步调查。


编辑 3: 我认为这可能与登录有关,但我没有发现任何看起来有问题的地方。我什至尝试更改连接字符串以使用 sa 帐户,但即使这样也没有用,仍然出现“查询超时已过期”。

这快把我逼疯了。没有解决方案,没有解决方法,最糟糕的是没有想法!


编辑 4: 转到 Management Studio 中的工具 > 选项 > 设计器并勾选“防止保存需要重新创建表的更改”。它什么也没做。

尝试将“数据”列数据类型从“nvarchar(MAX)”更改为劣质的“ntext”类型(我快绝望了)。没用。

尝试在帖子上执行我能想到的最小更改:

UPDATE [info] SET [confirmed]=0 WHERE [ID]=193246;

这会将位列设置为 false。没用。我尝试在 Management Studio 中执行完全相同的查询,结果完美无缺。

如果你有想法,请给我一些想法,因为我现在真的用完了。


编辑5:现在还尝试了以下连接字符串:

Provider=SQLOLEDB.1;Password=mypassword;Persist Security Info=True;User ID=myuser;Initial Catalog=databank;Data Source=localhost

没用。仅尝试将确认设置为 false,但仍然超时。


编辑 6:现在已尝试更新同一张表中的不同帖子:

UPDATE [info] SET [confirmed]=0 WHERE [ID]=1;

它也给出了超时错误。所以现在我们知道它不是特定于帖子的。

我可以通过 ASP 更新同一“数据库”数据库中其他表中的帖子。我还可以更新本地主机上其他数据库中的表。

会不会是 [info] 表有问题?我使用 MS Access 向导将数据从 Access 自动移动到 MS SQL Server 2012,它创建了数据类型为“ntext”的列,我手动将其更改为“nvarchar(MAX)”,因为不推荐使用 ntext。有什么东西坏了?当我更改数据类型时,它确实需要我重新创建表。

我必须睡一觉,但如果有人回复我,我一定会在明天回来查看。请这样做,即使你只有一些鼓励的话。


编辑 7: 睡前快速编辑。还尝试在连接字符串中将提供程序定义为“SQLNCLI11”(使用 DLL 名称而不是实际的提供程序名称)。没有什么不同的。连接创建得一样好,但超时仍然发生。

另外,我没有使用 MS SQL Server 2012 Express(据我所知,在安装过程中任何地方都没有提到“Express”)。这是完整的东西。

如果有帮助,这里是 Management Studio 提供的“帮助”>“关于...”信息:

Microsoft SQL Server Management Studio: 11.0.2100.60  
Microsoft Analysis Services Client Tools: 11.0.2100.60  
Microsoft Data Access Components (MDAC): 6.3.9600.16384  
Microsoft MSXML: 3.0 5.0 6.0   
Microsoft Internet Explorer: 9.11.9600.16521  
Microsoft .NET Framework: 4.0.30319.34011  
Operating System: 6.3.9600

编辑 8(也称为“程序员永不眠”编辑):

在尝试了一些事情之后,我最终尝试关闭数据库连接并在执行 SQL 语句之前重新打开它。它突然起作用了。什么...?

我的代码在一个子程序中,结果发现在它之外我试图更新的帖子已经打开了!所以超时的原因是帖子或整个表被尝试更新它的同一连接锁定。所以连接(或 CPU 线程)正在等待一个永远不会解锁的锁。

讨厌这么努力,结果却这么简单。

这个帖子已经被这个简单的代码在子程序之外打开了:

Set RecSet = Conn.Execute("SELECT etc")

我只是在调用子程序之前添加了以下内容。

RecSet.Close
Set RecSet = Nothing

我从未想过这件事的原因仅仅是因为这在 MS Access 中是允许的,但现在我已更改为 MS SQL Server,而且它不是那么好(或者说是草率)。 Conn.Execute() 创建的 RecSet 之前从未在数据库中创建过锁定的帖子,但现在突然之间它做到了。不太奇怪,因为连接字符串和实际数据库已经改变。

如果您正在从 MS Access 迁移到 MS SQL Server,我希望这篇文章可以帮其他人省去一些麻烦。虽然我无法想象现在世界上还剩下这么多 ​​Access 用户。

【问题讨论】:

  • 如果你使用的是SqlCommand mySql,那么试试mySql.CommandTimeout = 0。
  • 这里没有 MySQL 或 MySQL 相关的工具,只有 MS SQL。
  • mySql 是变量的名称。我知道它的 SQL 服务器。
  • 你使用哪个类来存储和执行你的 SQL 命令?
  • 上课?对不起,我不明白你的意思。它是 MS SQL 服务器中的东西吗?我是新手,只是更改了旧 Access 类型的所有数据库(此代码运行良好)。如果你的意思是在我的代码中,我没有任何课程。也许您的意思是我使用什么对象来执行 SQL 命令?我会把它添加到我的帖子中,请稍等。

标签: sql sql-server vbscript asp-classic sql-server-2012-express


【解决方案1】:

原来帖子(或者更确切地说是整个表格)被我试图更新帖子的同一个连接锁定。

我有一个由以下人创建的帖子的打开记录集:

Set RecSet = Conn.Execute()

这种类型的记录集应该是只读的,当我使用 MS Access 作为数据库时,它没有锁定任何东西。但显然这种类型的记录集确实在 MS SQL Server 2012 上锁定了一些东西,因为当我在执行 UPDATE SQL 语句之前添加这些代码行时......

RecSet.Close
Set RecSet = Nothing

...一切正常。

所以底线是要小心打开的记录集 - 即使它们是只读的,它们也可能会锁定您的表以防更新。

【讨论】:

    猜你喜欢
    • 2016-11-28
    • 2015-12-13
    • 1970-01-01
    • 2011-01-26
    • 1970-01-01
    • 1970-01-01
    • 2021-04-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多