解决方案 »
- oracle10g ome无法通过网页启动
- 祝Oracle版的网友们端午节快乐!顺便作个咨询调查。 :-)
- oracle developer 开发,急急!!
- 无效的rowid错误,在线等.急
- 在jbuilder中引用oracle.sql.*,oracle.jdbc.*有问题????
- 关于exists
- 错误ora-00904
- Oracle中date数据类型的问题(程序里输入的和数据库里显示的不同)
- 求救!启动不了enterprise manager console,总是一闪而过……
- 弱水三千进来!!!!请教你点问题!!!!考勤系统的开发(用oracle做数据库)
- 连接oracle出现“未发现Oracle(tm)客户端和网络组件”,求高手
- oracle 函数 挑战
oracle文档里面关于连接池提到:
thread1()
{
EXEC SQL CONTEXT ALLOCATE :ctx1;
EXEC SQL CONNECT :uid AT :TC1 USING :db_string;
...
}
thread2()
{
EXEC SQL CONTEXT ALLOCATE :ctx2;
EXEC SQL CONNECT :uid AT :TC2 USING :db_string;
...
}
thread3()
{
EXEC SQL CONTEXT ALLOCATE :ctx3;
EXEC SQL CONNECT :uid AT :TC3 USING :db_string;
EXEC SQL AT :TC3 SELECT count(*) into :count FROM emp;
...
}
thread4()
{
EXEC SQL CONTEXT ALLOCATE :ctx4;
EXEC SQL CONNECT :uid AT :TC4 USING :db_string;
...
}
这些线程的连接还有会话怎么回收呢?
http://wenku.baidu.com/view/e3f0114bcf84b9d528ea7aed.html
oracle的pro*c/c++ procompiler A97269文档有关多线程、连接池的内容也被我翻来覆去看了好多遍,头都大了。到底怎么配置怎么编码讲的不全,按我的理解加上连接池,会话、连接都不受控制。
我用的解决方案是这样的,首先还是用编译参数
proc db_fun.pc THREADS=YES CPOOL=YES CMAX=5 CMIN=1 CINCR=2
控制连接数,然后每次初始化一定数量的sql_context存放到空闲池,每次需要使用数据库操作时从空闲池取,用完又放进空闲池。每一个sql_context会产生一个会话,每个线程如果都新建一个sql_context然后按照顶楼代码那样,数据库资源需要等待进程结束时才真正释放,这样处理就就会看到会话越来越多,直到数据库会话限制。部分代码如下,请指正:
/******************************************************************************
* 函 数 名:ConnectDatabase
* 编写日期:2010.09
* 函数功能:根据配置文件中连接池连接数建立程序与ORACLE的连接池
* 输入说明:
* 返 回 值:0:连接成功, -1:连接失败
* 修改记录:
* 注意事项:
*******************************************************************************/
int ConnectDatabase( char *azp_UserName, /*用户名*/
char *azp_Password, /*密码*/
char *azp_DbString, /*DB连接串*/
int azp_dbcpool /*db连接池连接数*/
)
{
struct sqlca sqlca;
EXEC SQL ENABLE THREADS; /* 初始化数据库上下文池 */
int i = 0;
while(i < azp_dbcpool)
{
sql_context* sql_ctx = malloc(sizeof(sql_context)); EXEC SQL CONTEXT ALLOCATE :*sql_ctx;
EXEC SQL CONTEXT USE :*sql_ctx;
EXEC SQL WHENEVER SQLERROR DO SqlError(sqlca.sqlerrm.sqlerrmc); printf("begin to connect database [%s/%s@%s]........", azp_UserName, azp_Password, azp_DbString);
EXEC SQL CONNECT :azp_UserName IDENTIFIED BY :azp_Password AT db_name USING :azp_DbString; if (sqlca.sqlcode != 0)
{
printf("Can't Connect to %s!\n", azp_DbString);
return -1;
}
else
{
printf("OK!\n");
} /* 将初始化完成的上下文保存到空闲上下文链表 */
add_free_node(sql_ctx); i++;
} /*Create mutex for transaction retrieval */
if (pthread_mutex_init(&mutex,NULL))
{
printf("Can't initialize mutex\n");
return -1;
}
return 0;
}/******************************************************************************
* 函 数 名:free_sqlctx_list
* 编写日期:2010.09
* 函数功能:释放数据库上下文空闲队列,回收数据库资源
* 输入说明:
* 返 回 值:
* 修改记录:
* 注意事项:
*******************************************************************************/
int free_sqlctx_list()
{
while(NULL != p_free_ctx_head)
{
FREE_NODE* p_tmp = p_free_ctx_head;
p_free_ctx_head = p_free_ctx_head->p_next; EXEC SQL CONTEXT USE :*(p_tmp->ctx); printf("free database connect[%d]........", free_sql_ctx_count);
EXEC SQL AT db_name COMMIT WORK RELEASE;
if( sqlca.sqlcode != 0)
printf("cant disconnect!\n");
else
printf("disconnect!\n"); printf("free sql_context[%d]........",free_sql_ctx_count--);
EXEC SQL CONTEXT FREE :*(p_tmp->ctx);
if( sqlca.sqlcode != 0)
printf("cant free sql_context!\n");
else
printf("free sql_context!\n"); free(p_tmp->ctx);
p_tmp->ctx = NULL;
free(p_tmp);
p_tmp = NULL;
} return 0;
}/******************************************************************************
* 函 数 名:add_free_node
* 编写日期:2010.09
* 函数功能:增加一个空闲的数据库上下文到空闲队列
* 输入说明:
* 返 回 值:
* 修改记录:
* 注意事项:
*******************************************************************************/
void add_free_node(sql_context* ctx)
{
if (pthread_mutex_lock(&mutex))
printf("Can't lock mutex\n"); FREE_NODE* p_tmp = malloc(sizeof(FREE_NODE));
memset(p_tmp,0x00,sizeof(FREE_NODE));
p_tmp->ctx = ctx;
p_tmp->p_next = p_free_ctx_head; p_free_ctx_head = p_tmp; free_sql_ctx_count++; #if TEST
printf("======================================增加空闲上下文,目前空闲总数量[%d]\n",free_sql_ctx_count);
#endif if (pthread_mutex_unlock(&mutex))
printf("Can't unlock mutex\n"); return;
}/******************************************************************************
* 函 数 名:get_free_node
* 编写日期:2010.09
* 函数功能:从空闲队列获取一个空闲的数据库上下文
* 输入说明:
* 返 回 值:
* 修改记录:
* 注意事项:
*******************************************************************************/
sql_context* get_free_node()
{
if (pthread_mutex_lock(&mutex))
printf("Can't lock mutex\n"); sql_context* ctx_return = NULL; FREE_NODE* p_tmp = p_free_ctx_head;
if (p_free_ctx_head != NULL)
{
ctx_return = p_free_ctx_head->ctx;
p_free_ctx_head = p_free_ctx_head->p_next; free(p_tmp);
p_tmp = NULL; free_sql_ctx_count--;
} #if TEST
printf("======================================获取空闲上下文,目前空闲总数量[%d]\n",free_sql_ctx_count);
#endif if (pthread_mutex_unlock(&mutex))
printf("Can't unlock mutex\n"); return ctx_return;
}
/******************************************************************************
* 函 数 名:select_base_info
* 编写日期:2009.8
* 函数功能:实际业务
* 输入说明:
* 返 回 值:0:成功, -1:失败
* 修改记录(如果有)
* 注意事项:
*******************************************************************************/
int select_base_info(STRU_MSG *asp_recv_msg,STRU_MSG *asp_send_msg,STRU_PARAM *asp_Param)
{
struct sqlca sqlca; sql_context* ctx = get_free_node();
if (NULL == ctx)
{
sprintf(asp_send_msg->datatrans,"0001%-64s","内部错误,系统正忙");
return(-1);
} EXEC SQL CONTEXT USE :*ctx; EXEC SQL AT db_name ……; add_free_node(ctx);
return(0);
}
相应结构
/*空闲数据库上下文队列节点*/
typedef struct
{
sql_context * ctx;
struct FREE_NODE* p_next;
} FREE_NODE;/*空闲数据库上下文队列头指针*/
FREE_NODE* p_free_ctx_head = NULL;
/*空闲数据库上下文队列计数*/
int free_sql_ctx_count = 0;
pthread_mutex_t mutex;
关于连接池为什么进程退出才释放连接,我感觉是oracle配置问题,网上有类似的帖子!!!
#include <sqlda.h>
#include <sqlcpr.h>
#include <OCI.h>#define NUM 100class StdDBClass
{
public:
EXEC SQL BEGIN DECLARE SECTION;
sql_context ctx[100];
EXEC SQL END DECLARE SECTION; StdDBClass()
{
} ~StdDBClass()
{
} void UseThread()
{
EXEC SQL ENABLE THREADS;
}
void Allocate()
{
for(int i=0; i<NUM; ++i)
{
EXEC SQL CONTEXT ALLOCATE :ctx[i];
}
}
int OpenDB(const char* usr, const char* pwd,const char* szServerName, sql_context ctx)
{
EXEC SQL BEGIN DECLARE SECTION;
char username[64];
char passwd[64];
char server[64];
EXEC SQL END DECLARE SECTION;
strcpy(username,usr);
strcpy(passwd,pwd);
strcpy(server,szServerName);
struct sqlca sqlca;
EXEC SQL CONTEXT USE :ctx;
EXEC SQL CONNECT :username IDENTIFIED BY :passwd USING :server;
if (sqlca.sqlcode != 0)
{
printf( "连接oracle数据库失败!");
return -1;
}
return 0;
} int CloseDB(sql_context ctx)
{
struct sqlca sqlca;
EXEC SQL CONTEXT USE :ctx;
EXEC SQL COMMIT WORK RELEASE;
EXEC SQL CONTEXT FREE :ctx;
if( sqlca.sqlcode != 0 )
{
printf( "断开数据库连接失败!%d:%s\n",sqlca.sqlcode,sqlca.sqlerrm.sqlerrmc );
return -1;
}
return 0;
}
void Free()
{
for(int i=0; i<NUM; ++i)
{
EXEC SQL CONTEXT FREE :ctx[i];
}
}
...
};
这样是可行的,但是我不想每个函数都定义一个struct sqlca sqlca;所以就将线程主函数的定义的sqlca给当成指针传入其他函数了,所以其他函数在使用sqlca的时候是sqlca->sqlcode; 使用printf是可以正常打印的的,但是一旦执行了EXEC SQL ~~~的语句,程序立即崩溃,请问各位大侠遇见过吗?!