MYSQL源码分析(二)--主要代码流程

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

我们从MySQL启动开始,看一下MySQL业务流程。

★首先入口函数在目录sql/中:

int main(int argc, char **argv)

{

return mysqld_main(argc, argv);

}

调用了mysqld_main(argc, argv)函数,这个函数在sql/中

接着开始初始化:

★MY_INIT(argv[0]); 函数位于sql/my_,用于初始化mysql内部的系统库,MYSQL定义了大量的全局变量用于系统的状态值,这样省去很多函数之间的交互参数,这些全局变量定义在my_中。

★接着初始化变量sys_var_init();

★初始化审计接口(这部分用的不多,暂时不深入)mysql_audit_initialize();

★初始化日志功能logger.init_base();日志是系统的一个重要地方,mysql定义了一个logger 类,在文件sql/Logger.hpp中,里面定义了一系列的成员函数,具体可以参照logger.hpp 中的注释,很详细。(后续会专门针对日志模块做一次分析)

★接着就初始化配置信息了,

开始之后,又是一大堆全局变量初始化。

init_thread_environment()初始化线程环境。(这个就是线程池了)

mysql_init_variables()初始化配置变量,

这边给我最大的感悟就是,MYSQL在获取或者修改一些变量时,一定会先与之相关的系统变量都读出来确认一遍,全部没问题后才修改,有问题都会有相应的日志(所以日志模块必须最先初始化)

如果初始化失败,会调用mysql_server_end() ,而mysql_server_end()实际上是一个宏定义

#define mysql_server_end() mysql_client_plugin_deinit()宏定义也可以这样用

mysql_client_plugin_deinit()用于终止mysql server的线程。

★初始化server的模块init_server_components()

table_def_init() || hostname_cache_init(),初始化table cache

query_cache_init();初始化查询cache

#ifdef HAVE_REPLICATION

init_slave_list();如果有复制,还要初始化备机的状态list

#endif

后面还有一些cache初始化如

★network_init();//初始化网络模块,创建socket监听

这个流程和传统的tcp服务端代码基本一样,单独开启一个线程用于监听,set_ports();

函数用于初始化端口,默认为3306。

ip_sock= create_socket(ai, AF_INET, &a);

if (ip_sock == INVALID_SOCKET)

ip_sock= create_socket(ai, AF_INET6, &a);

// Report user-error if we failed to create a socket.

if (ip_sock == INVALID_SOCKET)

{

sql_perror(ER_DEFAULT(ER_IPSOCK_ERROR)); /* purecov: tested */

unireg_abort(1); /* purecov: tested */ }

现在IPV4上创建侦听,如果失败了,再在ipv6上创建侦听。

有时候,mysql所用的端口不会及时释放(重启,关闭的时候),这里有个算法for (waited= 0, retry= 1; ; retry++, waited+= this_wait)

{

if (((ret= bind(ip_sock, a->ai_addr, a->ai_addrlen)) >= 0 ) ||

(socket_errno != SOCKET_EADDRINUSE) ||

(waited >= mysqld_port_timeout))

break;

sql_print_information("Retrying bind on TCP/IP port %u", mysqld_port);

this_wait= retry * retry / 3 + 1;

sleep(this_wait);

}

他会按照

Sleep intervals: 1, 2, 4, 6, 9, 13, 17, 22, ...

Retry at second: 1, 3, 7, 13, 22, 35, 52, 74, ...

来省资源。

接着就是三种系统的侦听代码,原理都是一样的。

★start_signal_handler();// 创建pid文件

调用create_pid_file(),调用了自己封装的mysql_file_write()把内容写到了文件,mysql_file_write()也是个宏定义。

★if (mysql_rm_tmp_tables() || acl_init(opt_noacl) ||

my_tz_init((THD *)0, default_tz_name, opt_bootstrap))

删除tmp_table并初始化数据库级别的权限。

★init_status_vars(); 初始化mysql中的status变量

inlog_unsafe_map_init();

initialize_information_schema_acl();

execute_ddl_log_recovery();

create_shutdown_thread();

未启动先保护,这样异常出现时,系统不会直接崩掉,同时会尽可能的多保留下信息。

★start_handle_manager(); 创建manager线程

mysql_thread_create(key_thread_handle_manager,

&hThread, &connection_attrib, handle_manager, 0)

★handle_connections_sockets();

主要处理函数,

一系列异常保护之后,如果系统收到新的连接,就创建新的线程处理之

相关文档
最新文档