Oracle的 EXEC SQL CONTEXT學習


磨礪技術珠磯,踐行數據之道,追求卓越價值 
回到上一級頁面: PostgreSQL雜記頁     回到頂級頁面:PostgreSQL索引頁 
[作者 高健@博客園  luckyjackgao@gmail.com]

 

EXEC SQL CONTEXT... 是Oracle Pro*C的特有的語法,詳細信息參見

http://docs.oracle.com/cd/B28359_01/appdev.111/b28427/pc_11thr.htm#i997959

EXEC SQL ENABLE THREADS; EXEC SQL CONTEXT ALLOCATE :context_var; EXEC SQL CONTEXT USE { :context_var | DEFAULT}; EXEC SQL CONTEXT FREE :context_var;

 

所謂context ,被稱為runtime context,其實質就是保留連接數據庫的信息,保留連接數據庫的通道。

官方解釋中,使用 exec sql context ,有幾種方式:

1 各個進程之間不共享context

   事實上,Oracle的官方例子----  Thread_example1.pc,采用的就是這種方式。

   各個進程共通處理一堆轉賬數據,所以它們之間需要考慮對共同數據(文本格式的轉賬記錄)讀取時加mutex。

   但是,由於每個進程可以自己擁有一個context---數據庫通道,故此基本互相不干涉。

   我認為這是合理的,也可能是比較高效率的方式。

2 各個進程之間共享一個context

   此時,瓶頸出現在此context之上。可以想像一下,通過多線程來處理數據庫之外的數據之后,

   還是要回到一個共通的數據庫通道來排隊等候,是否效率並未發揮出來呢。

3 各個進程之間共享多個context

   這個是最復雜的,可能也是最沒有道理的。1的方式應該更好些。

而且,上述這些,都沒有考慮到連接池的作用,也許是這種技術出現的年代是很早的。

為了備忘,記錄oracle官方例子如下:

/* * 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"); } 

 

[作者 高健@博客園  luckyjackgao@gmail.com]
回到上一級頁面:PostgreSQL基礎知識與基本操作索引頁    回到頂級頁面:PostgreSQL索引頁
磨礪技術珠磯,踐行數據之道,追求卓越價值


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM