odbc测试增删改查性能(吞吐量)小程序

转载请注明:https://blog.csdn.net/fuqiangnxn/article/details/94158465

一.功能:

1.支持SQLExecDirect/SQLExecute两种调用

2.支持多线程(多SQLConnect)同时连接

3.支持增删改查4种性能测试

 

二.表结构

create table t1 (id bigint primary key,cause varchar(100),modifytime date,version int);

 

三.代码

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>

#include <pthread.h>
#include <string.h>

#include <sql.h>
#include <sqlext.h>
//#include <gperftools/profiler.h>

/* 参数说明
-t 客户端连接数量
-d dml类型 i u s d
-p 0-无prepare,其他-有prepare
-c 多少条Sql进行commit
-n 每个客户端执行的SQL数量
*/

#define ERRMSG_LEN 1024
#define bool char 
typedef enum 
{
    false = 0,
    true 
}booltype;

//执行SQL的类型
typedef enum
{
    dml_unknown = 0,
    dml_insert,
    dml_update,
    dml_select,
    dml_delete
}dmltype;

static int g_connect_num = 0;     //客户端连接数量
static int g_connect_failed = 0;  //客户端连接失败数量
static int g_connect_success = 0; //客户端连接成功数量
static dmltype g_dmltype =  dml_unknown;
static bool g_isprepare = false;  //使用prepare方式与否
static long g_commit_num = 0;     //多少条sql进行commit
static long g_round_num = 0;      //每个客户端执行的SQL数量

static long g_sql_missing = 0;    //执行sql未命中的总数量

static long g_throughput = 0;     //吞吐量计算方式的一种

static char g_dsn[] = "orcl" ;

static bool CheckError( SQLRETURN    mRet,
                        SQLSMALLINT  mHandleType,
                        SQLHANDLE    mHandle,
                        SQLCHAR*     mErrMsg)
{
    SQLRETURN       retcode = SQL_SUCCESS;

    SQLSMALLINT     errNum = 1;
    SQLCHAR         sqlState[6];
    SQLINTEGER      nativeError;
    SQLCHAR         errMsg[ERRMSG_LEN];
    SQLSMALLINT     textLengthPtr;

    if ((mRet != SQL_SUCCESS) && (mRet != SQL_SUCCESS_WITH_INFO))
    {
        while (retcode != SQL_NO_DATA)
        {
            retcode = SQLGetDiagRec (mHandleType, mHandle, errNum, sqlState, &nativeError, errMsg, ERRMSG_LEN, &textLengthPtr);

            if (retcode == SQL_INVALID_HANDLE)
            {
                fprintf (stderr, "CheckError function was called with an invalid handle!!\n");
                return true;
            }

            if ((retcode == SQL_SUCCESS) || (retcode == SQL_SUCCESS_WITH_INFO))
                fprintf (stderr, "ERROR: %d:  %s : %s \n", nativeError, sqlState, errMsg);

            errNum++;
        }

        fprintf (stderr, "%s\n", mErrMsg);
        return true;   /* all errors on this handle have been reported */
    }
    else
    {
        return false;   /* no errors to report */
    }
}

static SQLRETURN ConnectDB(SQLHDBC *mHdbc) 

    SQLRETURN   rc;
    SQLCHAR     verInfoBuffer[255];
    SQLSMALLINT    verInfoLen;
    char     errMsg[ERRMSG_LEN];
    unsigned int tid = (unsigned int) pthread_self();

    /* Establish the database connection */
    rc = SQLConnect (*mHdbc, (SQLCHAR*)g_dsn, SQL_NTS, (SQLCHAR *) "", SQL_NTS, (SQLCHAR *) "", SQL_NTS);
    sprintf(errMsg, "[%u] SQLConnect failed!\n", tid);
    if (CheckError (rc, SQL_HANDLE_DBC, *mHdbc, (SQLCHAR *) errMsg))
        return rc;

    /* Get version information from the database server */
    rc = SQLGetInfo (*mHdbc, SQL_DBMS_VER, verInfoBuffer, 255, &verInfoLen);
    sprintf(errMsg, "[%u] SQLGetInfo<SQL_dbms_ver> failed!\n", tid);
    if (CheckError (rc, SQL_HANDLE_DBC, *mHdbc, (SQLCHAR *) errMsg))
        return rc;

    /* Set the connection attribute SQL_ATTR_AUTOCOMMIT to SQL_AUTOCOMMIT_OFF */
    rc = SQLSetConnectAttr (*mHdbc, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_OFF, (SQLINTEGER) 0);
    sprintf(errMsg, "[%u] SQLSetConnectAttr<SQL_ATTR_AUTOCOMMIT> failed!\n", tid);
    if (CheckError (rc, SQL_HANDLE_DBC, *mHdbc, (SQLCHAR *) errMsg))
        return rc;

    return SQL_SUCCESS;
}

