【发布时间】:2018-02-26 03:03:02
【问题描述】:
我们有一个 c++ 服务器应用程序,它使用 libpq 库连接到 postgresql 数据库。应用程序创建了 100 个与数据库的连接,并且连接的大部分生命周期都是应用程序范围。
最初应用程序运行良好,但在一段时间后,postgres 服务器为长时间运行的连接消耗了更多内存。通过编写下面的示例程序,我了解到使用 PQsendPrepare 和 PQsendQueryPrepared 创建准备好的语句会导致数据库服务器中的内存消耗问题。
我们如何解决这个服务器内存问题?是否有任何 libpq 函数可以释放服务器中的内存?
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <stdio.h>
#include <stdlib.h>
#include <libpq-fe.h>
int main(int argc, char *argv[]) {
const int LEN = 10;
const char *paramValues[1];
int paramFormats[1];
int rowId = 7369;
Oid paramTypes[1];
char str[LEN];
snprintf(str, LEN, "%d", rowId);
paramValues[0] = str;
paramTypes[0]=20;
paramFormats[0]=0;
long int c=1;
PGresult* result;
//PGconn *conn = PQconnectdb("user=scott dbname=dame");
PGconn *conn = PQsetdbLogin ("", "", NULL, NULL, "dame", "scott", "tiger") ;
if (PQstatus(conn) == CONNECTION_BAD) {
fprintf(stderr, "Connection to database failed: %s\n",
PQerrorMessage(conn));
do_exit(conn);
}
char *stm = "SELECT coalesce(ename,'test') from emp where empno=$1";
for(;;)
{
std::stringstream strStream ;
strStream << c++ ;
std::string strStatementName = "s_" + strStream.str() ;
if(PQsendPrepare(conn,strStatementName.c_str(), stm,1,paramTypes) )
{
result = PQgetResult(conn);
if (PQresultStatus(result) != PGRES_COMMAND_OK)
{
PQclear(result) ;
result = NULL ;
do
{
result = PQgetResult(conn);
if(result != NULL)
{
PQclear (result) ;
}
} while (result != NULL) ;
std::cout<<"error prepare"<<PQerrorMessage (conn)<<std::endl;
break;
}
PQclear(result) ;
result = NULL ;
do
{
result = PQgetResult(conn);
if(result != NULL)
{
PQclear (result) ;
}
} while (result != NULL) ;
}
else
{
std::cout<<"error:"<<PQerrorMessage (conn)<<std::endl;
break;
}
if(!PQsendQueryPrepared(conn,
strStatementName.c_str(),1,(const char* const *)paramValues,paramFormats,paramFormats,0))
{
std::cout<<"error:prepared "<<PQerrorMessage (conn)<<std::endl;
}
if (!PQsetSingleRowMode(conn))
{
std::cout<<"error singrow mode "<<PQerrorMessage (conn)<<std::endl;
}
result = PQgetResult(conn);
if (result != NULL)
{
if((PGRES_FATAL_ERROR == PQresultStatus(result)) || (PGRES_BAD_RESPONSE == PQresultStatus(result)))
{
PQclear(result);
result = NULL ;
do
{
result = PQgetResult(conn);
if(result != NULL)
{
PQclear (result) ;
}
} while (result != NULL) ;
break;
}
if (PQresultStatus(result) == PGRES_SINGLE_TUPLE)
{
std::ofstream myfile;
myfile.open ("native.txt",std::ofstream::out | std::ofstream::app);
myfile << PQgetvalue(result, 0, 0)<<"\n";
myfile.close();
PQclear(result);
result = NULL ;
do
{
result = PQgetResult(conn) ;
if(result != NULL)
{
PQclear (result) ;
}
}
while(result != NULL) ;
sleep(10);
}
else if(PQresultStatus(result) == PGRES_TUPLES_OK || PQresultStatus(result) == PGRES_COMMAND_OK)
{
PQclear(result);
result = NULL ;
do
{
result = PQgetResult(conn) ;
if(result != NULL)
{
PQclear (result) ;
}
}
while(result != NULL) ;
}
}
}
PQfinish(conn);
return 0;
}
【问题讨论】:
标签: c++ postgresql memory-leaks libpq