之前遇到过新闻网站过了几天打不开的情形,查日志发现了错误码是MySQL Server has gone away,最后定位到数据库连接的时间到期问题。
其中wait_timeout就是数据库连接的超时时间,单位为秒,28800秒即八小时。为了便于观察,先将其值改小,改成10s
mysql> set global wait_timeout=10;
mysql> show global variables like 'wait_timeout';
为了支持重连,查阅了MYSQL的帮助文档,找到了几个关键API:
mysql_options和mysql_ping
mysql_options:
int mysql_options(MYSQL *mysql, enum mysql_option option, const char *arg)
描述
可用于设置额外的连接选项,并影响连接的行为。可多次调用该函数来设置数个选项。
应在mysql_init()之后、以及mysql_connect()或mysql_real_connect()之前调用mysql_options()。
选项参量指的是你打算设置的选项。Arg参量是选项的值。如果选项是整数,那么arg应指向整数的值。
mysql_ping:
int mysql_ping(MYSQL *mysql)
描述
检查与服务器的连接是否工作。如果连接丢失,将自动尝试再连接。
该函数可被闲置了较长时间的客户端使用,用以检查服务器是否已关闭了连接,并在必要时再次连接。
返回值
如果与服务器的连接有效返回0。如果出现错误,返回非0值。返回的非0值不表示MySQL服务器本身是否已关闭,连接可能因其他原因终端,如网络问题等。
使用mysql_options函数来设置重连属性。
mysql_init(&mysql_);
my_bool reconnect = 0;
mysql_options(&mysql_, MYSQL_OPT_RECONNECT, &reconnect);
connection_ = mysql_real_connect(&mysql_, hostname_.c_str(), user_.c_str(),
password_.c_str(), dbName_.c_str(), 0, 0, 0);
重连函数:
void Mysql::reConnect()
{
LOG<<"重新连接。。。";
connection_ = mysql_real_connect(&mysql_, hostname_.c_str(), user_.c_str(),
password_.c_str(), dbName_.c_str(), 0, 0, 0);
mysql_query(connection_, "set names utf8");
}
然后再每次query之前调用mysql_ping看连接是否存在,如果连接丢失则重连。返回值为0代表连接未丢失。
if (mysql_ping(&mysql_) != 0 )
reConnect();
保守起见,等了20s,再次进行数据库访问,发现返回了正常的数据,查日志发现出现了MySQL Server has gone away错误,并且确实调用了reConnect函数进行了重连。
将数据库连接的超时时间重新修改为默认值。
每次查询都检查连接是否存在的效率问题?
每次查询都检查确实会带来效率问题,看函数名称就知道它是通过ping来判断连接是否存在的,那么可以设置一个时长,每隔一段时间检查连接是否存在,若不存在即刻重连。