c++ 使用ODBC 写sql server2008 一段时间后会失败

骑着摩托上下班 2017-08-07 03:19:29
情况如下:
程序一直获取数据,写入sql server 2008中,使用的是ODBC。因为之前在数据库操作类中,SQLHENV henv, SQLHDBC hdbc 定义为成员变量,只在初始化时SQLAllocHandle、SQLConnect,发现很多写入操作会失败,也没有连接检查,就每次写数据前,申请、连接、操作、释放。
现在是前面的数据都写入成功了,但运行四五个小时后(已插入2千条+记录),提示错误
SQLConnect error : -1
errstate:IM005, errnative:0, errmsg:[Microsoft][ODBC 驱动程序管理器] 驱动程序的 SQLAllocHandle on SQL_HANDLE_DBC 失败


代码:
bool InitODBC(SQLHENV &henv, SQLHDBC &hdbc, SQLHSTMT &hstmt)
{
SQLRETURN ret = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
if (ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO)
{
LOG("SQLAllocHandle SQL_HANDLE_ENV error : %d", ret);
return false;
}

ret = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, SQL_IS_INTEGER);
if (ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO)
{
LOG("SQLSetEnvAttr error : %d", ret);
if (ret == SQL_ERROR)
{
SQLSMALLINT errmsglen;
SQLINTEGER errnative;
UCHAR errmsg[255] = {0};
UCHAR errstate[255] = {0};

SQLGetDiagRec(SQL_HANDLE_ENV, henv, 1, errstate, &errnative, errmsg, sizeof(errmsg), &errmsglen);
LOG("errstate:%s, errnative:%d, errmsg:%s", errstate, errnative, errmsg);
}
SQLFreeHandle(SQL_HANDLE_ENV, henv);
return false;
}

ret = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);
if (ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO)
{
LOG("SQLAllocHandle SQL_HANDLE_DBC error : %d", ret);
if (ret == SQL_ERROR)
{
SQLSMALLINT errmsglen;
SQLINTEGER errnative;
UCHAR errmsg[255] = {0};
UCHAR errstate[255] = {0};

SQLGetDiagRec(SQL_HANDLE_ENV, henv, 1, errstate, &errnative, errmsg, sizeof(errmsg), &errmsglen);
LOG("errstate:%s, errnative:%d, errmsg:%s", errstate, errnative, errmsg);
}
SQLFreeHandle(SQL_HANDLE_ENV, henv);
return false;
}

ret = SQLConnect(hdbc, (SQLCHAR*)m_strSource.c_str(), SQL_NTS, (SQLCHAR*)m_strUserName.c_str(), SQL_NTS, (SQLCHAR*)m_strPassword.c_str(), SQL_NTS);
if (ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO)
{
LOG("SQLConnect error : %d", ret);
if (ret == SQL_ERROR)
{
SQLSMALLINT errmsglen;
SQLINTEGER errnative;
UCHAR errmsg[255] = {0};
UCHAR errstate[255] = {0};

SQLGetDiagRec(SQL_HANDLE_DBC, hdbc, 1, errstate, &errnative, errmsg, sizeof(errmsg), &errmsglen);
LOG("errstate:%s, errnative:%d, errmsg:%s", errstate, errnative, errmsg);
}
SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
SQLFreeHandle(SQL_HANDLE_ENV, henv);
return false;
}

ret = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
if (ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO)
{
LOG("SQLAllocHandle SQL_HANDLE_STMT error : %d", ret);
if (ret == SQL_ERROR)
{
SQLSMALLINT errmsglen;
SQLINTEGER errnative;
UCHAR errmsg[255] = {0};
UCHAR errstate[255] = {0};

SQLGetDiagRec(SQL_HANDLE_DBC, hdbc, 1, errstate, &errnative, errmsg, sizeof(errmsg), &errmsglen);
LOG("errstate:%s, errnative:%d, errmsg:%s", errstate, errnative, errmsg);
}
SQLDisconnect(hdbc);
SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
SQLFreeHandle(SQL_HANDLE_ENV, henv);
return false;
}

return true;
}


void UnInitODBC(SQLHENV &henv, SQLHDBC &hdbc)
{
SQLDisconnect(hdbc);
SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
SQLFreeHandle(SQL_HANDLE_ENV, henv);
}

数据库操作在InitODBC 和 UnInitODBC 中间
...全文
223 2 打赏 收藏 转发到动态 举报
写回复
用AI写文章
2 条回复
切换为时间正序
请发表友善的回复…
发表回复
赵4老师 2017-08-07
  • 打赏
  • 举报
回复
使用try捕获该捕获的所有异常。 检查是否资源泄漏的办法之一: 在任务管理器 进程 查看 选择列 里面选择:内存使用、虚拟内存大小、句柄数、线程数、USER对象、GDI对象 让你的程序(进程)不退出,循环执行主流程很多遍,越多越好,比如1000000次甚至无限循环,记录以上各数值,再隔至少一小时,越长越好,比如一个月,再记录以上各数值。如果以上两组数值的差较大或随时间流逝不断增加,则铁定有对应资源的资源泄漏!
  • 打赏
  • 举报
回复
难道是申请太多了? 但每次都SQLDisconnect 和SQLFreeHandle 了。 不过这种每次使用就申请,应该会影响性能吧

3,881

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 其它技术问题
社区管理员
  • 其它技术问题社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