小弟刚开始接触ProC ,经验不足,使用时发现如下问题,恳请前辈指点迷津!!!先行谢过!!!
目的:
    在主程序中一次性建立多个oracle连接,然后在fork的子程序中多次使用,有点象缓冲池。程序中用信号灯来保证一个连接同时只有一个子程序在用。(仅是想法,未证实是否可行,所以写了下面的测试程序进行摸索。)
问题:
    小弟写了如下测试程序,这个测试程序没有更多信号灯控制,但加了sleep延时,来保证同时只有一个子程序在用这个连接。程序只执行一个select操作,耗时极短。
    在运行的时候发现,如果连续fork50个以上的子进程(有延时)时,就会发生-1000错误,说是游标打开太多。
 
ORA-01000 maximum open cursors exceeded  
Cause:
        A host language program attempted to open too many cursors. The initialization parameter OPEN_CURSORS determines the maximum number of cursors per user.  
Action:
     Modify the program to use fewer cursors. If this error occurs often, shut down Oracle, increase the value of OPEN_CURSORS, and then restart Oracle.  
        
         子程序里我也只是执行了一个SELECT而已,还有什么地方没释放完整嘛??
    我对Oracle也是新手,所以如果问的傻了,还请前辈多多批评!
    现在我的测试就被卡在这里了,请教各位前辈指点一下啊!!
是不是需要在子进程里进行一些处理??
    或者这样做压根不行?但在Unix ,Pro C下如何实现数据库连接缓冲池呢?
    请教!!!!请各位帮忙顶一下!!谢谢!!!下面附上完整的测试程序代码:[CODE]
#include <stdio.h>
#include <stdarg.h>#define DEBUGEXEC SQL INCLUDE sqlca;
EXEC SQL INCLUDE oraca;void DebugPrt(char * fmt,...);
int ora_connect(void);
int ExecuteSql(int ID,char * atConn);EXEC SQL BEGIN DECLARE SECTION;
char Conn_Name[15];
EXEC SQL END DECLARE SECTIOn;
int main(int argc, char *argv[])
{
EXEC SQL BEGIN DECLARE SECTION;
char fid[15];
EXEC SQL END DECLARE SECTION; int pid,i,j; 
int forkCount; /*建立的子进程数*/
int flagExitMain=0; /*主进程是否等待再退出*/ if (argc<2)
{
forkCount = 5;
}
else
{
forkCount = atoi(argv[1]);
}
if (forkCount<1)
{
forkCount =1 ;
}
if (argc>2)
{
flagExitMain = atoi(argv[2]);
} strcpy(Conn_Name,"conn"); /*连接名字*/
ora_connect(); /*连接数据库*/
for (i=0;i<forkCount ;i++ )
{
if (pid = fork()>0)
{
/*主进程*/
}
else if (pid ==0)
{
/*子进程*/
printf("pid=%d\n",getpid());
ExecuteSql(i,Conn_Name);
exit(0);
}
else
{
DebugPrt("fork error [%d]",pid);
}
sleep(1);
} printf("Main Proc Exit================= \n"); ora_disconnect();
exit(0);
}int ExecuteSql(int ID,char * atConn)
{
char fid[41];
DebugPrt("[%d] ",ID);
EXEC SQL AT :atConn SELECT oper_name INTO :fid  FROM clerk_info \
WHERE  oper_id = '999999999999999999'; 
if (sqlca.sqlcode<0)
{
DebugPrt("[%s]select error [%s][%d]----------------\n",atConn,fid,sqlca.sqlcode);
}
else
DebugPrt("[%s] >=[%d][%s][%d]\n",atConn,ID,fid,sqlca.sqlcode);
}int ora_connect(void)
{
EXEC SQL BEGIN DECLARE SECTION;
char username[60];
char password[20+1];
int  ret;
char db_name[20];
EXEC SQL END DECLARE SECTION; strcpy(db_name,"rising"); /*数据库服务*/
strcpy(username,"fpuser"); /*用户名*/
strcpy(password,"sy"); /*密码*/ EXEC SQL CONNECT :username IDENTIFIED BY :password \
AT :Conn_Name USING :db_name;
if(sqlca.sqlcode<0) 
{
DebugPrt("connect Error[%s][%d]\n",username,sqlca.sqlcode);
return(-1);
}
else
{
DebugPrt("connect OK ... [%s][%d]\n",Conn_Name,sqlca.sqlcode);
}
return(0);
}int ora_disconnect(void)
{
EXEC SQL AT :Conn_Name COMMIT WORK RELEASE;
DebugPrt("disconnect OK ... [%s][%d]\n",Conn_Name,sqlca.sqlcode);
return sqlca.sqlcode;
}
void DebugPrt(char * fmt,...)
{
#ifdef DEBUG
va_list argp; 
va_start( argp, fmt ); 
vprintf(fmt,argp);
va_end( argp); 
#endif
}[/CODE]

解决方案 »

  1.   

    思路应该可以吧,我在c++下,用多个线程没问题,如果是多个进程要考虑oracle的连接数
      

  2.   

    连接数不大啊。我用这个程序测试同时才两个连接,一直使用前一个,这是如果fork到第50个子进程,连接在执行就出错了。提示游标达到最大数量。
      

  3.   

    同一个进程里面,同一个连接名即使多次连接,也使用的是同一session,所以你线程多了,自然就达到游标数上限了。用Pro*C开发多线程应用程序 (注:本文来自Pro*C/C++ Precompiler Programmer's Guide Release 8.1.5)  这是一篇网上使用context实现多线程的文章。 测试时可用,但是在应用时出现泄漏,也没有查出原因来。另外你可以使用Multiple Explicit Connections ,就是在同一进程中使用不同的连接名,连接名是连接数据库时at字句后使用的名字,这样建立的就是多连接,不过我只是测试过,没有做过应用。不知道楼主有没有其他proc连接池方面的资料。
      

  4.   

    我上面用的是fork子进程来测试的,另外主进程延时了一秒,所以这时子进程应该已经退出执行了,
    这时游标是不是该关闭了呢?另外,我用sql_context昨天也试了。也出现同样的问题。
    没有关于专讲连接池的资料啊。就是ProC编程的。
      

  5.   

    int ExecuteSql(int ID,char * atConn)
    {
    char fid[41];
    DebugPrt("[%d] ",ID);
    EXEC SQL AT :atConn SELECT oper_name INTO :fid  FROM clerk_info \
    WHERE  oper_id = '999999999999999999'; 
    if (sqlca.sqlcode<0)
    {
    DebugPrt("[%s]select error [%s][%d]----------------\n",atConn,fid,sqlca.sqlcode);
    }
    else
    DebugPrt("[%s] >=[%d][%s][%d]\n",atConn,ID,fid,sqlca.sqlcode);
    }这样写游标并没有释放吧.加一句commit看看
      

  6.   

    我加了commit试过,但还是不行的。不过问题还是解决了。EXEC SQL INCLUDE sqlca;
    EXEC SQL INCLUDE oraca;
    EXEC ORACLE OPTION (ORACA=YES);
    EXEC ORACLE OPTION (RELEASE_CURSOR=YES);   /*加上这个就解决了,自动释放游标*/谢谢 ks9960啊给分了。