We have a c++ server application which is connecting to postgresql database using libpq library. Application creating 100s of connection to database and most of the connection's life time is application scope.
Initially application was running fine, but over a period of time postgres server consuming more memory for long running connections. By writing a below sample program I come to know creating prepared statements using PQsendPrepare and PQsendQueryPrepared is causing the memory consumption issue in database server.
How we can fix this server memory issue? is there any libpq function to free the memory in server?
#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;
}