UNIX下的线程与ORACLE数据库的连接问题,在线等待!!

发表于:2007-05-25来源:作者:点击数: 标签:数据库oracleUnix问题线程
我用 UNIX 下的多线程访问ORACLE 数据库 ,出现了一些问题请大家帮忙。 在主线程中创建数据库连接,子线程可以共享此连接对数据库进行访问。 但是我想让数据库连接在子线程中创建,通过日志查看connect已经成功, 但是select一个表中的数据则报告错误代码为1

我用UNIX下的多线程访问ORACLE数据库,出现了一些问题请大家帮忙。
在主线程中创建数据库连接,子线程可以共享此连接对数据库进行访问。
但是我想让数据库连接在子线程中创建,通过日志查看 connect 已经成功,
但是 select 一个表中的数据则报告错误代码为 1012的信息(数据库没有连接的错误)。请问各位谁能帮忙解决此问题,谢谢!!

 deathbravo 回复于:2003-07-24 12:28:46
有没有use context呀?
子线程里是不是默认使用default的context;
另外请告诉我你的程序的访问速度好吗

 wlkwlk 回复于:2003-07-24 12:38:21
我有用 context 但是不行,我是在UNIXWARE 上编译的,我将代码贴上,请帮忙看一看,怎样才能实现。谢谢。。。
#include <string.h>
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include        <stdlib.h>
#include        <errno.h>
#include        <sys/errno.h>
#include        <math.h>
#include        <time.h>
#include        <varargs.h>
#include        <sys/time.h>
#include        <sqlda.h>
#include        <sqlcpr.h>
#include        <sqlca.h>
#include        <oraca.h>


EXEC SQL BEGIN DECLARE SECTION;
        sql_context     envtext;
EXEC SQL END DECLARE SECTION;

/* 连接ORACLE数据库*/
int connectoracle()
{
EXEC SQL BEGIN DECLARE SECTION;
        char    userid[40];
        char    passid[40];
int intfilename=0;
EXEC SQL END DECLARE SECTION;

        strcpy(userid , "datalook");
        strcpy(passid , "datalook");

        EXEC SQL CONNECT :userid IDENTIFIED BY :passid;
        EXEC SQL CONTEXT ALLOCATE :envtext;
        EXEC SQL CONTEXT USE :envtext;

        if(sqlca.sqlcode!=0)
        {
                printf("连接失败 sqlcode=[%d]\n",sqlca.sqlcode);
                return(-1);
        }
printf("Oracle Connect Sucess!!!\n");
EXEC SQL SELECT FILENAME 
INTO :intfilename FROM SYS_TMP;
printf("sqlca.sqlcode =[%d]\n",sqlca.sqlcode);
printf("intfilename =[%d]\n",intfilename);
return(0);
}
void FreeConText()
{
        EXEC SQL CONTEXT FREE :envtext;
}
/* Set specify thread stack size */
int SetThreadStackSize(pthread_attr_t *Attr_t,int stacksize)
{
pthread_attr_t  thread_attr;
size_t  stack_size;
int     retcode=0;

        retcode=pthread_attr_init(&thread_attr);
        if(retcode)
        {
                printf("pthread_attr_init\n");
                return(retcode);
        }
        retcode=pthread_attr_getstacksize(&thread_attr,&stack_size);
        if(retcode)
        {
                printf("pthread_attr_getstacksize\n");
                return(retcode);
        }
        retcode=pthread_attr_setstacksize(&thread_attr,stack_size*100);
        if(retcode)
        {
                printf("pthread_attr_setstacksize\n");
                return(retcode);
        }
        memcpy((char *)Attr_t,(char *)&thread_attr,sizeof(pthread_attr_t));
return(0);
}
void *firstthread(void *param)
{
int retcode=0;
pthread_t conid;
int memlen=0;
pthread_attr_t  attr_val;

retcode= connectoracle();
FreeConText();
printf("firstthread is over..!!!\n");
return(0);
}

int main()
{
int retcode=0;
pthread_t conid;
int memlen=0;
pthread_attr_t  attr_val;

memlen=100*16000;
SetThreadStackSize(&attr_val,memlen);
retcode=pthread_create(&conid,&attr_val,firstthread,(void *)NULL);
if(retcode)
{
printf("create  ConSumeThread is error [%d]\n",retcode);
perror("error");
return(-1);
}

retcode=pthread_join(conid,NULL);
if(retcode)
{
printf("pthread_join is error [%d]\n",retcode);
perror("error");
return(-1);
}
printf("主线程退出!!!\n");
return(0);
}

 wlkwlk 回复于:2003-07-24 12:44:10
我采用的是子线程调度 动态库的形式。
数度大概在每分钟 3000-4000笔左右。

 deathbravo 回复于:2003-07-24 13:07:49
