mysql_init调用卡住原因分析

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介: mysql_init调用卡住原因分析.pdf 有同学做类似如下的操作: class X { public: X() /...

img_e25d4fb2f8de1caf41a735ec53088516.pngmysql_init调用卡住原因分析.pdf

有同学做类似如下的操作:

class X

{

public:

X() // 类X的构造函数ctor

{

_mysql_handler = mysql_init(NULL);

}
};

 

// 定义类X的全局变量

X g_x;

 

// 程序入口main函数

int main()

{

。。。 。。。

}

 

看似简单的代码,但非常不幸,程序运行时,卡在了mysql_init处。语法上看不出任何破绽,原因会是什么了?

 

他提供了另一个线索:不在构造函数中调用mysql_init则正常,不会卡住。结合起来分析,推断是因为mysql_init中也使用到了全局变量(另一种原因是有越界),而全局变量的初始化顺序程序是无法约定的,很有可能是因为g_x的初始化,发生在mysql_init依赖的全局变量之前。若推论成立,则mysql_init使用了未初始化的值,这是导致它卡住的根本原因。可以使用valgrind验证一下。当然,使用下列的方法应当也能奏效:全局变量相互依赖和初始化顺序的解决办法http://blog.chinaunix.net/uid-20682147-id-3245149.html),即改成:

#define g_x x_ref()

X& x_ref()

{

static X x; // 技巧就在这里

return x;

}

 

当然,良好的习惯是尽量避免使用全局变量,实在无法避免时(如考虑到结构的复杂性),则可以考虑用上述方法规避全局变量互依赖产生的问题。

 

附1:mysql_init源码

/****************************************************************************

  Init MySQL structure or allocate one

****************************************************************************/

 

MYSQL * STDCALL

mysql_init(MYSQL *mysql)

{

  if (mysql_server_init(0, NULL, NULL))

    return 0;

  if (!mysql)

  {

    if (!(mysql=(MYSQL*) my_malloc(sizeof(*mysql),MYF(MY_WME | MY_ZEROFILL))))

    {

      set_mysql_error(NULL, CR_OUT_OF_MEMORY, unknown_sqlstate);

      return 0;

    }

    mysql->free_me=1;

  }

  else

    memset(mysql, 0, sizeof(*(mysql)));

  mysql->charset=default_client_charset_info;

  strmov(mysql->net.sqlstate, not_error_sqlstate);

 

  /*

    Only enable LOAD DATA INFILE by default if configured with

    --enable-local-infile

  */

 

#if defined(ENABLED_LOCAL_INFILE) && !defined(MYSQL_SERVER)

  mysql->options.client_flag|= CLIENT_LOCAL_FILES;

#endif

 

#ifdef HAVE_SMEM

  mysql->options.shared_memory_base_name= (char*) def_shared_memory_base_name;

#endif

 

  mysql->options.methods_to_use= MYSQL_OPT_GUESS_CONNECTION;

  mysql->options.report_data_truncation= TRUE;  /* default */

 

  /*

    By default we don't reconnect because it could silently corrupt data (after

    reconnection you potentially lose table locks, user variables, session

    variables (transactions but they are specifically dealt with in

    mysql_reconnect()).

    This is a change: reconnect was set to 1 by default.

    How this change impacts existing apps:

    - existing apps which relyed on the default will see a behaviour change;

    they will have to set reconnect=1 after mysql_real_connect().

    - existing apps which explicitely asked for reconnection (the only way they

    could do it was by setting mysql.reconnect to 1 after mysql_real_connect())

    will not see a behaviour change.

    - existing apps which explicitely asked for no reconnection

    (mysql.reconnect=0) will not see a behaviour change.

  */

  mysql->reconnect= 0;

 

  mysql->options.secure_auth= TRUE;

 

  return mysql;

}

 

附2:mysql_server_init源码

/*

  Initialize the MySQL client library

 

  SYNOPSIS

    mysql_server_init()

 

  NOTES

    Should be called before doing any other calls to the MySQL

    client library to initialize thread specific variables etc.

    It's called by mysql_init() to ensure that things will work for

    old not threaded applications that doesn't call mysql_server_init()

    directly.

 

  RETURN

    0  ok

    1  could not initialize environment (out of memory or thread keys)

*/

 

int STDCALL mysql_server_init(int argc __attribute__((unused)),

      char **argv __attribute__((unused)),

      char **groups __attribute__((unused)))

{

  int result= 0;

  if (!mysql_client_init)

  {

    mysql_client_init=1;

    org_my_init_done=my_init_done;

    if (my_init()) /* Will init threads */

      return 1;

    init_client_errs();

    if (mysql_client_plugin_init())

      return 1;

    if (!mysql_port)

    {

      char *env;

      struct servent *serv_ptr __attribute__((unused));

 

      mysql_port = MYSQL_PORT;

 

      /*

        if builder specifically requested a default port, use that

        (even if it coincides with our factory default).

        only if they didn't do we check /etc/services (and, failing

        on that, fall back to the factory default of 3306).

        either default can be overridden by the environment variable

        MYSQL_TCP_PORT, which in turn can be overridden with command

        line options.

      */

 

#if MYSQL_PORT_DEFAULT == 0

      if ((serv_ptr= getservbyname("mysql", "tcp")))

        mysql_port= (uint) ntohs((ushort) serv_ptr->s_port);

#endif

      if ((env= getenv("MYSQL_TCP_PORT")))

        mysql_port=(uint) atoi(env);

    }

 

    if (!mysql_unix_port)

    {

      char *env;

#ifdef __WIN__

      mysql_unix_port = (char*) MYSQL_NAMEDPIPE;

#else

      mysql_unix_port = (char*) MYSQL_UNIX_ADDR;

#endif

      if ((env = getenv("MYSQL_UNIX_PORT")))

mysql_unix_port = env;

    }

    mysql_debug(NullS);

#if defined(SIGPIPE) && !defined(__WIN__)

    (void) signal(SIGPIPE, SIG_IGN);

#endif

#ifdef EMBEDDED_LIBRARY

    if (argc > -1)

       result= init_embedded_server(argc, argv, groups);

#endif

  }

  else

    result= (int)my_thread_init();         /* Init if new thread */

  return result;

}

 

 

相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
16天前
|
关系型数据库 MySQL 索引
mysql 分析5语句的优化--索引添加删除
mysql 分析5语句的优化--索引添加删除
13 0
|
3月前
|
关系型数据库 MySQL Serverless
高顿教育:大数据抽数分析业务引入polardb mysql serverless
高顿教育通过使用polardb serverless形态进行数据汇总,然后统一进行数据同步到数仓,业务有明显高低峰期,灵活的弹性伸缩能力,大大降低了客户使用成本。
|
3月前
|
关系型数据库 MySQL 索引
【MySQL 解析】Hash索引和B+树索引对比分析
【1月更文挑战第11天】【MySQL 解析】Hash索引和B+树索引对比分析
|
3月前
|
SQL 关系型数据库 MySQL
mysql事务原理分析
mysql事务原理分析
28 0
|
3月前
|
缓存 固态存储 关系型数据库
MySQL性能优化指南:深入分析重做日志刷新到磁盘的机制
MySQL性能优化指南:深入分析重做日志刷新到磁盘的机制
|
3月前
|
SQL 监控 关系型数据库
MySQL Metadata Locking(MDL)机制的实现与获取机制分析
MySQL Metadata Locking(MDL)机制的实现与获取机制分析 为了满足数据库在并发请求下的事务隔离性和一致性要求,同时针对MySQL插件式多种存储引擎都能发挥作用,MySQL在Server层实现了 Metadata Locking(MDL)机制。这种机制可以灵活自定义锁的对象、锁的类型以及不同锁类型的优先级,甚至可以做到在系统不同状态时动态调整不同锁类型的兼容性。本篇文章将详细介绍MDL系统中的常用数据结构及含义,从实现角度讨论MDL的获取机制与死锁检测,以及在实践中如何监控MDL状态。
36 2
|
27天前
|
SQL 关系型数据库 MySQL
【MySQL技术专题】「问题实战系列」深入探索和分析MySQL数据库的数据备份和恢复实战开发指南(8.0版本升级篇)
【MySQL技术专题】「问题实战系列」深入探索和分析MySQL数据库的数据备份和恢复实战开发指南(8.0版本升级篇)
96 0
|
16天前
|
SQL 缓存 关系型数据库
mysql性能优化-慢查询分析、优化索引和配置
mysql性能优化-慢查询分析、优化索引和配置
83 1
|
22天前
|
缓存 关系型数据库 MySQL
MySQL 查询优化:提速查询效率的13大秘籍(索引设计、查询优化、缓存策略、子查询优化以及定期表分析和优化)(中)
MySQL 查询优化:提速查询效率的13大秘籍(索引设计、查询优化、缓存策略、子查询优化以及定期表分析和优化)(中)
|
24天前
|
SQL 关系型数据库 MySQL
【MySQL】慢SQL分析流程
【4月更文挑战第1天】【MySQL】慢SQL分析流程