/* Get Current Time to microsecond */
static double GetUTimeToDouble()
{
    struct timeval tv;
    gettimeofday(&tv, NULL);
    return tv.tv_sec + 0.000001 * tv.tv_usec;
}

static void *Workload(void *mPartitionID)
{
    //ProfilerStart("out.prof");
    SQLHENV henv   = SQL_NULL_HANDLE;
    SQLHDBC hdbc   = SQL_NULL_HANDLE;
    SQLHSTMT hstmt = SQL_NULL_HANDLE;

    SQLRETURN rc;
    char strSql[1000]; 
    long int userid = -1;
    int partition_id;
    char errMsg[ERRMSG_LEN];

    double time_start, time_end;
    unsigned int tid;
    int i;

    tid = (unsigned int) pthread_self();
    partition_id = *(int *) mPartitionID;

    /* Allocate the Environment handle */
    rc = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
    if (rc != SQL_SUCCESS)
    {
        fprintf (stdout, "[%u] Environment Handle Allocation failed!!\n", tid);
        goto exit;
    }

    /* Set the ODBC version to 3.0 */
    rc = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC3, 0);
    sprintf(errMsg, "[%u] SQLSetEnvAttr<ODBC_VERSION> failed!!\n", tid);
    if (CheckError(rc, SQL_HANDLE_ENV, henv, (SQLCHAR *) errMsg))
        goto exit;

    /* Allocate the connection handle */
    rc = SQLAllocHandle (SQL_HANDLE_DBC, henv, &hdbc);
    sprintf(errMsg, "[%u] Connection Handle Allocation failed!!\n", tid);
    if (CheckError(rc, SQL_HANDLE_ENV, henv, (SQLCHAR *) errMsg))
        goto exit;

    /* Workload Start */
    rc = ConnectDB(&hdbc);
    if ((rc != SQL_SUCCESS) && (rc != SQL_SUCCESS_WITH_INFO))
    {
        __sync_fetch_and_add(&g_connect_failed,1);
        goto exit;
    }
    else
    {
        __sync_fetch_and_add(&g_connect_success,1);
    }
        
    /* Allocate the statement handle */
    {
        rc = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
        sprintf(errMsg, "[%u] Statement Handle Allocation failed!\n", tid);
        if (CheckError (rc, SQL_HANDLE_DBC, hdbc, (SQLCHAR *) errMsg))
            goto exit;
    }
    if(g_isprepare)
    {
        /* Prepare Statement */
        {
            switch(g_dmltype)
            {
                case dml_insert:
                    sprintf(strSql,"insert into t1 values (?,'aaaaaaaaaaaaaaaaaaaaaaaaaaa',to_date('2018-10-11'),1)");
                    break;
                case dml_update:
                    sprintf(strSql,"update t1 set cause = 'bbbbbbbbbbbbbbbbbbbbbbbbbbbb',modifytime = to_date('2018-11-12'),version = 2 where id = ?");
                    break;
                case dml_select:
                    sprintf(strSql,"select * from t1 where id=?");
                    break;
                case dml_delete:
                    sprintf(strSql,"delete from t1 where id=?");
                    break;
                default:
                break;
            }
            
            rc = SQLPrepare(hstmt, (SQLCHAR *)strSql, strlen(strSql));
            sprintf(errMsg, "[%u] SQLPrepare '%s' failed!\n", tid, strSql);
            if (CheckError(rc, SQL_HANDLE_STMT, hstmt, (SQLCHAR *) errMsg))
                goto exit;

            rc = SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_SBIGINT, SQL_BIGINT, 8, 0, (SQLBIGINT *)&userid, 0, NULL);
            sprintf(errMsg, "[%u] SQLBindParameter (param 1) failed!\n", tid);
            if (CheckError (rc, SQL_HANDLE_STMT, hstmt, (SQLCHAR *) errMsg))
                goto exit;
        }
    }
    time_start=GetUTimeToDouble();
    for(i=0;i<g_round_num;i++)
    {
        userid = i + partition_id*g_round_num;

        if(g_isprepare)
        {
            rc =SQLExecute(hstmt);
            if (!(rc == SQL_SUCCESS) || (rc == SQL_SUCCESS_WITH_INFO))
            {
                sprintf(errMsg, "[%u] SQLExecute failed!\n", tid);
                if (CheckError (rc, SQL_HANDLE_STMT, hstmt, (SQLCHAR *) errMsg))
                {
                    goto exit;
                }
            }
        }
        else
        {
            switch(g_dmltype)
            {
                case dml_insert:
                    sprintf(strSql,"insert into t1 values (%ld,'aaaaaaaaaaaaaaaaaaaaaaaaaaa',to_date('2018-10-11'),1)",userid);
                    break;
                case dml_update:
                    sprintf(strSql,"update t1 set cause = 'bbbbbbbbbbbbbbbbbbbbbbbbbbbb',modifytime = to_date('2018-11-12'),version = 2 where id = %ld",userid);
                    break;
                case dml_select:
                    sprintf(strSql,"select * from t1 where id=%ld",userid);
                    break;
                case dml_delete:
                    sprintf(strSql,"delete from t1 where id=%ld",userid);
                    break;
                default:
                break;
            }
            
            rc =SQLExecDirect(hstmt,(SQLCHAR*)strSql,SQL_NTS);
            if (!(rc == SQL_SUCCESS) || (rc == SQL_SUCCESS_WITH_INFO))
            {
                sprintf(errMsg, "[%u] SQLExecDriect failed!\n", tid);
                if (CheckError (rc, SQL_HANDLE_STMT, hstmt, (SQLCHAR *) errMsg))
                {
                    goto exit;
                }
            }
        }

        if(g_dmltype == dml_select)
        {
            #if 1//View Select Result
            rc = SQLFetch(hstmt);
            if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO)
            {
                SQLBIGINT Value1=0; 
                SQLCHAR Value2[50];
                memset(Value2, 0, sizeof(Value2));
                SQLLEN   len1 = 1,len2 = 1;
                rc = SQLGetData(hstmt,1,SQL_C_SBIGINT,&Value1,0,(SQLLEN*)&len1);
                rc = SQLGetData(hstmt,2,SQL_C_CHAR,Value2, sizeof(Value2),(SQLLEN*)&len2);
                printf("[%u] id:%ld results:value1:%ld,values2:%s,len1:%d,len2:%d\n",tid,userid,(long)Value1,Value2,(int)len1,(int)len2);
            }
            else
            {
                if (rc == SQL_NO_DATA)
                {
                    __sync_fetch_and_add(&g_sql_missing,1);
                } 
                else
                {
                    sprintf(errMsg, "[%u] SELECT SQLFetch failed!\n", tid);
                    if (CheckError (rc, SQL_HANDLE_STMT, hstmt, (SQLCHAR *) errMsg))
                    {
                        goto exit;
                    }
                }
            }
            #endif

            rc = SQLCloseCursor (hstmt);
            if (!(rc == SQL_SUCCESS) || (rc == SQL_SUCCESS_WITH_INFO))
            {
                sprintf(errMsg, "[%u] SQLCloseCursor failed!\n", tid);
                if (CheckError (rc, SQL_HANDLE_STMT, hstmt, (SQLCHAR *) errMsg))
                    goto exit;
            }
        }
        else
        {
            if ( i % g_commit_num == 0 )
            {
                rc = SQLEndTran (SQL_HANDLE_DBC, hdbc, SQL_COMMIT);
                sprintf(errMsg, "[%u] DCL SQLEndTran failed!\n", tid);
                if (CheckError (rc, SQL_HANDLE_STMT, hstmt, (SQLCHAR *) errMsg))
                {
                    goto exit;
                }
            }
        }
    }

    if(g_dmltype != dml_select)
    {
        if ( g_round_num % g_commit_num != 0 )
        {
            rc = SQLEndTran (SQL_HANDLE_DBC, hdbc, SQL_COMMIT);
            sprintf(errMsg, "[%u] DCL SQLEndTran failed!\n", tid);
            if (CheckError (rc, SQL_HANDLE_STMT, hstmt, (SQLCHAR *) errMsg))
            {
                goto exit;
            }
        }
    }
    time_end=GetUTimeToDouble();
    printf("[%u] ---time:%lf,throughput:%lf---\n", tid, time_end-time_start,(double)g_round_num/(double)(time_end-time_start));
    __sync_fetch_and_add(&g_throughput,(long)((double)g_round_num/(double)(time_end-time_start)));
    /* Workload End */
    //ProfilerStop();
