`
muscle-liu
  • 浏览: 230019 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

Pro*C 简单实现 Oracle 数据连接池

阅读更多
对于连接池的工作原理,我的一编转载有介绍:http://muscle-liu.iteye.com/admin/blogs/391916

利用Java/C++很容易实现。因项目需要,要用 C 实现。项目需求,这里我是实现连接Oracle的连接池。因为我用是 Pro*C 来写的(网上的人说这个相比 OCI 简单多),所以这个连接池是与 PL/SQL 来写的。

用 Proc*C 可以创建连接名来保存 Oracle connection(具体的 Proc*C 语法这里不介绍):
EXEC SQL CREATE DATABASE LINK link_name
	CONNECT uid IDENTIFIED BY pwd USING dbname;


对于如上述的 link_name 就是一个连接名。我的连接池里主要就是保存一定数量的连接名,每次要连接时就直接调用这些连接名。

而我的简单连接池实现原理如下:

      创建一个连接名结构体(包括名称、是否空闲),然后用一个循环链表来装载连接名。每次取一个空闲连接出来时,就按循环圈来搜索,当搜索到空闲连接就取出来,同时把它标识为忙碌。同理,当一个连接用完后,就把它标识为空闲就行了。
      当全部都是忙碌时,就设定一个时间timeout,继续循环。


缺点:这种实现方法连接数不能太大,太大循环占用时间很长。

追加一个功能: 在应用一个空闲连接时,自动判断它是否已断开,如是,就自动连上。

09/06/02 update
****************************************************************
经过几天研究,DATABASE LINK 保存的数据连接并不能很好的实现,反而通过 Runtime Contexts 可以实现保存一个连接的 session. 关于 Runtime Contexts 可以参考http://www.cs.umbc.edu/help/oracle8/server.815/a68022/threads.htm. 里边有个例子如下:
/*
 * Name:        Thread_example1.pc
 *
 * Description: This program illustrates how to use threading in
 *      conjunction with precompilers. The program creates as many
 *      sessions as there are threads. Each thread executes zero or
 *      more transactions, that are specified in a transient
 *      structure called 'records'.
 * Requirements:
 *      The program requires a table 'ACCOUNTS' to be in the schema
 *      scott/tiger. The description of ACCOUNTS is:
 *  SQL> desc accounts
 *   Name                            Null?    Type
 *  ------------------------------- -------  ------
 *  ACCOUNT                                  NUMBER(36)
 *  BALANCE                                  NUMBER(36,2)
 *
 *  For proper execution, the table should be filled with the accounts
 *      10001 to 10008.
 *
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sqlca.h>

#define      _EXC_OS_        _EXC__UNIX
#define      _CMA_OS_        _CMA__UNIX

#ifdef DCE_THREADS
  #include <pthread.h>
#else
  #include <thread.h>
#endif

/* Function prototypes */
void   err_report();
#ifdef DCE_THREADS
void   do_transaction();
#else
void   *do_transaction();
#endif
void   get_transaction();
void   logon();
void   logoff();

#define CONNINFO "scott/tiger"
#define THREADS  3 

struct parameters 
{ sql_context * ctx;
  int thread_id;
};
typedef struct parameters parameters;

struct record_log
{  char action;
   unsigned int from_account;
   unsigned int to_account;
   float  amount;
};
typedef struct record_log record_log;

record_log records[]= { { 'M', 10001, 10002, 12.50 },
                        { 'M', 10001, 10003, 25.00 },
                        { 'M', 10001, 10003, 123.00 },
                        { 'M', 10001, 10003, 125.00 },
                        { 'M', 10002, 10006, 12.23 },
                        { 'M', 10007, 10008, 225.23 },
                        { 'M', 10002, 10008, 0.70 },
                        { 'M', 10001, 10003, 11.30 },
                        { 'M', 10003, 10002, 47.50 },
                        { 'M', 10002, 10006, 125.00 },
                        { 'M', 10007, 10008, 225.00 },
                        { 'M', 10002, 10008, 0.70 },
                        { 'M', 10001, 10003, 11.00 },
                        { 'M', 10003, 10002, 47.50 },
                        { 'M', 10002, 10006, 125.00 },
                        { 'M', 10007, 10008, 225.00 },
                        { 'M', 10002, 10008, 0.70 },
                        { 'M', 10001, 10003, 11.00 },
                        { 'M', 10003, 10002, 47.50 },
                        { 'M', 10008, 10001, 1034.54}};

static unsigned int trx_nr=0;
#ifdef DCE_THREADS
pthread_mutex_t mutex;
#else
mutex_t mutex;
#endif



/*********************************************************************
 *  Main
 ********************************************************************/
main()
{
  sql_context ctx[THREADS];
#ifdef DCE_THREADS
  pthread_t thread_id[THREADS];
  pthread_addr_t status;
#else
  thread_t thread_id[THREADS];
  int status;
#endif
  parameters params[THREADS];
  int i;
  
  EXEC SQL ENABLE THREADS;

  EXEC SQL WHENEVER SQLERROR DO err_report(sqlca);

  /* Create THREADS sessions by connecting THREADS times */
  for(i=0;i<THREADS;i++)
  {
    printf("Start Session %d....",i);
    EXEC SQL CONTEXT ALLOCATE :ctx[i];
    logon(ctx[i],CONNINFO);
  }

  /*Create mutex for transaction retrieval */
#ifdef DCE_THREADS
  if (pthread_mutex_init(&mutex,pthread_mutexattr_default))
#else
  if (mutex_init(&mutex, USYNC_THREAD, NULL))
#endif
  {
     printf("Can't initialize mutex\n");
     exit(1);
  }

  /*Spawn threads*/
  for(i=0;i<THREADS;i++)
  {
    params[i].ctx=ctx[i];
    params[i].thread_id=i;

    printf("Thread %d... ",i);
#ifdef DCE_THREADS
    if (pthread_create(&thread_id[i],pthread_attr_default,
        (pthread_startroutine_t)do_transaction,
        (pthread_addr_t) &params[i]))
#else
    if (status = thr_create
    (NULL, 0, do_transaction, &params[i], 0, &thread_id[i]))
#endif
      printf("Cant create thread %d\n",i);
    else
      printf("Created\n");
  }


  /* Logoff sessions....*/
  for(i=0;i<THREADS;i++)
  {
     /*wait for thread to end */
     printf("Thread %d ....",i);
#ifdef DCE_THREADS
     if (pthread_join(thread_id[i],&status))
       printf("Error when waiting for thread % to terminate\n", i);
     else
      printf("stopped\n");

     printf("Detach thread...");
     if (pthread_detach(&thread_id[i]))
       printf("Error detaching thread! \n");
     else
       printf("Detached!\n");
#else
     if (thr_join(thread_id[i], NULL, NULL))
       printf("Error waiting for thread to terminate\n");
#endif
     printf("Stop Session %d....",i);
     logoff(ctx[i]);
     EXEC SQL CONTEXT FREE :ctx[i];
  }


  /*Destroys mutex*/
#ifdef DCE_THREADS
  if (pthread_mutex_destroy(&mutex))
#else
  if (mutex_destroy(&mutex))
#endif
  {
    printf("Can't destroy mutex\n");
    exit(1);
  }
}

/*********************************************************************
 * Function: do_transaction
 *
 * Description:  This functions executes one transaction out of the 
 *               records array. The records array is 'managed' by
 *               the get_transaction function.
 *
 *
 ********************************************************************/
#ifdef DCE_THREADS
void do_transaction(params)
#else
void *do_transaction(params)
#endif
parameters *params;
{
  struct sqlca sqlca;
  record_log *trx;
  sql_context ctx=params->ctx;

  /* Done all transactions ? */
  while (trx_nr < (sizeof(records)/sizeof(record_log)))
  {
    get_transaction(&trx);

    EXEC SQL WHENEVER SQLERROR DO err_report(sqlca);
    EXEC SQL CONTEXT USE :ctx;

    printf("Thread %d executing transaction\n",params->thread_id);
    switch(trx->action)
    {
      case 'M':  EXEC SQL UPDATE ACCOUNTS
                          SET    BALANCE=BALANCE+:trx->amount
                          WHERE  ACCOUNT=:trx->to_account;
                 EXEC SQL UPDATE ACCOUNTS
                          SET    BALANCE=BALANCE-:trx->amount
                          WHERE  ACCOUNT=:trx->from_account;
                 break;
       default:  break;
    }
    EXEC SQL COMMIT;
  }
}


/*****************************************************************
 * Function: err_report
 *
 * Description: This routine prints out the most recent error
 *
 ****************************************************************/
void      err_report(sqlca)
struct sqlca sqlca;
{
  if (sqlca.sqlcode < 0)
   printf("\n%.*s\n\n",sqlca.sqlerrm.sqlerrml,sqlca.sqlerrm.sqlerrmc);
  exit(1);
}

/*****************************************************************
 * Function: logon
 *
 * Description: Logs on to the database as USERNAME/PASSWORD
 *
 *****************************************************************/
void      logon(ctx,connect_info)
sql_context ctx;
char * connect_info;
{
    EXEC SQL WHENEVER SQLERROR DO err_report(sqlca);
    EXEC SQL CONTEXT USE :ctx;
    EXEC SQL CONNECT :connect_info;
    printf("Connected!\n");

}

/******************************************************************
 * Function: logoff
 *
 * Description: This routine logs off the database
 *
 ******************************************************************/
void      logoff(ctx)
sql_context ctx;
{
    EXEC SQL WHENEVER SQLERROR DO err_report(sqlca);
    EXEC SQL CONTEXT USE :ctx;
    EXEC SQL COMMIT WORK RELEASE;
    printf("Logged off!\n");
}


/******************************************************************
 * Function: get_transaction
 *
 * Description: This routine returns the next transaction to process
 *
 ******************************************************************/
void get_transaction(trx)
record_log ** trx;
{
#ifdef DCE_THREADS
  if (pthread_mutex_lock(&mutex))
#else
  if (mutex_lock(&mutex))
#endif
    printf("Can't lock mutex\n");

  *trx=&records[trx_nr];

  trx_nr++;

#ifdef DCE_THREADS
  if (pthread_mutex_unlock(&mutex))
#else
  if (mutex_unlock(&mutex))
#endif
    printf("Can't unlock mutex\n");
}
0
0
分享到:
评论

相关推荐

    linux下c/c++连oracle数据库技术pro*c

    在Linux环境下,C/C++程序员经常需要与Oracle数据库进行交互,以实现数据的存取、查询和其他操作。Pro*C是Oracle公司提供的一种预编译器,它允许C或C++程序直接调用PL/SQL代码,极大地简化了数据库操作。本篇文章将...

    [Oracle.11g.Pro﹡C.C.编程艺术].王海凤.扫描版

    通过对《Oracle 11g Pro*C/C++编程艺术》的学习,读者不仅可以提升数据库编程技能,还能深入了解Oracle 11g数据库的内部工作原理,从而更好地设计和实现高性能、高可用性的数据库应用系统。这本书是C/C++程序员在...

    Oracle Pro C文档.zip

    3. **数据类型**:介绍如何在C和Oracle数据类型之间进行转换,如`CHAR`、`NUMBER`、`DATE`等。 4. **错误处理**:如何使用Oracle的错误处理机制,如`OCIErrorGet`函数来获取和报告错误信息。 5. **游标操作**:...

    Pro﹡C编程艺术

    7. 高级特性:为了提高效率和灵活性,Pro*C还支持动态SQL、游标、事务处理、连接池等高级特性。这些内容对于希望深入学习Pro*C编程的读者而言是必不可少的。 8. 安全性和性能优化:在实际工作中,编写高效且安全的...

    ORACLE与C语言通用调用接口的实现.pdf

    总之,Oracle与C语言的通用调用接口是通过Oracle提供的接口工具,如PRO * C/C++和OCI,来实现对数据库的高效访问。选择合适的接口取决于具体项目的需求,如灵活性、性能和开发效率等因素。无论选择哪种方式,都能够...

    oracle instantclient12.1

    12.1版本的JDBC驱动支持JDBC 4.1规范,提供了更强大的功能,如连接池管理和数据源。 8. **TNS**: TNS是Oracle的网络服务,负责处理客户端和服务器之间的通信。12.1版本的TNS支持新的网络协议和服务发现,简化了多...

    Oracle Client 11 x64

    另外,可以通过调整连接池大小、预取行数等参数,优化客户端的性能和资源使用。 总的来说,Oracle Client 11 x64 是一个强大的数据库连接工具,它提供了丰富的功能和接口,使得开发者和DBA能有效管理和操作Oracle...

    PROC程序设计和ORACLE调用接口

    1. **Oracle调用接口(OCI)**:Oracle Call Interface (OCI) 是Oracle提供的一种C语言编程接口,允许开发者直接在C或C++程序中访问和操纵Oracle数据库。通过OCI,程序员可以实现数据的查询、插入、更新和删除,以及...

    ORACLE基础知识学习

    - OCI是Oracle提供的C语言API,用于编写应用程序访问Oracle数据库。 **4.2 SQL*Plus** - SQL*Plus是Oracle提供的命令行工具,用于执行SQL命令和脚本。 **4.3 Pro*C/C++编程** - Pro*C/C++是一种预编译器,它允许...

    基于嵌入式SQL的数据库连接池应用技术研究.pdf

    《基于嵌入式SQL的数据库连接池应用技术研究》探讨了在多层体系结构的应用程序环境中,如何通过数据库连接池技术提升系统性能和资源利用效率。本文主要关注的关键技术包括PL/SQL、多线程以及数据库连接池。 1. PL/...

    Oracle9I ProCC++编程指南

    书中会介绍Oracle的连接池技术,这是在多线程环境中管理数据库连接的有效手段,可以降低系统开销并提高资源利用率。 最后,书中可能会涉及Oracle的异常处理机制,这是处理数据库操作中可能出现错误的重要手段。C++...

    Unix下PROC开发ORACLE库的接口方法.pdf

    在Unix操作系统中,开发ORACLE数据库接口程序通常采用Pro*C/C++工具,这是一种将C或C++语言与SQL语句结合的编程方式,提供了高效、直接的数据访问手段。Oracle数据库以其强大的功能、良好的安全性和可移植性,深受...

    oracle_instanceclient_x64_11gR2_12cR1_12cR2_all_in_one

    这包括用于SQL*Plus、OCI (Oracle Call Interface)、OCCI (Oracle C++ Call Interface)、JDBC (Java Database Connectivity) 和 Pro*C/C++ 等工具和API的组件。 2. **11g R2**: Oracle Database 11g Release 2...

    oracle驱动包合集

    - 它使用Oracle的Pro*C预编译器将SQL语句嵌入到C/C++代码中,提供高性能的数据访问。 4. **Oracle Universal Driver**: - 这是一种综合性的驱动,可以理解为一个驱动包,包含了所有类型的JDBC驱动。 - ...

    qt 5.6.1 oracle 11.2.0 数据库驱动

    QT 5.6.1与Oracle 11.2.0数据库驱动的集成与...请注意,实际应用中可能需要根据你的具体需求和环境进行调整,比如SSL连接、连接池等高级特性。在进行数据库操作时,务必遵循最佳实践,确保数据安全性和系统的稳定性。

    oracle oci tool

    Oracle OCI,全称为Oracle Call Interface,是Oracle数据库提供的一种C语言编程接口,允许开发者在C或C++等语言中直接访问Oracle数据库。这个工具对于开发人员来说至关重要,因为它提供了低级别的数据库访问能力,...

    Oracle API

    通过JDBC,开发人员可以执行SQL语句,处理结果集,管理事务,并实现数据库连接池。Oracle提供了JDBC驱动,如ojdbc,以优化对Oracle数据库的访问性能。 2. OCI(Oracle Call Interface):这是Oracle的C语言API,...

    Oracle 简明进程架构

    当用户运行一个应用程序(如Pro*C程序或SQL\*Plus)时,操作系统会创建一个客户端进程(有时称为用户进程)来运行该用户的应用程序。 ##### 1. 客户端和服务器进程的区别 为客户端进程服务的Oracle进程与客户端...

    instant client_11 客户端 32位

    此外,通过OCI和ODBC接口,还可以使用连接池技术优化连接的创建和管理。 8. **性能**:由于其轻量级特性,Instant Client在资源消耗方面相对较低,对于远程数据库访问尤其有利。 9. **安全性**:11g版本加强了安全...

Global site tag (gtag.js) - Google Analytics