‣ ‣ ‣ ‣
撕逼星球的plantegg老师提供了一个案例,大体上是阿里云的 sysbench 在压测mysql的时候在mysql 侧kill链接,发现sysbench没有重连QPS始终为0,而某些版本的sysbench则没有问题。
不符合预期的场景
符合预期的场景
在符合预期的场景中我们发现重连成功。QPS恢复。
在之前的文章中定位到大体上是因为依赖的问题造成的,异常的版本本 libmysqlclient_18 正常的版本是 libmysqlclient_21。
两者在接口上大部分传参一直,双方也有各自特有的API 例如 mariadb_reconnect (mariadb独占),mysql_get_ssl_session_reused(mysql 独占) 具体API差异可以查看后边的API文档。
sysbench 在重连处的逻辑如下
//sysbench/src/drivers/mysql/drv_mysql.c
static int mysql_drv_reconnect(db_conn_t *sb_con)
{
db_mysql_conn_t *db_mysql_con = (db_mysql_conn_t *) sb_con->ptr;
MYSQL *con = db_mysql_con->mysql;
// 注意这里做了close()
// 这个函数是libmysqlclient 动态库中提供的函数
mysql_close(con);
// 这里调用了自己的函数,返回值是 != 1 就一直循环
while (mysql_drv_real_connect(db_mysql_con))
{
if (sb_globals.error)
return DB_ERROR_FATAL;
usleep(1000);
}
// 返回了这个表示DB链接又可以使用了,直接用原来的 connection就行。
return DB_ERROR_IGNORABLE;
}
static int mysql_drv_real_connect(db_mysql_conn_t *db_mysql_con)
{
MYSQL *con = db_mysql_con->mysql;
... 省略了部分代码
// 这里又调用了 libmysqlclient 中提供的库。
return mysql_real_connect(con,
db_mysql_con->host,
db_mysql_con->user,
db_mysql_con->password,
db_mysql_con->db,
db_mysql_con->port,
db_mysql_con->socket,
CLIENT_MULTI_STATEMENTS
) == NULL;
}
libmysqlclient_18 mysql_close 中的逻辑如下
//mariadb-connector-c/libmariadb/mariadb_lib.c
void STDCALL
mysql_close(MYSQL *mysql)
{
if (mysql) /* Some simple safety */
{
...省略若干
// 注意这里
if (mysql->net.extension)
free(mysql->net.extension);
if (mysql->extension)
free(mysql->extension);
// 注意这里
mysql->net.extension = NULL;
mysql->extension = NULL;
mysql->net.pvio= 0;
if (mysql->free_me)
free(mysql);
}
return;
}