mysql 编程

linux下多线程连接mysql(C语言)

代码使用了pthread库,在Ubuntu环境下使用gcc编译并运行成功。
增加的编译选项 -lpthread -Llibmysqlclient_r.so
后者是mysql 的线程安全链接库。
原有代码嵌入在一个应用程序中,这里只给出数据库访问部分。
关键是每个线程维护一个单独的MYSQL结构,并初始化线程专用数据,由于mysql_real_connect会自动调用mysql_thread_init(),函数里面不再重复调用。

int main()
{
    mysql_library_init(0,NULL,NULL);
    pthread_t producer;
    pthread_t consumer_1;
    pthread_t consumer_2;
//produce_fun不涉及数据库链接,不贴出来
    pthread_create(&producer,NULL,produce_fun,NULL);
    pthread_create(&consumer_1,NULL,consume_fun,NULL);
    pthread_create(&consumer_2,NULL,consume_fun,NULL);
//下面的三句非常重要,main线程等待其他三个线程的结束,避免main线程执行到mysql_library_end时退出,而
//其他三个线程仍然在运行并报错的情形
    pthread_join(producer,NULL);
    pthread_join(consumer_1,NULL);
    pthread_join(consumer_2,NULL);
    mysql_library_end();
    return 0;
}

void addRecord_d(MYSQL *ptr_db,const char *t_name,int item){
    char query_buffer[100];
    sprintf(query_buffer,"insert into %s values(0,%d)",t_name,item);
    int ret=mysql_query(ptr_db,query_buffer);
    if(ret){
        fprintf(stderr,"%s%s\n","cannot add record to ",t_name);
        return;
    }

    unsigned long long update_id=mysql_insert_id(ptr_db);
    printf("add record (%llu,%d) ok.",update_id,item);
}


void * consume_fun(void *arg){
    MYSQL db;
    MYSQL *ptr_db=mysql_init(&db);
    mysql_real_connect();
   //蓝色部分可以改为其他任何带操作数据库语句的代码
    //procedure
    while(1){
        printf("consumer...");
        int item=consume(&p);
        addRecord_d(ptr_db,"test",item);
    }
   mysql_thread_end();
    pthread_exit(NULL);
}

 

 

//MYSQL_RES保存查询结构

MYSQL_RES* result_ = NULL;

int error_code = 0;                         //保存错误码

char error_info[1024] = '\0';               //保存错误信息

//对mysql数据库进行查询操作:

char query_sql[1024] = "select * from db_name.table_name";          //构建查询sql语句

if(result_ != NULL)                         //防止之前已经被使用过(所有的使用,在使用前都要判空)

{

      mysql_free_result(result_);

      result_ = NULL;

}

if(link_ == NULL)                          //防止没有链接

{

         //重连,按照建立mysql数据库链接的方法进行建立,前面的blog中有讲到

}

//执行sql查询

if(mysql_query(link_,query_sql) != 0)

