Archive for February, 2007
又遇到”maximum open cursors exceeded”
Posted by xbin999 in Uncategorized on February 15, 2007
昨天刚骂完娘,下午还是又被拉到学院路了。说是程序出错,提示"maximum open cursors exceeded"。电话都到老板那里了,伙计们也都急着要回家过年。
只有自己再过去看看是啥。当初曾碰到过一次,那时的原因是"远程访问序列"的问题。这里再描述一次吧:
在oracle的文档中给出了取sequence值的例子:schema.sequence.nextval@dblink
不过这里还有一个要注意的地方,就是写完整的sql语句时,应该是
select yourseq.nextval@dblink from dual@dblink
而不是
select yourseq.nextval@dblink from dual
两者有差别,这一次我的程序就犯了这个错误,使用了后一种写法,结果在后台服务程序长时间运行后出错,错误信息:
ORA-01000 maximum open cursors exceeded
主要原因就是使用后一种写法,造成分布式事务,每执行一次会打开游标,而没有关闭,这样一个session长时间执行后,就可能超出OPEN_CURSORS的阀值。
如果有环境的话,大家可以一试:
在sqlplus中执行
select seq_test.nextval@mydblink from dual;
语句,然后检查
select OPEN_CURSORS from v$dblink;
该数值持续增长。
赶到机房,看了错误,再问了一下同事的代码,感觉采用OTL时用了静态变量出了问题。写了段测试代码:
int test_open_cursors( otl_connect& dbConnect, CBSErrorMsg& cErrorMsg)
{
int16 rv;
try
{
int iOpenCursors = 0;
string strSql = "select 1 from dual@testcs2";
string strSql2 = "select OPEN_CURSORS from v$dblink";
double llSeqId;
int32 iMax = 2000;
for ( int i = 0; i < iMax; ++i)
{
static otl_stream os;
os.open( 1, strSql.c_str(), dbConnect);
os >> llSeqId;
cout << llSeqId << "t";
// os.close();
otl_stream os2( 1, strSql2.c_str(), dbConnect);
os2 >> iOpenCursors;
cout << iOpenCursors << endl;
}
}
catch(otl_exception& p)
{
cerr << string( (const char*)p.msg + string(p.stm_text) + string(p.var_info)) << endl;
return -1;
}
return 0;
}
哎,果然。静态变量os光做了open,没有close,结果导致游标打开持续增长。好了,总算问题找到了,伙计,赶紧改程序吧。
希望还能过好年。