以下是测试代码,程序运行一段时间以后就出现段错误,如果把OCILogon那一行代码注释起来就没事了。
这该如何解决呢?难道oracle就不支持在多线程里同时连接数据库。
#include <string.h>
#include <wchar.h>
#include <stdlib.h>#include <sys/types.h>
#include <sys/stat.h>#include <errno.h>
#include <pthread.h>
#include <signal.h>
#include <sys/time.h>
#include <semaphore.h>#include <iostream>
#include <string>
#include <map>using namespace std;#include <oci.h>
#pragma comment(lib,"libclntsh.so")bool g_flag = true;void * thread_func( void * lpParam )
{ sword status = -1; OCIEnv * envhp = NULL; // 环境句柄
OCIServer * svrhp = NULL; // 服务器句柄
OCIError * errhp = NULL; // 错误句柄
OCISvcCtx * svchp = NULL; // 服务上下文句柄 while( g_flag )
{
//printf( " prepare sleep = %u\n",&pid );
sleep( 1 ); // 创建OCI环境句柄
status = OCIEnvCreate(&envhp, OCI_DEFAULT, NULL, NULL, NULL, NULL, 0, NULL); 
if(status != OCI_SUCCESS && status != OCI_SUCCESS_WITH_INFO )
{
printf( "## OCIEnvCreate failed... ID = \n" );
}
// 分配服务器句柄
status = OCIHandleAlloc ((dvoid *)envhp, (dvoid **)&svrhp,OCI_HTYPE_SERVER, 0, (dvoid **) 0);
if(status != OCI_SUCCESS && status != OCI_SUCCESS_WITH_INFO )
{
printf( "## OCI_HTYPE_SERVER failed... ID = \n" );
}
// 分配错误句柄
status = OCIHandleAlloc ((dvoid *)envhp, (dvoid **)&errhp,OCI_HTYPE_ERROR, 0, (dvoid **) 0);
if(status != OCI_SUCCESS && status != OCI_SUCCESS_WITH_INFO )
{
printf( "## OCI_HTYPE_ERROR failed... ID = \n" );
}
// 分配服务上下文句柄
status = OCIHandleAlloc ((dvoid *)envhp, (dvoid **)&svchp,OCI_HTYPE_SVCCTX, 0, (dvoid **) 0);
if(status != OCI_SUCCESS && status != OCI_SUCCESS_WITH_INFO )
{
printf( "## OCI_HTYPE_SVCCTX failed... ID = \n" );
} char * username = "gagb";
char * password = "gagb";
char * conn = "(DESCRIPTION =(ADDRESS_LIST =(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.0.201)(PORT = 1521)) )(CONNECT_DATA = (SID = GAGB)))";
status = OCILogon( envhp,errhp,&svchp,(text *)username,(ub4)strlen(username),(text *)password,(ub4)strlen(password),(text *)conn,(ub4)strlen(conn) );
if(status != OCI_SUCCESS && status != OCI_SUCCESS_WITH_INFO )
{
printf( "## OCILogon failed... ID = %u\n",envhp );
}
else
{
sleep( 1 );
OCILogoff( svchp,errhp );
printf( "## OCILogon successed... ID = %u\n",envhp );
}
// 按照顺序依次释放相关句柄
// 释放服务上下文句柄
if( svchp != NULL )
{
OCIHandleFree(svchp, OCI_HTYPE_SVCCTX);
svchp = NULL;
}
// 释放错误句柄
if( errhp != NULL )
{
OCIHandleFree(errhp, OCI_HTYPE_ERROR);
errhp = NULL;
}
// 释放服务器句柄
if( svrhp != NULL )
{
OCIHandleFree(svrhp, OCI_HTYPE_SERVER);
svrhp = NULL;
}
// 释放OCI环境句柄
if( envhp != NULL )
{
OCIHandleFree(envhp, OCI_HTYPE_ENV);
envhp = NULL;
}
}
}void sigint_func( int signum );int main( int argc,char * argv[] )
{
signal( SIGINT,sigint_func );

int i;

pthread_t  pid[50];
for( i = 0; i < 50; i++ )
{
pthread_create( &pid[i],NULL,thread_func,(void*)0 );
} for( i = 0; i < 50; i++ )
{
pthread_join( pid[i],NULL );
} return 0;
}void sigint_func( int signum )
{
g_flag = false;
}

解决方案 »

  1.   

    如果我把OCILogon放在互斥锁中,保证同一时间只有一个线程能OCILogon,从测试情况来看,目前还没有问题。难道多线程里就不支持同时“OCILogon”?不科学啊,那如果我把多线程改成多进程,在多进程里OCILogon,和多线程同时OCILogon不是一个道理吗?总不能多进程也不能同时OCILogon吧?这个我还没有测试。
      

  2.   

    玩OCI的比较少,只能给点预测和建议。看症状来说应该是超过最大连接数了。测试下多进程是啥状况,因为就代码来看不存在自身资源独占问题。(OCILogon封装的看不到)
      

  3.   

    你看下当出现问题时进程有多少个,用LINUX下的进程查看命令,应该是不停的建立OCI没有释放(虽然你的代码里有释放,但很可能性没有真正释放或根本就没执行释放代码)
      

  4.   

    如果我把OCILogon放在互斥锁中,保证同一时间只有一个线程能OCILogon,从测试情况来看,目前还没有问题。也就是代码中修改一下:pthread_mutex_lock(&g_mutex);
    status = OCILogon( envhp,errhp,&svchp,(text *)username,(ub4)strlen(username),(text *)password,(ub4)strlen(password),(text *)conn,(ub4)strlen(conn) );
    pthread_mutex_unlock(&g_mutex);好了,没有问题了, 运行多久(测试的是连续运行大约12小时,而且加锁后从来没有发现过有出错的现象)也不会出现“段错误”。如果不加互斥代码的话基本上10分钟就崩了。难道OCILogon就不支持多线程同时调用?不科学啊。好歹也是ORACLE,知名的数据库产品啊。
      

  5.   

    我猜想有可能是我的引入库没有引入多线程版本的库导致的,但是在网上搜索也没有找到哪里有说ORACLE的多线程版本库有没有?是哪个?
      

  6.   

    我找到原因了,多线程下面要给创建环境句柄传入多线程模式的参数。如下:
    status = OCIEnvCreate(&envhp, OCI_DEFAULT, NULL, NULL, NULL, NULL, 0, NULL);结帖。