EXEC SQL CONTEXT USE :envtext; 
应该在connect之前呀;
要不然你连接的就是default;
envtext的环境里就是未连接的;

 wlkwlk 回复于:2003-07-24 13:18:29
非常感谢,我试了一下,还请问一下,如果在子线程里创建连接,context 变量 envtext 是否必须定义为全局变量。

 deathbravo 回复于:2003-07-24 13:25:25
不必;
但是这个连接只能在子线程内部使用;
子线程结束就释放掉;

可是我觉得这样开销比较大呀;
我是在主线程里建立了一个context池;
可是速度并不比你得快多少;每分钟也就7000到8000比;
最高不超过10000;
你如果发现什么提高速度的窍门,请一定告诉我;

 wlkwlk 回复于:2003-07-24 13:39:18
以前我也是采用在主线程建立连接,然后子线程直接共享主线程的连接对DB进行操作,但是如果两个子线程同时对DB进行操作则会 Core 程序崩溃 ,而且我建立的子线程是守候线程,不会退出,所有我需要为每个子线程创建一个context池。速度我也在通过各种方式优化。如有大的提高我会通知您的。

 wlkwlk 回复于:2003-07-24 14:03:30
/* 此函数在子线程中被调用 */
int contest()
{
EXEC SQL BEGIN DECLARE SECTION;
 int     intfilename=0;
EXEC SQL END DECLARE SECTION;

 EXEC SQL SELECT FILENAME INTO :intfilename FROM SYS_TMP;
 printf("in contest sqlca.sqlcode=[%d]\n",sqlca.sqlcode);
 printf("in contest intfilename  =[%d]\n",intfilename);
return(0);
/* 子线程 */
void *firstthread(void *param)
{
EXEC SQL BEGIN DECLARE SECTION;
 char    userid[40];
 char    passid[40];
 char    currdate[40];
 int     intfilename=0;
 sql_context     envtext;
EXEC SQL END DECLARE SECTION;

        strcpy(userid , "datalook");
        strcpy(passid , "datalook");

        EXEC SQL CONTEXT ALLOCATE :envtext;
        EXEC SQL CONTEXT USE :envtext;
        EXEC SQL CONNECT :userid IDENTIFIED BY :passid;
        if(sqlca.sqlcode!=0)
        {
                printf("连接失败 sqlcode=[%d]\n",sqlca.sqlcode);
                return;
        }
        printf("Oracle Connect Sucess!!!\n");
        EXEC SQL SELECT FILENAME INTO :intfilename FROM SYS_TMP;
        printf("sqlca.sqlcode   =[%d]\n",sqlca.sqlcode);
        printf("intfilename     =[%d]\n",intfilename);
        EXEC SQL SELECT TO_CHAR(SYSDATE,'YYYYMMDDHH24MISS') INTO :currdate
                FROM SYS_TMP;
        currdate[14]=0;

        contest();
        printf("contest is over...........\n");

        EXEC SQL CONTEXT FREE :envtext;
return(0);
}
此代码执行以后报告 函数contest 不能连接数据库,麻烦请看一看。谢谢!!

 deathbravo 回复于:2003-07-24 14:09:56
调用contest 时需要把envtext作为参数传给它;
然后在contest 内部所有SQL语句前面加上
EXEC SQL CONTEXT USE :xxxxxxx; 

不然contest 内部的嵌入SQL会使用default context;

 jsean 回复于:2003-07-24 21:46:23
问一下,这是pro*c编程吗?

 蓝色键盘 回复于:2003-07-25 09:56:13
嗯,不错,偶觉得论坛中讨论的气氛现在很好。

楼上两位讨论的很好!

 wlkwlk 回复于:2003-07-25 11:27:46
[quote:70dc671568="jsean"]问一下,这是pro*c编程吗?[/quote:70dc671568]     
是的。

 wlkwlk 回复于:2003-07-25 11:30:53
deathbravo   您好,我的问题已经解决,我用的是ORACLE默认的连接池。再次感谢你的帮助。
现在我在测试性能,如果有比较大的提高我会通知的。

 deathbravo 回复于:2003-07-25 11:39:47
共同进步,静候佳音

 xasun 回复于:2003-07-28 15:19:07
能否告诉我你的proc程序的运行环境?

 bjf 回复于:2003-11-28 10:13:07
如果一个进程创建了一个以上的线程,这些线程都要独占一个连接,并行地去访问数据库,这样做还行吗?我也正在为此事烦恼呢。

 lihuabo 回复于:2004-05-17 13:43:55
我的问题更加郁闷.(导师要我解决的)我用一个线程建立连接后,循环访问数据库,如果在此时网线断掉,那么线程将会阻塞,怎么也动不了.应该怎么解决??

原文转自:http://www.ltesting.net

评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)