Error: 9561的一种处理方法

本文的目的在于给出一种方法(或者workaround)来屏蔽错误Error: 9561。

在老环境ASE 12.5上测试某程序时,执行一些命令会报Error: 9561!

环境介绍:

ASE版本为: Adaptive Server Enterprise/12.5/SWR 9616 GA/P/NT (IX86)/OS 4.0/main/1647/32-bit/OPT/Fri Jun 01 16:58:25 2001
此版本为ASE 12.5 GA,裸奔很久了。

lock scheme=allpages

系统库model、tempdb以及用户数据库均启用了选项:allow nulls by default

现象描述:

使用存储过程sp_helpindex查看表上的索引信息时,会报Error:9561。

1> sp_helpindex sysobjects
2> go
Msg 9561, Level 20, State 5:
Server 'TEST', Procedure 'sp_helpindex', Line 306:
An insert or update to table '#spindtab____01000430020573012' places column 'maxrowsperpage' at offset 2, ending at offset 4. The maximum permitted ending offset for this column is 2. This is a server internal error.
Msg 9561, Level 20, State 5:
Server 'TEST', Procedure 'sp_helpindex', Line 306:
An insert or update to table '#spindtab____01000430020573012' places column 'maxrowsperpage' at offset 2, ending at offset 4. The maximum permitted ending offset for this column is 2. This is a server internal error.
 index_name           index_description                                        index_keys
 -------------------- -------------------------------------------------------- --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

(0 rows affected)
(return status = 0)

执行存储过程sp_helprotect查看对象权限分配信息时,也报类似的Error:9561。

1>sp_helprotect dbo
2>go
Msg 9561, Level 20, State 5:
Server 'TEST', Procedure 'sp_helprotect', Line 299:
An insert or update to table '#sysprotects201000430020573012' places column 'id' at offset 2, ending at offset 6. The maximum permitted ending offset for this column is 2. This is a server internal error.

 

分析过程

根据Error:9561的错误信息描述,曾经怀疑某系统表中某字段的偏移信息出现了差错。

在网上搜索一下CR: 389129( 来源于:Targeted CR List for ASE 15.0 ESD #2

Error 511 "Attempt to update or insert row failed because resultant row of size < value > bytes is larger than the maximum size ( < value > bytes) allowed for this table..." may be raised during the execution of a stored procedure using the reformatting strategy and the creation of a DOL (Datarows Only Locking) work table. Alternatively the error 9561 "An insert or update to table 'temp worktable' places column '(unknown column)' at offset < value > ..." may be raised.

很奇怪,我的ASE12.5配置的lock scheme为allpages,怎么会自动创建DOL类型的工作表呢?

浏览存储过程sp_helpindex的源代码,发现一张临时表#spindtab的创建语句:

create table #spindtab

(
        index_name      varchar(30),
        index_keys      varchar(1024),
        index_description       varchar(68),
        index_max_rows_per_page smallint,
        index_fillfactor        smallint,
        index_reservepagegap    smallint,
        index_created           datetime NULL
)

Error:9561信息中显示的#spindtab____01000430020573012就是指的存储过程sp_helpindex中创建的临时表#spindtab!

此处你需要了解一下会话临时表的命名规则,可以参考Rob V.的文章:Reading temporary tables that aren't yours

再继续追踪列名:maxrowsperpage,找到这样一条语句:

insert into #spindtab
    select name, @keys, @inddesc, maxrowsperpage, fill_factor,
        isnull(res_page_gap ,0), crdate
        from sysindexes
            where id = object_id(@objname)
                and indid = @indid

查看一下列maxrowsperpage在表sysindexes中的偏移情况:

1> select colid,name,offset,length from syscolumns where id= 2  and name='maxrowsperpage'
2> go
 colid  name                           offset length
 ------ ------------------------------ ------ -----------
     16 maxrowsperpage                     48           2

列maxrowsperpage在sysindexes处于第16个位置,偏移48字节,好像和Error:9561提示的offset:2没有什么关系。

再来看看临时表#spindtab中的第4个字段: index_max_rows_per_page,它的类型是:smallint,占用2字节。和Error:9561提示的开始偏移2,结束偏移4可能有点关系!

字段index_max_rows_per_page前面的3个字段都是varchar类型,都是属于变长类型字段;

如果index_max_rows_per_page存储在offset=2位置处的话,必要要求index_max_rows_per_page定义为NOT NULL,表#spindtab的定义语句中没有指定NOT NULL或者NULL。这是问题所在!

 

解决方法

关闭临时数据库、model上的选项:allow nulls by default;

将lock scheme设置成datarows,Error:9561的错误信息就变成:

An insert or update to table '#spindtab____01000430020573012' places column 'maxrowsperpage' at offset 6, ending at offset 8. The maximum permitted ending offset for this column is 6. This is a server internal error.

本文的关键信息

1、选项:allow nulls by default会影响没有显示指定是否为空字段的为空属性;

2、一个字段是否为空,在行内的存储位置是不同的;

3、DOL表与APL表的初始offset值不同;

  • 本文链接地址:https://www.dbainfo.net/one-way-to-deal-with-error-9561.htm
  • 本文为dbainfo个人原创,请在尊重作者劳动成果的前提下进行转载;
  • 转载务必注明原始出处 : Sybase数据库技术,数据库恢复专家
  • 对《Error: 9561的一种处理方法》有何疑问或见解,请在本文下方发表;
  • 对网站还有其他问题或建议,请提交在留言板,谢谢!
  • 目前还没有任何评论.
    :wink: :twisted: :roll: :oops: :mrgreen: :lol: :idea: :evil: :cry: :arrow: :?: :-| :-x :-o :-P :-D :-? :) :( :!: 8-O 8)