关于"ISAM error: non-exclusive access"的说明

错误模拟:

Session A: 定义一个存储过程,并打开一个游标,让游标保持60s

 

createprocedure "informix".a ()
define i int;
define j char(30);
foreach cur1 for select a,b into i,j from x
system 'sleep 60';
end foreach;
end procedure ;
execute procedure a();

 

Session B:在A进行的同时,修改表结构

Alter table x add ( c char(10) );
 

 242: Could not open database table(informix.modinfo).  

 106: ISAM error:  non-exclusive access.  

 

Session B 会得到如下报错。这个报错并不是因为上面的游标锁住了该表,我们可以检查syslocks或者在sessionB执行:

lock table x in exclusive mode;

Table locked.

 

 

究其原因,应该是由于使用了游标读取,虽然游标并不加锁,但是会保证表的partion信息不被更新。

我们也可以这么模拟:

Session A: 执行一个大表的扫描,如表modinfo,该表有1000000以上的数据量

dbaccess shentest <<! 1>/dev/null 2>&1
select * from modinfo;
!

Session B:在A进行的同时,修改表结构

Alter table modinfo add ( c char(10) );

同样会得到上面的错误。

 

解决问题方法:

针对该问题,网上说可以增加IFX_DIRTY_WAIT环境变量,我也进行了尝试,确实可以解决问题,但会产生一些新问题,说明如下:

Session A: 对大表进行select

dbacces sshentest <<! 1>/dev/null 2>&1
select* from modinfo;
!

Session B: 设置 exportIFX_DIRTY_WAIT=30,执行:

Alter table modinfo add ( c char(10) );

这时session B会处于等待状态,如果A在30s内完成,B可以正常执行,否则仍报“non-exclusive access”错误。

 

带来的问题如下:

当session A正在执行,而Session B也在等待时,我们执行sessionC,而无论SessionC是否设置IFX_DIRTY_WAIT,都会出现:

Session C:

dbaccess shentest <<!
Select * from modinfo;
!

[informix@dbmaster~]$ sh y.sh

 Databaseselected.

  243: Could not position within a table(informix.modinfo).

  106: ISAM error:  non-exclusive access.
   
  
 Databaseclosed.

Session C立刻会报这个错误。而如果只有session A和sessionC执行时(两个select),各自不干扰,可同时执行。

究其原因,应该是sessionB虽然在等待sessionA执行完毕,但已经独占了该表的partition信息,致使其他连接无法读取该表。为了避免该问题,建议对表结构的修改采用反复尝试的办法,而不是采取设置该环境变量的方法。尝试方式可以加入死循环,先检查,在执行,在检查,在执行。

 

常用案例: 修改表分区,detach过期分区:

drop procedure defrag;

create procedure defrag(tabname varchar(20),part varchar(20))
define i int;
define procname char(32);
define sql varchar(255);
DEFINE sql_errI NTEGER;
DEFINE isam_err INTEGER;
DEFINE err_txt CHAR(200);
let procname='defrag';

for i in (1 to 1000 step 1)

on exception SET sql_err, isam_err, err_txt
	insert into proclog values(procname,current year to second,sql_err, isam_err, err_txt);
end exception with resume;

if exists (select b.tabname from sysfragments a, systables b
	    where a.tabid=b.tabid and b.tabname=tabname and a.partition=part )
then
	let sql='alter fragment on table '||tabname||' detach '||part||' '||tabname||part;
	execute immediate sql;
end if;

if exists (select tabname from systables where tabname=tabname||part)
then
	let sql='drop table '||' '||tabname||part;
	execute immediate sql;
end if;          
end for;
end procedure;

execute procedure defrag('minfo','pt1105');
	
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值