1 从mysqld的main()函数开始

一、sql/main.cc

extern int mysqld_main(int argc, char **argv);

int main(int argc, char **argv)
{
  return mysqld_main(argc, argv);
}
这就是mysqld的main()函数,它只是调用了mysql_main()。


二、mysqld_main

mysqld_main()位于sql/mysqld.cc中。sql/mysqld.cc中包含的头文件基本位于include/和sql/这两个文件夹下。下面看mysqld_main()的执行流程。


1、my_init()——init my_sys library & pthreads

其中static MYSQL_FILE instrumented_stdin.m_file= stdin;调用my_thread_global_init(),其中设置pthread_key_create(&THR_KEY_mysys, NULL)),mysql_mutex_init()初始化mutex(THR_LOCK_malloc, THR_LOCK_open, THR_LOCK_charset, THR_LOCK_threads以及之后的THR_LOCK_lock, THR_LOCK_isam,HR_LOCK_heap等)(见备注1),调用my_thread_init()初始化THR_KEY_mysys(见备注2),mysql_cond_init()初始化THR_COND_threads。


备注1:mysql_mutex_init(key_THR_LOCK_malloc, &THR_LOCK_malloc, MY_MUTEX_INIT_FAST)

key_THR_LOCK_malloc为PSI_mutex_key(unsigned int),THR_LOCK_malloc为struct mysql_mutex(主要成员是pthread_mutex_t m_mutex),该函数主要是初始化m_mutex。

备注2:my_thread_init()

执行pthread_setspecific(THR_KEY_mysys, tmp)(tmp为struct st_my_thread_var *);初始化这个tmp。


2、load_defaults()->my_load_defaults()

调用init_alloc_root()初始化MEM_ROOT *alloc;dirs=init_default_directories(&alloc)初始化目录数组(可能存放my.cnf的目录),数据保存在alloc管理的内存block中。my_init_dynamic_array()初始化用于存放argv参数的动态数组DYNAMIC_ARRAY args;my_search_option_files()先根据目录数组找到my.cnf(打开为MYSQL_FILE* fp),并提取参数,但尚未处理


3、init_sql_statement_names

初始化LEX_CSTRING sql_statement_names[ ]数组,内部存放着诸如"create_db" "insert"等对应于SQL语句的字符串。


4、sys_var_init

调用my_hash_init()初始化HASH* system_variable_hash;调用mysql_add_sys_var_chain(all_sys_vars.first)(注意all_sys_vars此时并不为空,它已经被初始化了,什么时候初始化的,见备注3),它将这些变量的指针存在system_variable_hash哈希表中。


备注3:all_sys_vars.first的类型是sys_var *,这是一个class,具有构造函数。在sql/sys_vars.cc中具有多个static变量(当我们在客户端使用SHOW VARIABLES LIKE 'perf%';时就可以看到这些变量),这些变量在程序一开始就得到了初始化,并链入了all_sys_vars.first中。


5、my_getopt_register_get_addr()设置getopt_get_addr = null(getopt_get_addr 类型为my_getopt_value,这是一个函数指针)。


6、sys_var_add_options(&all_early_options, sys_var::PARSE_EARLY)

all_early_options为DYNAMIC_ARRAY,该函数将all_sys_vars链表中每个sys_var的option字段的地址存入该动态数组all_early_options中。


7、buffered_logs.init()初始化Buffered_logs buffered_logs的成员MEM_ROOT m_root(注意Buffered_logs是一个类)。(这是第二次出现MEM_ROOT了,这里它应当是用于管理log缓存的)。备注Buffered_logs::print()就是用于将缓存的日志写到日志文件中。


8、my_getopt_error_reporter= buffered_option_error_reporter前者是个函数指针,后者这个函数作用就是将出错信息缓存到上一步中的buffered_logs中。


9、handle_options(&remaining_argc, &remaining_argv,(my_option*)(all_early_options.buffer), NULL)
这里remaining_argv是命令行和my.cnf中所有参数的集合,all_early_options是每个sys_var的option字段都存在此处,很明显该函数是处理各参数;同时可看出上一步的设置的作用:将解析参数时的出错信息也记录到日志中。不过这里并没有处理完(实际上我设置的参数和option字段都没关系,所以这里并没有设置option字段中的值)。在此之后,delete all_early_options。


10、init_error_log_mutex()初始化LOCK_error_log(类型为mysql_mutex_t)


11、mysql_audit_initialize()——Initialize Audit global variables:初始化LOCK_audit_mask锁(mysql_mutex_t)


12、logger.init_base()

logger的类型是class Logger(位于sql/log.h),Class which manages slow, general and error log event handlers。初始化log handler (class Log_to_file_event_handler,其中元素有mysql_log和mysql_slow_log)。


13、init_common_variables()见第三部分。

14、init_signals()信号相关初始化。

15、init_server_components()

table_def_init()初始化table_def_cache哈希表;hostname_cache_init()初始化hostname_cache;query_cache_init();ifdef HAVE_REPLICATION,init_slave_list(); process_key_caches(&ha_init_key_cache)初始化key caches;plugin_init(&remaining_argc, remaining_argv, ...)初始化剩余的参数(这是第三次处理),这些参数,这些与存储引擎相关,见下一篇,该函数还创建了很多线程;ha_init()初始化存储引擎;Set the default storage engine,并设置到global_system_variables.table_plugin中;ha_recover();


