mysql 重新连接 c++
现在我有一个 C++ 客户端应用程序,它使用 mysql.h 连接到 MYSQL 数据库,并且必须执行一些逻辑,以防断开连接。我想知道这是否是在客户端断开连接的情况下重新连接 MYSQL 数据库的最佳方法。
bool MYSQL::Reconnect(const char *host, const char *user, const char *passwd, const char *db)
{
bool out = false;
pid_t command_pid = fork();
if (command_pid == 0)
{
while(1)
{
sleep(1);
if (mysql_real_connect(&m_mysql, host, user, passwd, db, 0, NULL, 0) == NULL )
{
fprintf(stderr, "Failed to connect to database: Error: %s\n",
mysql_error(&m_mysql));
}
else
{
m_connected = true;
out = true;
break;
}
}
exit(0);
}
if (command_pid < 0)
fprintf(stderr, "Could not fork process[reconnect]: %s\n", mysql_error(&m_mysql));
return out;
}
现在我获取所有参数并执行分叉。子进程每秒尝试使用 sleep() 语句重新连接。这是一个好方法吗?谢谢
Right now I have a C++ client application that uses mysql.h to connect to a MYSQL database and have to preform some logic in case there is a disconnect. I'm wondering if this is the best way to reconnect to a MYSQL database in a situation where my client gets disconnected.
bool MYSQL::Reconnect(const char *host, const char *user, const char *passwd, const char *db)
{
bool out = false;
pid_t command_pid = fork();
if (command_pid == 0)
{
while(1)
{
sleep(1);
if (mysql_real_connect(&m_mysql, host, user, passwd, db, 0, NULL, 0) == NULL )
{
fprintf(stderr, "Failed to connect to database: Error: %s\n",
mysql_error(&m_mysql));
}
else
{
m_connected = true;
out = true;
break;
}
}
exit(0);
}
if (command_pid < 0)
fprintf(stderr, "Could not fork process[reconnect]: %s\n", mysql_error(&m_mysql));
return out;
}
Right now i take in all my parameters and preform a fork. the child process attempts to reconnect every second with a sleep() statement. Is this a good way to do this? Thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
抱歉,您的代码没有按照您的想法执行,Kaiser Wilhelm。
从本质上讲,您试图将叉子视为线程,但事实并非如此。
当您分叉一个子进程时,父进程将被完全克隆,包括文件和套接字描述符,这就是您的程序连接到 MySQL 数据库服务器的方式。也就是说,当您分叉时,父级和子级最终都会获得与数据库服务器的相同连接的自己的副本。我假设父级仅在发现连接断开时调用此
Reconnect()
方法,并停止使用现已失效的 MySQL 连接对象m_mysql
的副本。如果是这样,当您开始重新连接操作时,父连接的副本与客户端的连接副本一样无用。问题是,反之亦然:一旦子进程成功重新连接到数据库服务器,父进程的连接对象仍然失效。孩子所做的任何事情都不会传播回父母。分叉后,两个进程完全独立,除非它们可能尝试访问它们最初共享的某些 I/O 资源。例如,如果您在连接建立时调用此
Reconnect()
并继续使用父级中的连接,则子级尝试在同一连接上与数据库服务器通信将会混淆mysqld
或libmysqlclient
,可能会导致数据损坏或崩溃。如上所述,解决此问题的一种方法是使用线程而不是分叉。但是,请注意使用线程的许多问题使用 MySQL C API。
如果有选择,我宁愿使用异步 I/O 在应用程序的主线程中进行后台连接尝试,但 MySQL C API 不允许这样做。
看来您在尝试重新连接数据库服务器时试图避免阻塞主应用程序线程。您可能可以通过设置来同步执行此操作连接超时为1秒,当MySQL服务器与客户端位于同一台机器或同一局域网上时,这很好。如果您可以容忍主线程因连接尝试失败而阻塞长达一秒钟(最坏的情况发生在服务器位于单独的计算机上并且物理上断开连接或设有防火墙时),那么这可能是比线程更干净的解决方案。如果服务器计算机仍在运行且端口未受防火墙保护,例如在重新启动且 TCP/IP 堆栈[仍然]运行时,连接尝试可能会更快失败。
Sorry, but your code doesn't do what you think it does, Kaiser Wilhelm.
In essence, you're trying to treat a fork like a thread, which it is not.
When you fork a child, the parent process is completely cloned, including file and socket descriptors, which is how your program is connected to the MySQL database server. That is, both the parent and the child end up with their own copy of the same connection to the database server when you fork. I assume the parent only calls this
Reconnect()
method when it sees the connection drop, and stops using its copy of the now-defunct MySQL connection object,m_mysql
. If so, the parent's copy of the connection is just as useless as the client's when you start the reconnect operation.The thing is, the reverse is not also true: once the child manages to reconnect to the database server, the parent's connection object remains defunct. Nothing the child does propagates back up to the parent. After the fork, the two processes are completely independent, except insofar as they might try to access some I/O resource they initially shared. For example, if you called this
Reconnect()
while the connection was up and continued using the connection in the parent, the child's attempts to talk to the DB server on the same connection would confuse eithermysqld
orlibmysqlclient
, likely causing data corruption or a crash.As hinted above, one solution to this is to use threads instead of forking. Beware, however, of the many problems with using threads with the MySQL C API.
Given a choice, I'd rather use asynchronous I/O to do the background connection attempt within the application's main thread, but the MySQL C API doesn't allow that.
It seems you're trying to avoid blocking your main application thread while attempting the DB server reconnection. It may be that you can get away with doing it synchronously anyway by setting the connect timeout to 1 second, which is fine when the MySQL server is on the same machine or same LAN as the client. If you could tolerate your main thread blocking for up to a second for connection attempts to fail — worst case happening when the server is on a separate machine and it's physically disconnected or firewalled — this would probably be a cleaner solution than threads. The connection attempt can fail much quicker if the server machine is still running and the port isn't firewalled, such as when it is rebooting and the TCP/IP stack is [still] up.
据我所知,这并没有达到您的预期。
逻辑问题
重新连接
根本不“在断开连接的情况下执行某些逻辑”。它会一遍又一遍地尝试连接,直到成功为止,然后停止。就是这样。连接状态不再被检查。如果连接断开,此代码对此一无所知。
技术问题
还要密切关注 Warren 提出的技术问题。
As far as I can tell, this doesn't do what you intended.
Logical issues
Reconnect
doesn't "perform some logic in case there is a disconnect" at all.It attempts to connect over and over again until it succeeds, then stops. That's it. The state of the connection is never checked again. If the connection drops, this code knows nothing about it.
Technical issues
Also pay close attention to the technical issues that Warren raises.
当然,完全没问题。您可能想考虑用类似的东西替换
while ( 1 )
循环,这是一种通过实践学习的习惯用法,但据我所知,您的代码工作得很好。不要忘记在
while
循环内放置一个计数器。Sure, it's perfectly OK. You might want to think about replacing the
while ( 1 )
loop with something likewhich is the kind of idiom that one learns by practice, but your code works just fine as far as I can see. Don't forget to put a counter inside the
while
loop.