? 一般来说内存暴涨都是资原未释放,或者说创建了太多资原
客户端内存暴涨 最常见得用法就是未释放从服务端接收到得数据:
服务端内存暴涨最常见就是创建了太多服务端资原对象.
先看结论:
1: es = PQgetResult(conn); 这个res必须使用PQclear(res);清除掉,任何时候都是 必须得 2: PQsendPrepare这个函数如果不停得调用会造成服务端内存暴涨, 如果同一个连接执行同一个语句, 就必须要在客户端做sql缓存,再次准备同样得语句必须使用 PQsendDescribePrepared代替PQsendPrepare; 此两个函数得函数原型如下:
int PQsendPrepare(PGconn *conn, const char *stmtName, const char *query, int nParams, const Oid *paramTypes) int PQsendDescribePrepared(PGconn *conn, const char *stmt)
客户端缓存直接用std::map<string,string> 存起来即可,key可以是sql语句,value可以是uuid
一般写法如下:
m_nCount = -1;
m_pDB = db;
GS_LOCK_IT(m_ptrDB);
Reset();
m_strSQL = sql;
if (m_ptrDB->IsSQLID(sql))
{
m_StrCmdID = m_ptrDB->GetSQLID(sql);
int ascres = PQsendDescribePrepared(m_ptrDB->Handle(), m_StrCmdID);
if (ascres != 1)//成功
{
OnPGError(m_ptrDB->Handle());
return false;
}
}
else
{
m_StrCmdID = m_ptrDB->GetSQLID(sql);
int ascres = PQsendPrepare(m_ptrDB->Handle(), m_StrCmdID, sql, m_nParamsCount, NULL);
if (ascres != 1)//成功
{
OnPGError(m_ptrDB->Handle());
return false;
}
}
//异步api必须get结果清除
PGresult * res = PQgetResult(m_ptrDB->Handle());
while (res)
{
ExecStatusType status = PQresultStatus(res);
PQclear(res);
if (status != PGRES_COMMAND_OK && status != PGRES_TUPLES_OK)
{
OnPGError(m_ptrDB->Handle());
return false;
}
res = PQgetResult(m_ptrDB->Handle());
}
return true;
GsString PGDatabase::GetSQLID(const char * strSQL) { auto end = m_SqlGUIDMap.find(strSQL); if (end != m_SqlGUIDMap.end()) return end->second; auto strID = GsMath::NewGUID(); m_SqlGUIDMap[strSQL] = strID; return strID; }
bool PGDatabase::IsSQLID(const char * strSQL) { auto end = m_SqlGUIDMap.find(strSQL); if (end != m_SqlGUIDMap.end()) return true; return false; }
3: 连接不用需要 使用 PQfinish 释放
总结一下pg得函数步骤如下(带send都是异步API):
- 连接: PQconnectStart
- 准备SQL语句: 同样SQL语句第一次执行使用PQsendPrepare, 第二次后用PQsendDescribePrepared
- 清除结果集: Prepared后, 异步api必须get结果清除 PGresult * res = PQgetResult(PGconn); PQclear(res);
- 执行查询: PQsendQueryPrepared
- 获取数据:res = PQgetResult(conn);获取几行几列数据PQgetvalue(res, i, j));
- 清除,释放连接PQclear(res); res = PQgetResult(conn);PQfinish(conn);
?
|