Sybase ASE 用于更新崩溃的游标
Sybase ASE for update cursor that crashes
我刚刚遇到了使用更新游标的 ASE(15.7 ESD 15.2 版)的奇怪行为。
最后我找到了根本原因,但我想 post 把它放在这里因为它可能有用,也许有人已经面对它了。
我写了这个简单的 "for update" 游标:
DECLARE c_contactrule
CURSOR FOR
SELECT a.id
FROM FTContactRule a, Client b, ClientContact c
WHERE /* join conditions */
AND a.client_id IN ( bla bla bla )
AND a.message_subtype_id ( bla bla bla )
AND /* and so on */
for update of a.preferred_medium_id
go
(为了提高可读性,我对这个 post 的查询做了一些总结)
以后当然是读取游标值直到最后。
open c_contactrule
fetch c_contactrule into @rule_to_update
while @@sqlstatus = 0
begin
/* do something */
end
close c_contactrule
deallocate c_contactrule
go
我想你猜到了某个地方有一个 update preferred_medium_id where current of
目前,此查询以一种非常特殊的方式崩溃:抛出的消息是 "ASE termintaed this process",事实上,他终止了我的会话!
调查后,我发现错误的代码行是第一个 fetch into
语句。
我终于找到了导致此错误消息的原因,但我仍然认为这是一个错误,因为崩溃是服务器反应过于强烈。应该有一个对用户更友好的消息或一个解析错误,而不是一个无声的终止。
无论如何,我的测试表明问题是由于我更新了一个不在游标的 select 语句中的字段:
select a.id
....
for update of a.preferred_medium_id
我刚刚在 select 列表中添加了该字段,当然我在 fetch into 中添加了一个变量并且它工作正常。
select a.id, a.preferred_medium_id
....
for update of a.preferred_medium_id
但是,当您不需要对它做任何事情时,必须在变量中保存一个值有点奇怪。
此外,终止会话并不是服务器的良好响应。如果有这样的语法规则,那么我们应该有一个解析错误说 "You cannot update a field wich is not in you select list for un update cursor"
如果 ASE 终止了会话,则说明您遇到了 ASE 中的错误。唯一的补救措施是升级到包含修复程序的更新版本。与 TechSupport 检查是否可以识别错误(错误日志中应该有堆栈跟踪)以及是否有可用的修复程序。
如果您以不同的方式重写查询,例如导致不同的查询计划,则有可能不会遇到错误,但这并不能保证(也不是一个非常令人欣慰的解决方案)。
我刚刚遇到了使用更新游标的 ASE(15.7 ESD 15.2 版)的奇怪行为。
最后我找到了根本原因,但我想 post 把它放在这里因为它可能有用,也许有人已经面对它了。
我写了这个简单的 "for update" 游标:
DECLARE c_contactrule
CURSOR FOR
SELECT a.id
FROM FTContactRule a, Client b, ClientContact c
WHERE /* join conditions */
AND a.client_id IN ( bla bla bla )
AND a.message_subtype_id ( bla bla bla )
AND /* and so on */
for update of a.preferred_medium_id
go
(为了提高可读性,我对这个 post 的查询做了一些总结)
以后当然是读取游标值直到最后。
open c_contactrule
fetch c_contactrule into @rule_to_update
while @@sqlstatus = 0
begin
/* do something */
end
close c_contactrule
deallocate c_contactrule
go
我想你猜到了某个地方有一个 update preferred_medium_id where current of
目前,此查询以一种非常特殊的方式崩溃:抛出的消息是 "ASE termintaed this process",事实上,他终止了我的会话!
调查后,我发现错误的代码行是第一个 fetch into
语句。
我终于找到了导致此错误消息的原因,但我仍然认为这是一个错误,因为崩溃是服务器反应过于强烈。应该有一个对用户更友好的消息或一个解析错误,而不是一个无声的终止。
无论如何,我的测试表明问题是由于我更新了一个不在游标的 select 语句中的字段:
select a.id
....
for update of a.preferred_medium_id
我刚刚在 select 列表中添加了该字段,当然我在 fetch into 中添加了一个变量并且它工作正常。
select a.id, a.preferred_medium_id
....
for update of a.preferred_medium_id
但是,当您不需要对它做任何事情时,必须在变量中保存一个值有点奇怪。
此外,终止会话并不是服务器的良好响应。如果有这样的语法规则,那么我们应该有一个解析错误说 "You cannot update a field wich is not in you select list for un update cursor"
如果 ASE 终止了会话,则说明您遇到了 ASE 中的错误。唯一的补救措施是升级到包含修复程序的更新版本。与 TechSupport 检查是否可以识别错误(错误日志中应该有堆栈跟踪)以及是否有可用的修复程序。
如果您以不同的方式重写查询,例如导致不同的查询计划,则有可能不会遇到错误,但这并不能保证(也不是一个非常令人欣慰的解决方案)。