exit:
    /* Close the statement handle */
    SQLFreeStmt(hstmt, SQL_CLOSE);

    /* Free the statement handle */
    SQLFreeHandle(SQL_HANDLE_STMT, hstmt);

    /* Disconnect from the data source */
    SQLDisconnect(hdbc);

    /* Free the environment handle and the database connection handle */
    SQLFreeHandle (SQL_HANDLE_DBC, hdbc);
    SQLFreeHandle (SQL_HANDLE_ENV, henv);
    return NULL;
}

void display_usage(void)
{
    printf("select -t <client_num> -d <dml_type> -n <sql num per client> \n");
    printf("select -c <how many sql to commit> -p <prepare or not>  \n");
    exit(EXIT_FAILURE);
}

int main(int argc, char *argv[])
{
    double time_start, time_end;
    time_start=GetUTimeToDouble();
    int opt=-1;
    int i;

    while((opt = getopt(argc, argv, "t:d:n:c:p:h:?:")) != -1)
    {
        switch(opt)
        {
        case 't': 
            g_connect_num = atoi(optarg);
            break;
        case 'd':
            if(strcmp(optarg,"i") == 0) 
            {
                g_dmltype = dml_insert;
            }
            else if(strcmp(optarg,"u") == 0) 
            {
                g_dmltype = dml_update;
            }
            else if(strcmp(optarg,"s") == 0) 
            {
                g_dmltype = dml_select;
            }
            else if(strcmp(optarg,"d") == 0) 
            {
                g_dmltype = dml_delete;
            }
            else
            {
                printf("unknown options is founded!\n");
                display_usage();
            }
            break;
        case 'n': 
            g_round_num = atoi(optarg);
            break;
        case 'c': 
            g_commit_num = atoi(optarg);
            break;
        case 'p': 
            if(atoi(optarg) != 0)
            {
                g_isprepare = true;
            }
            break;

        case 'h':
        case '?':
            display_usage();
            break;

        default:
            printf("%d\n", opt);
            printf("unknown options is founded!\n");
            display_usage();
            break;
        }
    }

    if (optind < argc) {
        printf("non-option ARGV-elements: ");
        while(optind < argc)
            printf("%s ", argv[optind++]);
        printf("\n");
    }

    /* Check Arguments */
    if(g_connect_num<0)
    {
        printf("client num err!\n");
        exit(EXIT_FAILURE);
    }
    if(g_round_num<1)
    {
        printf("round num err!\n");
        exit(EXIT_FAILURE);
    }
    if(g_commit_num<1)
    {
        printf("commit num err!\n");
        exit(EXIT_FAILURE);
    }

    pthread_t *tid=(pthread_t *)malloc(g_connect_num*sizeof(pthread_t));
    int *partition_id = (int *)malloc(g_connect_num*sizeof(int));

    #if 0
    int scope = 0;
    pthread_attr_t attr;
    pthread_attr_init(&attr);
    pthread_attr_getscope(&attr,&scope);
    if(scope == PTHREAD_SCOPE_PROCESS)
    {
        int i = 0;
    }
    else if(scope == PTHREAD_SCOPE_SYSTEM)
    {
        int i = 1;
    }
    pthread_attr_setscope(&attr,PTHREAD_SCOPE_PROCESS);
    #endif

    /* Generate Workload Thread */
    printf("Start with Client:%d,DmlType:%d,Round:%ld,Commit:%ld,Prepare:%d\n", g_connect_num, g_dmltype, g_round_num,g_commit_num,g_isprepare); 
    for(i=0; i<g_connect_num; i++)
    {
        partition_id[i] = i;
        if(0 != pthread_create(&tid[i], NULL/*&attr*/, Workload, (void *) &partition_id[i]))
        {
            printf("pthread_create %d failed ---\n",i);
            exit(EXIT_FAILURE);
        }
    }
    for(i=0; i<g_connect_num; i++)
    {
        pthread_join(tid[i],NULL);
    }
    time_end=GetUTimeToDouble();
    printf("connect--success:%d,failed:%d..sql--missing:%ld,throughput:%ld\n", g_connect_success,g_connect_failed,g_sql_missing,g_throughput);
    printf("end---total---time:%lf,throughput:%lf\n", time_end-time_start,(double)g_round_num/(double)(time_end-time_start));
    return 0;
}
 

四.makefile

.SUFFIXES: .c .o

CC = gcc
#-g
CFLAGS = -Wall -O0 -g

LFLAGS = -L$(_HOME)/lib
LIB = -lodbc -lpthread -ldl -lm -lrt 

INC = -I$(_HOME)/include

TARGET = gltest
OBJECTS = $(TARGET).o
SRCS = $(TARGET).c

$(TARGET):    $(OBJECTS)
        $(CC) -o $(TARGET) $(OBJECTS) $(LFLAGS) $(LIB)

$(OBJECTS):    $(SRCS)
        $(CC) $(CFLAGS) -c $(INC) $(SRCS)

clean:
        rm $(TARGET).o $(TARGET)
 

五.调用脚本

./gltest -t 4 -d s -n 20 -c 3 -p 1

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值