问题 如何防止'查询超时过期'? (SQLNCLI11错误'80040e31')


我在经典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秒,以确保,但我仍然得到相同的错误(在页面加载btw 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

没工作。只是尝试将确认设置为假但仍然有一段时间。


编辑6: 现在尝试更新同一个表中的其他帖子:

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

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

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

可能会因[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用户。


11816
2018-03-18 21:19


起源

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


答案:


事实证明,帖子(或者更确切地说是整个表格)被我尝试更新帖子的连接锁定了。

我有一个打开的记录集,由以下内容创建:

Set RecSet = Conn.Execute()

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

RecSet.Close
Set RecSet = Nothing

......一切正常

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


11
2018-03-19 11:14