阅读本教程你需要提前知道的
1.本文参考的源码版本 mysql-5.7.38, 可能和8.0有区别, 请以实际版本为主.
2.不含初始化数据库(bootstrap/initialize), 不含win32 (_WIN32), 不含ia64, 尽量不含performance_schema
3.基础编程知识(c/c++,py,go,shell,js等均可) (*表示取指针的值, &表示取值的地址(指针))
4.不含流程图(懒得画)
5.不会详细讲具体的函数(太多了)
6.能力有限, 错误之处多多包涵.
主要是sql/mysqld.cc中的mysqld_main , 其它文件尽量不要涉及.
int mysqld_main(int argc, char **argv)
入口函数, 为啥不是main呢(1.#define mysqld_main main 2.gcc -nostartfiles -e mysqld_main). (我想起个段子 #define mian 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函数里面调用的
就是执行mysqld --datadir=xx --basedir=xx 的这个参数
orig_argc= argc;
orig_argv= argv;
my_getopt_use_args_separator= TRUE;
my_defaults_read_login_file= FALSE;
my_getopt_use_args_separator= FALSE;
defaults_argc= argc;
defaults_argv= argv;
remaining_argc= argc;
remaining_argv= argv;
system_charset_info= &my_charset_utf8_general_ci;
//error_log_print(enum loglevel level, const char *format, va_list args)
local_message_hook= error_log_print;
init_pfs_instrument_array();
所以参数 performance_schema
是只读的, 只能开机设置
ho_error= handle_early_options();
忽略未知参数,添加系统变量,添加命令行选项, 检查bootstrap和initialize/opt_initialize_insecure.
应该是为了兼容性的
这一块不熟... (LEX后面再看)
for (i= 0; i < ((uint) SQLCOM_END + 1); i++)
sql_statement_names[i]= empty;
系统变量初始化 (必须先初始化system_charset_info (第三步))
适配依赖关系选项(顺序不能改变,因为有依赖关系)
adjust_open_files_limit(requested_open_files);
adjust_max_connections(*requested_open_files);
adjust_table_cache_size(*requested_open_files);
adjust_table_def_size(); //依赖table_cache_size
初始化查询日志 slow log 和 general log 都需要这个玩意
刚才检查的参数, 现在才判断...
flush_error_log_messages();
exit (MYSQLD_ABORT_EXIT);
init_common_variables
后初始的命令行参数, 所以命令行参数的优先级要高.
初始化信号量的, 比如 SIGUSR1 is used to interrupt the socket listener
设置线程的堆栈大小的. pthread_attr_getstacksize
和参数 --keyring-migration-xxxx 相关的, 没用过, 就不做介绍了.
opt_keyring_migration_source
opt_keyring_migration_destination
migrate_connect_options
设置数据库数据目录
如果启用binlog就必须要server-id
(opt_bin_log && !(server_id_supplied) )
使用函数初始化一些内部的东西. 具体如下, 挺多的
mdl_init() //Initialize the metadata locking subsystem
partitioning_init()
table_def_init() | hostname_cache_init(host_cache_size)
my_timer_initialize()
init_server_query_cache() //这里初始的查询缓存,8.0没有
randominit()
setup_fpu()
init_slave_list //(ifdef HAVE_REPLICATION)
就是server-uuid 唯一表示服务器的, 没得就会自动创建, 路径在@@datadir 下面的 auto.cnf
初始化gtid(必须先初始化server-uuid)
从mysql/gtid_executed.ibd表读取gtid集
计算方式就不讲了, 太多了..... 懒得看.
初始化ssl 也挺复杂的....
初始化网络, 也是一堆... 成功就返回false (同init_ssl)
my_str_malloc= &my_str_malloc_mysqld; //my_malloc
my_str_free= &my_str_free_mysqld; //my_free
my_str_realloc= &my_str_realloc_mysqld; //my_realloc
跟客户端错误信息有关的
error_handler_hook= my_message_sql
创建pid文件, 并讲pid(getpid())写入文件(mysql_file_write), 然后关闭文件(mysql_file_close)
加载优化器成本配置表, 就是 mysql.server_cost 和 mysql.engine_cost
相关代码: sql/opt_costconstantcache.cc // c++写的
删除临时表
初始化权限(user/db) sql/auth/sql_auth_cache.cc
初始化时区
初始化权限(table/column)
servers_init(0) 初始化server, 0 表示要初始化 //bool servers_init(bool dont_read_servers_table)
具体内容如下:
mysql_rwlock_init //init the mutex
my_hash_init //initialise our servers cache
init_sql_alloc //Initialize the mem root for data
初始化服务器状态 sql/sql_show.cc //c++写的
就是检查BINLOG_CACHE_SIZE是不是比MAX_BINLOG_CACHE_SIZE大, 是的话, 就取MAX_BINLOG_CACHE_SIZE的值 (两者取其小)
就是检查 BINLOG_STMT_CACHE_SIZE是不是比MAX_BINLOG_STMT_CACHE_SIZE大.
定义binlog异常, 在sql/sql_lex.cc里的
就是配置文件里面的 slave-skip-errors=xxxx;
初始化从库信息, 前提是server_id != 0 //其实前面还设置了opt_skip_slave_start, 但是没必要. 太罗嗦了.
初始化information_schema. //sql/auth/sql_auth_cache.cc
执行内部DDL日志恢复.
就是启动的时候指定的 --init-file=name 这个是不需要权限认证的, 所以可以用来更改密码.
启动handle manager线程.(具体的后面再慢慢看)
创建压缩gtid的线程
主要是error_log_print
设置进程信号量
初始化super_read_only的值
设置服务器状态 server_operational_state=SERVER_OPERATING //默认是SERVER_BOOTING 关闭的时候是SERVER_SHUTTING_DOWN, 下面就会说的
设置mysql监听状态 socket_listener_active= true;
就是启动时候的参数 --daemonize 俗称 放后台
mysqld::runtime::signal_parent(pipe_write_fd,1); //1 means initialization complete and the serveris ready to accept client connections
就是循环处理客户端连接. 数据库会一直'堵'在这里
Connection_handler_manager *mgr= Connection_handler_manager::get_instance();
while (!abort_loop)
{
Channel_info *channel_info= m_listener->listen_for_connection_event();
if (channel_info != NULL)
mgr->process_new_connection(channel_info);
}
从这开始就是关闭流程了, 不在本文范围内
看完差不多就忘完了. 基本上都是各种初始化. 而且是c和c++混合写的. 感兴趣的可以使用strace验证下是不是这样的.
1.开启binlog必须要server-id!=0
2.可以通过--init-file修改root密码
3.可以通过skip-slave-start参数禁止slave自动启动
4.ddl log恢复是数据库启动的时候自动做的
5.权限分为系统级(user/db)权限和表级权限(table/column)
https://dev.mysql.com/doc/dev/mysql-server/latest/
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。