我最近才开始学习oci,看到有关多线程的部分时对于多线程情况下的mode参数设置有些疑问.
1.在 Oracle Call Interface Programmer's Guide 中这样写"In order to take advantage of thread safety, an application must be running on a thread-safe platform. Then the application must tell the OCI layer that theapplication is running in multithreaded mode, by specifying OCI_THREADED for the mode parameter of the opening call to OCIEnvCreate()."也就是说在多线程的程序中需要用OCI_THREADED.
2.而在oci本身自带的Multi-threading example中却是用OCI_DEFAULT
调用的OCIEnvCreate().
3.在文档中关于environment的mutex保护又有这样一段话
"The following three scenarios are possible, depending on how many connections exist in each environment handle, and how many threads will be spawned in each connection
1.If an application has multiple environment handles, but each only has one thread (one session exists in each environment handle), no mutexing is required.
2.If an application running in OCI_THREADED mode maintains one or more environment handles, each of which has multiple connections, it also has the following options:
Pass a value of OCI_NO_MUTEX for the mode of OCIEnvCreate(). In this case the application must mutex OCI calls by made on the same environment handle itself. This has the advantage that the mutexing scheme can be optimized based on the application design. The programmer must also insure that only one OCI call is in process on the environment handle connection at any given time.
Pass a value of OCI_DEFAULT to OCIEnvCreate(). In this case, the OCI library automatically gets a mutex on every OCI call on the same environment handle."
结合 2,3小第猜想假如在多线程的情况下假如每个env只包含一个数据库的连接,则不需要使用OCI_THREADED 来调用OCIEnvCreate().假如每个env包含多于一个的数据库连接则需要OCI_THREADED.
因为我刚开始看oci的东西,所以还没有写过半程序来测试,希望有相关经验的大侠拔刀相助.
希望感爱好的人一起研究一下.要试这个问题首先要写连接程序,我用c++写了简单的连接类现在已经调试通过了,写的匆忙没有什么错误控制代码.贴出来给大家讨论,因为我是第一次写所以肯定有不少问题,现在也是没有办法啊.希望大侠出现啊.
h file
#ifndef __ORACONNECT_H__
#define __ORACONNECT_H__
#include
extern "C"
{
sWord OCIEnvCreate (OCIEnv **envp, ub4 mode, dvoid *ctXP,
dvoid *(*malocfp)(dvoid *ctxp, size_t size),
dvoid *(*ralocfp)(dvoid *ctxp, dvoid *memptr, size_t newsize),
void (*mfreefp)(dvoid *ctxp, dvoid *memptr),
size_t xtramem_sz, dvoid **usrmempp);
}
class OraConnect
{
public:
OraConnect();
~OraConnect();
bool Connect();
bool DisConnect();
void setUsername(char* strusername);
void setPassword(char* strpassword);
void setDbname(char* strdbname);
void checkerr(OCIError *errhp,sword status);
protected:
private:
char username[128];
char password[128];
char dbname[128];
//Set the OCI variable
OCIEnv *envhp;
OCIError *errhp;
OCISession *authp;
OCIServer *srvhp;
OCISvcCtx *svchp;
};
#endif
.cpp file
#include "StdAfx.h"
#include "Connect.h"
OraConnect::OraConnect()
{
}
OraConnect::~OraConnect()
{
}
void
OraConnect::setUsername(char* strusername)
{
strcpy(username,strusername);
}
void
OraConnect::setPassword(char* strpassword)
{
strcpy(password,strpassword);
}
void
OraConnect::setDbname(char* strdbname)
{
strcpy(dbname,strdbname);
}
bool
OraConnect::Connect()
{
ub4 mode = OCI_SHAREDOCI_THREADED;
//ub4 mode=OCI_DEFAULT;
//Create the envirnment.
//(void) OCIEnvCreate(&envhp, mode, (CONST dvoid *)0, 0, 0, 0, (size_t)0, (dvoid **)0);
(void) OCIInitialize((ub4) OCI_DEFAULT, (dvoid *)0,(dvoid * (*)(dvoid *, size_t)) 0,(dvoid * (*)(dvoid *, dvoid *, size_t))0,(void (*)(dvoid *, dvoid *)) 0 );
(void) OCIEnvInit( (OCIEnv **) &envhp, OCI_DEFAULT, (size_t) 0,(dvoid **) 0 );
//Allocate the handle
(void) OCIHandleAlloc( (dvoid *) envhp, (dvoid **) &errhp, OCI_HTYPE_ERROR,(size_t) 0, (dvoid **) 0);
(void) OCIHandleAlloc( (dvoid *) envhp, (dvoid **) &srvhp, OCI_HTYPE_SERVER,(size_t) 0, (dvoid **) 0);
(void) OCIHandleAlloc( (dvoid *) envhp, (dvoid **) &svchp, OCI_HTYPE_SVCCTX,(size_t) 0, (dvoid **) 0);
//Set the db link name.
(void) OCIServerAttach( srvhp, errhp, (text *)dbname, strlen(dbname), 0);
/* set attribute server context in the service context */
(void) OCIAttrSet( (dvoid *) svchp, OCI_HTYPE_SVCCTX, (dvoid *)srvhp,(ub4) 0, OCI_ATTR_SERVER, (OCIError *) errhp);
(void) OCIHandleAlloc((dvoid *) envhp, (dvoid **)&authp,(ub4) OCI_HTYPE_SESSION, (size_t) 0, (dvoid **) 0);
(void) OCIAttrSet((dvoid *) authp, (ub4) OCI_HTYPE_SESSION,(dvoid *) username, (ub4) strlen((char *)username),(ub4) OCI_ATTR_USERNAME, errhp);
(void) OCIAttrSet((dvoid *) authp, (ub4) OCI_HTYPE_SESSION,(dvoid *) password, (ub4) strlen((char *)password),(ub4) OCI_ATTR_PASSWORD, errhp);
checkerr(errhp, OCISessionBegin ( svchp, errhp, authp, OCI_CRED_RDBMS,
(ub4) OCI_DEFAULT));
(void) OCIAttrSet((dvoid *) svchp, (ub4) OCI_HTYPE_SVCCTX,(dvoid *) authp, (ub4) 0,(ub4)OCI_ATTR_SESSION, errhp);
return true;
}
bool
OraConnect:isConnect()
{
if (errhp)
(void) OCIServerDetach( srvhp, errhp, OCI_DEFAULT );
if (srvhp)
checkerr(errhp, OCIHandleFree((dvoid *) srvhp, OCI_HTYPE_SERVER));
if (svchp)
(void) OCIHandleFree((dvoid *) svchp, OCI_HTYPE_SVCCTX);
if (errhp)
(void) OCIHandleFree((dvoid *) errhp, OCI_HTYPE_ERROR);
if(envhp)
(void) OCIHandleFree((dvoid *) envhp, OCI_HTYPE_ENV);
return true;
}
void
OraConnect::checkerr(OCIError *errhp,sword status)
{
text errbuf[512];
sb4 errcode = 0;
switch (status)
{
case OCI_SUCCESS:
break;
case OCI_SUCCESS_WITH_INFO:
(void) printf("Error - OCI_SUCCESS_WITH_INFO\n");
break;
case OCI_NEED_DATA:
(void) printf("Error - OCI_NEED_DATA\n");
break;
case OCI_NO_DATA:
(void) printf("Error - OCI_NODATA\n");
break;
case OCI_ERROR:
(void) OCIErrorGet((dvoid *)errhp, (ub4) 1, (text *) NULL, &errcode,
errbuf, (ub4) sizeof(errbuf), OCI_HTYPE_ERROR);
(void) printf("Error - %.*s\n", 512, errbuf);
break;
case OCI_INVALID_HANDLE:
(void) printf("Error - OCI_INVALID_HANDLE\n");
break;
case OCI_STILL_EXECUTING:
(void) printf("Error - OCI_STILL_EXECUTE\n");
break;
case OCI_CONTINUE:
(void) printf("Error - OCI_CONTINUE\n");
break;
default:
break;
}
}
在调试中反而发现了一个怪问题,当我的mode设置成OCI_SHAREDOCI_THREADED,用OCIEnvCreate调用会crash,不过假如单用OCI_SHARED或OCI_THREADED就不会有问题,假如用
OCIInitialize和OCIEnvInit来替代OCIEnvCreate则没有什么问题,不过我觉得是我自己的编译参数不太对吧.我的环境是(oracle8.1.7,windows2000 professional,vc6(sp5)).
调用代码.
OraConnect conn[10];
for(int i=0;i
{
conn[i].setUsername("skyems");
conn[i].setPassword("skyems");
conn[i].setDbname("skydb");
conn[i].Connect();
}
for(int j=0;j
{
conn[j].DisConnect();
}
试了试,应该是没什么问题的.试了试,应该是没什么问题的.h file中的extern声明是因为oci是个c接口