16、network_init()
创建tcp套接口ip_sock并监听,创建unix套接口unix_sock(需要创建文件mysqld.sock,注意需要给mysql用户添加文件夹写入权限)。


17、start_signal_handler()

创建线程signal_thread,线程处理函数为signal_hand();主线程等待该线程完成一些工作。signal_hand见第四部分。


18、mysql_rm_tmp_tables() || acl_init(opt_noacl) || my_tz_init()与数据表相关

acl_init():Initialize structures responsible for user/db-level privilege checking and load privilege information for them from tables in the 'mysql' database;

my_tz_init():Initialize time zone support infrastructure.


19、grant_init():Initialize structures responsible for table/column-level privilege checking and load information for them from tables in the 'mysql' database

20、servers_init(): Initialize structures responsible for servers used in federated server scheme information for them from the server table in the 'mysql' database

21、init_status_vars():Make all_status_vars[ ] usable for SHOW STATUS(注意add_status_vars()已在init_common_variables()中调用。)只是做了排序。

22、binlog_unsafe_map_init()?

23、init_slave():Initialize slave structures;其中pthread_key_create(&RPL_MASTER_INFO, NULL);初始化Master_info *active_mi。

24、execute_ddl_log_recovery()

25、Events::init(opt_noacl || opt_bootstrap)

26、start_handle_manager()实际上本例什么也没做(因为flush_time=0)

27、mysql_cond_signal(&COND_server_started):如果有某线程等待主线程启动,此时主线程通知它已启动。

28、handle_connections_sockets()

Handle new connections and spawn new process to handle them. 其中循环调用poll一直等待客户端连接。当连接到来时,accept,vio_new,my_net_init(&thd->net, vio_tmp),create_new_thread()处理连接;然后主线程继续循环等待新的连接。注意:对于本地,使用的是unix套接字。

备注:vio_new()初始化一个struct st_vio,设置了write、read等处理函数,封装了buffer相关处理;my_net_init()用这个st_vio去初始化thd->net(类型为struct st_net,该结构可看做client connection descriptor)。这样对io的处理进行了虚拟化。


29、当上述循环退出时,主线程等待ready_to_exit为1时,调用clean_up()和mysqld_exit()退出。


三、init_common_variables

1、init_thread_environment()初始化多个线程相关的锁;初始化connection_attrib(类型为pthread_attr_t);pthread_key_create(&THR_THD, NULL)。

2、初始化mysql_bin_log(类型为MYSQL_BIN_LOG,class MYSQL_BIN_LOG: public TC_LOG, private MYSQL_LOG)

3、设置pidfile_name为“hostname+.pid”,本例为“ubuntu.pid”。

4、default_storage_engine= const_cast<char *>("InnoDB")

5、add_status_vars(status_vars)创建all_status_vars这个动态数组,将status_vars各个数组的各项的指针存入动态数组中,类似于前面的all_early_options。

6、get_options(&remaining_argc, &remaining_argv)这里继续处理命令行和my.cnf中设置的参数。操作的是struct my_option my_long_options[ ]。不过还有一些关于innoDB的参数没有被处理。

7、设置open_files_limit(本例为1024)

8、unireg_init()设置error_handler_hook = my_message_stderr;my_disable_async_io=1

9、设置my_default_lc_messages为"en_US";global_system_variables.lc_messages= my_default_lc_messages

10、init_errmessage()初始化DEFAULT_ERRMSGS(即my_default_lc_messages->errmsgs->errmsgs,类型为char**,指向各种错误提示字符串)

11、init_client_errs():Register client error messages for use with my_error()

12、mysql_client_plugin_init():Initializes the client plugin layer

13、lex_init()初始化SYMBOL symbols[ ]

14、item_create_init():Load the hash table for native functions;将Native_func_registry func_array[ ]中的各项(好像是各种函数,位于sql/item_create.cc中)加入native_functions_hash这个哈希表。

15、item_init()初始化hash_user_locks哈希表和LOCK_user_locks锁。

16、get_charset_by_csname()初始化default_charset_info(本例初始化为utf8);初始化character_set_filesystem(本例为binary);my_locale_by_name()设置my_default_lc_time_names(本例为en_US)。这些量都被保存于global_system_variables中。

17、本例设置opt_logname为"/var/lib/mysql2/ubuntu.log",opt_slow_logname为"/var/lib/mysql2/ubuntu-slow.log"

18、bitmap_init()设置位图。

19、my_dboptions_cache_init()初始化dboptions这个哈希表。

20、初始化table_alias_charset(本例为&my_charset_bin,为"binary")。


四、signal_hand()

1、my_thread_init():以后分析。

2、init_thr_alarm():Setup alarm handler

3、 create_pid_file():创建pid.fill。(之后就可以唤醒主线程了)

4、之后是一直等待信号的到来,并相应处理。因此次线程就是一个信号处理线程。


本篇只是对mysqld的启动做了一个大概的认识,很多函数并未深入下去,下一篇将从客户端连接后,mysqld的处理来继续学习。看了mysqld的启动,觉得mysql确实是一个很庞大的东西,要学习的东西很多,只能在此先给自己加个油。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值