Description:
1 using c xapi "mysqlx_get_session_from_options" create a session
2 using "mysqlx_sql execute" any statement such as "show databases;"
3 using "mysqlx_free" free the step 2's results
4 repeate step 2-3 many times, the memory will increase slowly...until the session closed
5 linux and windows both has problem
How to repeat:
here is my test code: run memoryTestOne and look up the memory occupy
bool MysqlApiTest::connect(mysqlx_session_t*& session_t, const bool withOpenssl,unsigned int& errcode, std::string& errstring)
{
if (session_t != NULL)
{
std::cout << "session_t not null release first\n";
try
{
mysqlx_session_close(session_t);
session_t = NULL;
}
catch (...)
{
std::cout << "mysqlx_session_close(session_t); exception";
}
session_t = NULL;
}
errcode = 0;
errstring = "";
mysqlx_session_options_t *opt = NULL;
mysqlx_error_t *error = NULL;
opt = mysqlx_session_options_new();
int optRes;
if (withOpenssl)
{
optRes = mysqlx_session_option_set(opt,
OPT_HOST(mIp.c_str()), OPT_PORT(mPort),
OPT_USER(mUser.c_str()), OPT_PWD(mPwd.c_str()),
OPT_DB(mDbName.c_str()),
//OPT_SSL_MODE(SSL_MODE_DISABLED),
// OPT_VIA_SSL_TIMEOUT(15),
PARAM_END);
}
else {
optRes = mysqlx_session_option_set(opt,
OPT_HOST(mIp.c_str()), OPT_PORT(mPort),
OPT_USER(mUser.c_str()), OPT_PWD(mPwd.c_str()),
OPT_DB(mDbName.c_str()),
OPT_SSL_MODE(SSL_MODE_DISABLED),
PARAM_END);
}
session_t = mysqlx_get_session_from_options(opt, &error);
mysqlx_free(opt);
if (session_t == NULL)
{
std::cout << "session null" << std::endl;
errcode = mysqlx_error_num(error); //if option error, mCurErrcode = 0
std::string str(mysqlx_error_message(error));
errstring = str;
std::cout << "code:" << errcode << ","<< str << std::endl;
mysqlx_free(error);
return false;
}
std::cout << "session create success" << std::endl;
if (error != NULL) {
mysqlx_free(error);
error = NULL;
}
return true;
}
void MysqlApiTest::disconnect(mysqlx_session_t*& session_t)
{
if (session_t == NULL)
{
std::cout << "session null when disconnect" << std::endl;
return;
}
mysqlx_session_close(session_t);
session_t = NULL;
}
void MysqlApiTest::memoryTestOne()
{
const std::string tag = "[memoryTestOne]";
std::cout<< tag << "begin.." << std::endl;
mysqlx_session_t* session_t = NULL;
unsigned int errcode = 0;
std::string errstring;
std::string stop;
const bool needopenssl = false;
if (!connect(session_t, needopenssl, errcode, errstring))
{
std::cout << tag << "connect fail, openssl:" << needopenssl << std::endl;
if (!connect(session_t, !needopenssl, errcode, errstring))
{
std::cout << tag << "connect fail, openssl:" << !needopenssl << std::endl;
return;
}
}
//cpuusage(tag);
bool needrun = true;
std::cout << "please input any thing to continue, enter q to quit:" << std::endl;
std::cin >> stop;
if (stop == std::string("q"))
{
needrun = false;
}
unsigned int count = 0;
while (needrun)
{
mysqlx_result_t* result = NULL;
std::string sql = "SHOW DATABASES;";
result = mysqlx_sql(session_t, sql.c_str(), sql.length());
count++;
if (result != NULL)
{
mysqlx_free(result);
result = NULL;
if(count % 5000 == 0)
std::cout << tag << " mysqlx_sql:" << count << std::endl;
}
else
{
errcode = mysqlx_error_num(session_t);
const char* errorChar = mysqlx_error_message(session_t);
if (errorChar != NULL)
{
errstring = errorChar;
}
std::cout << tag << "mysqlx_sql fail:" << errcode << "," << errstring << std::endl;
if (checkIsDisconnectErr(errcode))
{
std::cout << tag << "correct sql fail: IsDisconnectErr" << std::endl;
break;
}
}
if (count % 10000 == 0)
{
std::cout << tag << count << " please input any thing to continue, enter q to quit:" << std::endl;
std::cin >> stop;
if (stop == std::string("q"))
{
needrun = false;
}
//cpuusage(tag);//you can look up the memory occupy
std::this_thread::sleep_for(std::chrono::seconds(2));
}
}
disconnect(session_t);
}
Suggested fix:
In fact, the memory is occupyed by "mysqlx_stmt_struct" in session:
see this function, the stmt has not been released after mysqlx_sql and mysqlx_free for result won't free this too:
in fact the stmt could not be released here because the result will released together.
mysqlx_result_struct * STDCALL mysqlx_sql(mysqlx_session_struct *sess,
const char *query,
size_t query_len)
{
SAFE_EXCEPTION_BEGIN(sess, NULL)
mysqlx_stmt_struct *stmt = sess->sql_query(query, query_len);
mysqlx_result_struct *res = mysqlx_execute(stmt);
if (res == NULL)
SET_ERROR_FROM_STMT(sess, stmt, NULL);
return res;
SAFE_EXCEPTION_END(sess, NULL)
}
Description: 1 using c xapi "mysqlx_get_session_from_options" create a session 2 using "mysqlx_sql execute" any statement such as "show databases;" 3 using "mysqlx_free" free the step 2's results 4 repeate step 2-3 many times, the memory will increase slowly...until the session closed 5 linux and windows both has problem How to repeat: here is my test code: run memoryTestOne and look up the memory occupy bool MysqlApiTest::connect(mysqlx_session_t*& session_t, const bool withOpenssl,unsigned int& errcode, std::string& errstring) { if (session_t != NULL) { std::cout << "session_t not null release first\n"; try { mysqlx_session_close(session_t); session_t = NULL; } catch (...) { std::cout << "mysqlx_session_close(session_t); exception"; } session_t = NULL; } errcode = 0; errstring = ""; mysqlx_session_options_t *opt = NULL; mysqlx_error_t *error = NULL; opt = mysqlx_session_options_new(); int optRes; if (withOpenssl) { optRes = mysqlx_session_option_set(opt, OPT_HOST(mIp.c_str()), OPT_PORT(mPort), OPT_USER(mUser.c_str()), OPT_PWD(mPwd.c_str()), OPT_DB(mDbName.c_str()), //OPT_SSL_MODE(SSL_MODE_DISABLED), // OPT_VIA_SSL_TIMEOUT(15), PARAM_END); } else { optRes = mysqlx_session_option_set(opt, OPT_HOST(mIp.c_str()), OPT_PORT(mPort), OPT_USER(mUser.c_str()), OPT_PWD(mPwd.c_str()), OPT_DB(mDbName.c_str()), OPT_SSL_MODE(SSL_MODE_DISABLED), PARAM_END); } session_t = mysqlx_get_session_from_options(opt, &error); mysqlx_free(opt); if (session_t == NULL) { std::cout << "session null" << std::endl; errcode = mysqlx_error_num(error); //if option error, mCurErrcode = 0 std::string str(mysqlx_error_message(error)); errstring = str; std::cout << "code:" << errcode << ","<< str << std::endl; mysqlx_free(error); return false; } std::cout << "session create success" << std::endl; if (error != NULL) { mysqlx_free(error); error = NULL; } return true; } void MysqlApiTest::disconnect(mysqlx_session_t*& session_t) { if (session_t == NULL) { std::cout << "session null when disconnect" << std::endl; return; } mysqlx_session_close(session_t); session_t = NULL; } void MysqlApiTest::memoryTestOne() { const std::string tag = "[memoryTestOne]"; std::cout<< tag << "begin.." << std::endl; mysqlx_session_t* session_t = NULL; unsigned int errcode = 0; std::string errstring; std::string stop; const bool needopenssl = false; if (!connect(session_t, needopenssl, errcode, errstring)) { std::cout << tag << "connect fail, openssl:" << needopenssl << std::endl; if (!connect(session_t, !needopenssl, errcode, errstring)) { std::cout << tag << "connect fail, openssl:" << !needopenssl << std::endl; return; } } //cpuusage(tag); bool needrun = true; std::cout << "please input any thing to continue, enter q to quit:" << std::endl; std::cin >> stop; if (stop == std::string("q")) { needrun = false; } unsigned int count = 0; while (needrun) { mysqlx_result_t* result = NULL; std::string sql = "SHOW DATABASES;"; result = mysqlx_sql(session_t, sql.c_str(), sql.length()); count++; if (result != NULL) { mysqlx_free(result); result = NULL; if(count % 5000 == 0) std::cout << tag << " mysqlx_sql:" << count << std::endl; } else { errcode = mysqlx_error_num(session_t); const char* errorChar = mysqlx_error_message(session_t); if (errorChar != NULL) { errstring = errorChar; } std::cout << tag << "mysqlx_sql fail:" << errcode << "," << errstring << std::endl; if (checkIsDisconnectErr(errcode)) { std::cout << tag << "correct sql fail: IsDisconnectErr" << std::endl; break; } } if (count % 10000 == 0) { std::cout << tag << count << " please input any thing to continue, enter q to quit:" << std::endl; std::cin >> stop; if (stop == std::string("q")) { needrun = false; } //cpuusage(tag);//you can look up the memory occupy std::this_thread::sleep_for(std::chrono::seconds(2)); } } disconnect(session_t); } Suggested fix: In fact, the memory is occupyed by "mysqlx_stmt_struct" in session: see this function, the stmt has not been released after mysqlx_sql and mysqlx_free for result won't free this too: in fact the stmt could not be released here because the result will released together. mysqlx_result_struct * STDCALL mysqlx_sql(mysqlx_session_struct *sess, const char *query, size_t query_len) { SAFE_EXCEPTION_BEGIN(sess, NULL) mysqlx_stmt_struct *stmt = sess->sql_query(query, query_len); mysqlx_result_struct *res = mysqlx_execute(stmt); if (res == NULL) SET_ERROR_FROM_STMT(sess, stmt, NULL); return res; SAFE_EXCEPTION_END(sess, NULL) }