{

         //查询失败

         error_code = mysql_errno(link_);                      //获取错误码

         strncpy(error_info,mysql_error(link_),1024);          //获取错误信息

         if((error_code == 2013) || (error_code == 2006))      //2006 mysql服务器不可用,2013查询过程中,丢失链接

         {

             //重链,按照建立mysql数据库链接的方法进行建立

             if(//重链失败)

             {

                   return false;

             }

            //重链成功,再次查询

            if(mysql_query(link_,query_sql) != 0)

            {

                 //再次查询失败

                 error_code = mysql_errno(link_);

                 strncpy(error_info,mysql_error(link_),1024);

                 //返回错误

                 return false;

            }

            error_code = 0; //查询成功了。

         }

}

else

{

      //查询成功

}

 

 

 

//查询成功,保存查询结果

result_ = mysql_store_result(link_);

if(result_ == NULL)

{

     error_code = mysql_errno(link_);                    //获取错误码

     strncpy(error_info,mysql_error(link_),1024);           //获取错误信息

     //返回错误                                     

     return false;

}

 

 

//获取查询结果的行数(记录数)

return mysql_num_rows(result_);

 

 

 

//获取查询结果的字段数

return mysql_num_fields(result_);

 

 

//获取查询结果的各个字段的字段名称

MYSQL_FIELD  *fields;                              //保存字段名字信息

unsing int  num_fields;

unsigned int  i;

num_fields = mysql_num_fields(result);             //获取查询结果中,字段的个数

fields = mysql_fetch_fields(result);               //获取查询结果中,各个字段的名字

for(i = 0; i < num_fields;i++)

{

       printf("field  %u  is  %s\n",i,fields[i].name);

}

 

//获取查询出来的结果,即遍历查询到的每一行记录

MYSQL_ROW  row;                                    //保存行记录信息

unsigned  int  num_fields;

unsigned  int  i;

num_fields  =  mysql_num_fields(result_);

while((row = mysql_fetch_row(result_)))            //遍历查询结果中的各行记录

{

      unsigned long *lengths = NULL;

      lengths = mysql_fetch_lengths(result_);     //获取每一个记录行中,每一个字段的长度,在lengths数组中。

      for( i = 0; i < num_fields; i++)

      {

            printf("数据长度%u \t  数据内容%s",lengths[i],row[i]?row[i]:"NULL");

      }

      printf("\n");

}

 

 //释放资源,断开链接

if(result_ != NULL)

{

     mysql_free_result(result_);

     result_  = NULL;

}

if(link_ != NULL)

{

     mysql_close(link_);

     link_ = NULL;

}

 

 

使用mysql C语言API编写程序—建立mysql数据库链接(超时设定,建立链接)

//MYSQL句柄   (任何一个mysql操作都是基于MYSQL这个句柄来操作的)

MYSQL* link_ = NULL;

//对mysql操作进行必要的初始化

if(link_  !=  NULL)

{

         mysql_close(link_);

}

link_   =   mysql_init(NULL);             //初始化MYSQL句柄

//设置超时时间(链接超时时间,查询超时时间,写数据库超时时间)

int  timeout_  =  3;                      //超时时间设置为3秒

if(link_ != NULL)

{

       mysql_options(link_,MYSQL_OPT_CONNECT_TIMEOUT,(const char *)&timeout_);

       //设置链接超时时间.

       mysql_options(link_,MYSQL_OPT_READ_TIMEOUT,(const char *)&timeout);

       //设置查询数据库(select)超时时间

       mysql_options(link_,MYSQL_OPT_WRITE_TIMEOUT,(const char *)&timeout);

       //设置写数据库(update,delect,insert,replace等)的超时时间。

}

//真正建立mysql链接

char  host_name[1024] = "192.168.123.236";           //mysql服务器的IP

char  user_name[1024] = "chenbaihu";                 //用户名

char  user_password[1024] = "xy871202";                      //密码

unsigned short host_port = 3306;                     //服务器端口

int   error_code;

char  error_info[1024];

if(!mysql_real_connect(link_,host_name,user_name,user_password,NULL,host_port,NULL,0))

{

      //失败处理

      error_code  =  mysql_errno(link_);            //获取错误码

      strncpy(error_info,mysql_error(link_),1024);  //获取错误信息

      mysql_close(link_);                           //释放句柄

      link_  = NULL;

}

else

{

       //链接建立成功,可以进行具体的操作(select   insert    delete   update  replace等)

}

 

 

 

mysql—开发C,C++程序,避免连接超时、读数据库超时、写数据库超时,系统再也不怕被MySQL服务器挂死

避免连接超时:  //可以用采用停掉mysqld或iptables封掉端口测试。

int g_iTimeOut = 5;

mysql_options(&mysql_, MYSQL_OPT_CONNECT_TIMEOUT, (const char *)&g_iTimeOut);

避免读超时:     //可以采用对表加写锁   lock  table tablename  write  或killall   -STOP  mysqld等来进行测试。

       int  g_iTimeOut = 5;

mysql_options(&mysql_, MYSQL_OPT_READ_TIMEOUT, (const char *)&g_iTimeOut);

避免写超时:    //可以采用对表加写锁     lock  table tablename  write  或killall   -STOP  mysqld等来进行测试。

      int  g_iTimeOut = 5;

      mysql_options(&mysql_, MYSQL_OPT_WRITE_TIMEOUT, (const char *)&g_iTimeOut);

 注意mysql API版本的问题::

       虽然很多版本都支持上面的控制,但是建议还是使用MySQL 5.1.12及以上版本。

 

Mysql乱码—字段编码(filed)、表编码(table)、数据库编码(db)、数据库服务器(dbserver)编码

Mysql数据库 2010-11-28 11:09:43 阅读38 评论0   字号:大中小 订阅

Mysql数据库的编码分为四级:

         1、Mysql数据库服务器编码;

                       (在相应的配置文件中,需要修改配置文件)

         2、Mysql数据库编码;

                       (可以在创建的时候指定,也可以在创建之后进行修改)

        3、Mysq数据库中表的编码;

                       (可以在创建的时候指定,也可以在创建之后进行修改)

        4、Mysql数据库表中字段的编码;

                        (可以在创建的时候指定,也可以在创建之后进行修改)

 

数据库编码选择的一般准则:

         1、GBK/GB2312

                        适合纯中文存储的数据库

         2、LATIN1

                       适合于纯英文的存储

         3、UTF8

                       适合中英文混合编码的存储。

 

 

创建数据库并指定编码:                   (数据库)

方法1、

         creat   database    db_name     default     character    set     utf8

方法2、

       create   database    db_name    default   charset=utf8

 

创建表并指定编码:                           (表)

方法1、

       create table table_name

      (

            ......//字段信息

      )default   character    set   utf8;

方法2、

       create table table_name

      (

                ......//字段信息

      )default   charset=utf8;

 

 

指定字段的编码:                          (字段)                                仅有一种方法

方法:

create   table    table_name

(

          filed_name   varchar(20)     character     set   utf8                //注意不能有default

);

 

 

MySQL++ 一个成熟的C++封装
http://tangentsoft.net/mysql++/
http://tangentsoft.net/mysql++/doc/pdf/userman.pdf

 

一些用例:

 


1. 使用方便
    一个头文件
    #include <mysql++.h>
    一个库
    libmysqlpp

 

 

 

2. 方便的数据访问
    #include <mysql++.h>
   
    mysqlpp::Connection conn(db, server, user, pass);
    mysqlpp::Query query = conn.query();
    query << "SELECT devid, md5value from t_snmp_index limit 10";
   
    mysqlpp::StoreQueryResult res = query.store();
    mysqlpp::StoreQueryResult::const_iterator it;
    for (size_t i = 0; i < res.num_rows(); ++i)
    {
        cout << res[i]["devid"] << "\t" << res[i]["md5value"] << endl;             //通过字段名访问
    }
   
    //===> or
   
    for (size_t i = 0; i < res.num_rows(); ++i)
    {
        cout << res[i][0] << "\t" << res[i][1] << endl;                                             //通过列数访问字段名
    }
   

 

3. sql模板
    #include <mysql++.h>
    

    //建立mysql链接       
    mysqlpp::Connection conn(db, server, user, pass);
    

    //实现mysql查询           方法1
    string sqltemplate = "select devid, md5value from %s limit %d, 10";
    char buf[1024];
    snprintf(buf, sizeof(buf), sqltemplate.c_str(), tablename, index);

    mysqlpp::Query query = conn.query(buf);
    mysqlpp::StoreQueryResult res1 = query.store();
   
    //===> or
   
 //实现mysql查询           方法2
    mysqlpp::Query query = conn.query();
    query << "SELECT devid, md5value from %0 limit %1q, 10";
    query.parse();
   
    mysqlpp::StoreQueryResult res1 = query.store(tablename, index);
   
   
4.
 与stl的融合
    #include <mysql++.h>
    #include <ssqls.h>

    // 生成struct SNMP
    sql_create_6(SNMP,
                1, 6,
                mysqlpp::sql_int, devid,
                mysqlpp::sql_int, attrid,
                mysqlpp::sql_varchar, snmp_index,
                mysqlpp::sql_varchar, index_name,
                mysqlpp::sql_varchar, port_type,
                mysqlpp::sql_char, md5value)

   
    //
 结果保存在vector中
    vector<SNMP> v;

    mysqlpp::Connection conn(db, server, user, pass);
    mysqlpp::Query query = conn.query();
    query << "SELECT * from t_snmp_index limit 10";
    query.storein(v);

    for (vector<SNMP>::iterator it = v.begin(); it != v.end(); ++it) {
        cout << it->devid
            << "\t" << it->attrid
            << "\t" << it->snmp_index
            << "\t" << it->index_name
            << "\t" << it->port_type
            << "\t" << it->md5value
            << endl;
    }

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值