• 关于mysql_free_result和mysql_close的解惑


    之前用mysql的时候一直是在用短链接,调用mysql_store_result获取一次数据之后就直接调用:

    1
    2
    mysql_free_result(m_result);
    mysql_close(m_Database);

    但是有两个问题:
    1.当使用长连接时(即connect之后一直不close),如果最后会调用mysql_close,需不需要每次都调用mysql_free_result呢?
    2.当mysql_close调用之后,m_result的数据是否还可以用。

    先说一下结论:
    1.必须每次调用。因为经过测试,每次mysql_store_result的指针都是不同的,可见并不是共享了同一块buf。
    2.还是可以使用。经过valgrind扫描,只调用mysql_close的扫描结果是:

    ==9397== 16,468 (88 direct, 16,380 indirect) bytes in 1 blocks are definitely lost in loss record 4 of 5
    ==9397== at 0x40219B3: malloc (vg_replace_malloc.c:195)
    ==9397== by 0x8053EA2: my_malloc (in /data/home/dantezhu/appbase/application/platform/openqqcom/share/db_openright/test/test)
    ==9397== by 0x806D314: mysql_store_result (in /data/home/dantezhu/appbase/application/platform/openqqcom/share/db_openright/test/test)
    ==9397== by 0x804BB04: CMySQLCppClient::Result(st_mysql_res*&) (mysql_cpp_client.cpp:127)
    ==9397== by 0x804AB58: CDBOpenRight::GetUinsByApp(unsigned int, std::set<unsigned int, std::less<unsigned int>, std::allocator<unsigned int> >&) (db_openright.cpp:58)
    ==9397== by 0x8049F10: main (test.cpp:27)

    这里连同测试代码和我之前写的一个简单的C++封装的mysql库一起放出下载,有需要的同学可以下载试试:
    代码下载

    其中只有mysql_cpp_client.h和mysql_cpp_client.cpp是核心文件,其他均为测试代码.

    里面有简单的演示,如查询:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    char strSql[MAX_QUERYLEN_OPENRIGHT];
    snprintf(strSql,sizeof(strSql),"select uin \
    from %s where appid=%u;"
    ,OPENRIGHT_TB_CARE,appid);
     
    int ret;
     
    ret = m_SqlClient.Execute(strSql);
    if(ret)
    {
    snprintf(m_StrErrMsg,sizeof(m_StrErrMsg),"[%s][%d][%s]Error:[%d][%s]\n",
    __FILE__,__LINE__,__FUNCTION__,ret,m_SqlClient.GetErrMsg());
    return -1;
    }
     
    MYSQL_RES *result = NULL;
    ret = m_SqlClient.Result(result);
    if(ret)
    {
    snprintf(m_StrErrMsg,sizeof(m_StrErrMsg),"[%s][%d][%s]Error:[%d][%s]\n",
    __FILE__,__LINE__,__FUNCTION__,ret,m_SqlClient.GetErrMsg());
    return -2;
    }
     
    //这里很重要,做了析构时自动调用mysql_free_result
    StCppResult freeRes(result);
     
    unsigned int unRecords = mysql_num_rows(result);
     
    if (0 == unRecords)
    {
    snprintf(m_StrErrMsg,sizeof(m_StrErrMsg),"[%s][%d][%s]Error: Result is empty\n",
    __FILE__,__LINE__,__FUNCTION__);
    return 0;
    }
    MYSQL_ROW row;
    for(unsigned int unIndex = 0; unIndex < unRecords; unIndex++)
    {
    row=mysql_fetch_row(result);
    unsigned uin = unsigned(atoi((char*)row[0]));
    setUins.insert(uin);
    }
    return 0;

    插入:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    if(setUins.size() <= 0)
    {
    return 0;
    }
    if(setUins.size() > 1000)
    {
    snprintf(m_StrErrMsg,sizeof(m_StrErrMsg),"[%s][%d][%s]Error:[uins more than 1000]\n",
    __FILE__,__LINE__,__FUNCTION__);
    return -1;
    }
    string strValues;
    char szValue[100];
    for(set<unsigned int>::iterator it = setUins.begin();it!=setUins.end();++it)
    {
    if (setUins.begin() == it)
    {
    snprintf(szValue,sizeof(szValue),TPL_ADDUIN2APP,*it,appid);
    }
    else
    {
    snprintf(szValue,sizeof(szValue),","TPL_ADDUIN2APP,*it,appid);
    }
    strValues.append(szValue);
    }
     
    char strSql[MAX_QUERYLEN_OPENRIGHT];
    snprintf(strSql,sizeof(strSql),"insert into %s(uin,appid) VALUES %s;",OPENRIGHT_TB_CARE,strValues.c_str());
     
     
    int ret;
    ret = m_SqlClient.Execute(strSql);
    if(ret)
    {
    snprintf(m_StrErrMsg,sizeof(m_StrErrMsg),"[%s][%d][%s]Error:[%d][%s]\n",
    __FILE__,__LINE__,__FUNCTION__,ret,m_SqlClient.GetErrMsg());
    return -2;
    }
    if(m_SqlClient.AffectRows()<=0)
    {
    snprintf(m_StrErrMsg,sizeof(m_StrErrMsg),"[%s][%d][%s]Error:[%d][%s]\n",
    __FILE__,__LINE__,__FUNCTION__,ret,m_SqlClient.GetErrMsg());
    return -3;
    }
    return 0;

    OK,就这样。

  • 相关阅读:
    syslog+rsyslog+logstash+elasticsearch+kibana搭建日志收集
    行为型模式(一)
    spring cloud Sleuth
    Java面试题(基础)
    Java笔试题
    Idea创建SpringBoot项目整合Hibernate
    Java中遍历Map的四种方式
    SQL面试题
    Linux入门
    Spring Boot AOP Demo
  • 原文地址:https://www.cnblogs.com/rooney/p/2340863.html
Copyright © 2020-2023  润新知