百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

从源码角度看mysql数据库目录结构、核心库以及数据库启动过程

cac55 2024-10-19 02:54 19 浏览 0 评论

概述

今天主要从源码层面梳理mysql数据库目录结构、核心库以及启动过程中调用函数的顺序和作用。


1、MySQL目录结构

?build: 内含有各个平台、各种编译器下进行编译的脚本。如compile-pentium-debug表示在pentium架构上进行调试编译的脚本。
?client: 客户端工具,如mysql,mysqladmin之类。
?cmd-line-utils: readline,libedit工具。
?config: 给aclocal使用的配置文件。
?dbug: 提供一些调试用的宏定义。
?Docs: MySQL在不同平台下的参考手册
?extra: 提供innochecksum,resolveip等额外的小工具。
?include: 包含的头文件
?libmysql: 库文件,生产libmysqlclient.so。
?libmysql_r: 线程安全的库文件,生成libmysqlclient_r.so。
?libmysqld: 嵌入式MySQL Server库.
?libservices: 5.5.0中新加的目录,实现了打印功能。
?man: 适合man命令查看的帮助文件。
?mysql-test: mysqld的测试工具套件。
?mysys: 为实现跨平台,MySQL自己实现了一套常用的数据结构和算法,如string, hash等。还包含一些底层函数的跨平台封装,一般以my_开头。
?netware: 在netware平台上进行编译时需要的工具和库。
?plugin: MySQL 5.1开始支持一个插件式API接口,不需要重启mysqld即可动态载入插件,FullText就是一个例子。
?pstack: GNU异步栈追踪工具。
?regex: 正则表达式实现(来自多伦多大学Henry Spencer大牛的源码)。
?scripts: 提供脚本工具,如mysql_install_db/mysqld_safe等。
?server-tools: 包含instance_manager子目录,负责实例的本地和远程管理。
?sql: MySQL Server主要代码,将会生成mysqld文件。
?sql-bench: 一些基准测试代码代码,主要是Perl程序(虽然后缀是sh)。
?sql-common: 存放部分服务器端和客户端都会用到的代码,有些地方的同名文件是这里lin过去的。
?storage: 存储引擎所在目录。
?strings: string库,包含很多字符串处理的函数。
?support-files: my.cnf示例配置文件及编译所需的一些工具。
?tests: 测试文件所在目录。
?unittest: 单元测试文件。
?vio: 虚拟io系统,是对network io的封装,把不同的协议封装成统一的IO函数。
?win: 在windows平台编译所需的文件和一些说明。
?zlib: zlib算法库(GNU)

2、InnoDB目录结构

?btr: B+树的实现
?buf: 缓冲池的实现,包括LRU算法,Flush刷新算法等
?dict: InnoDB内存数据字典的实现
?dyn: InnoDB动态数组的实现
?fil: InnoDB文件数据结构以及对于文件的一些操作
?fsp: 对InnoDB物理文件的管理,如页/区/段等(即File Space)
?ha: 哈希算法的实现
?handler: 继承与MySQL的handler,实现handler API与Server交互
?ibuf: 插入缓冲(Insert Buffer)的实现
?include: InnoDB所有头文件都放在这个目录,是查找结构定义的最佳地点
?lock: InnoDB的锁实现及三种锁算法实现
?log: 日志缓冲(Log Buffer)和重做日志组(Redo Log)的实现
?mem: 辅助缓冲池(Additional Memory Pool)的实现,用来申请一些内部数据结构的内存
?mtr: 事务的底层实现(日志,缓冲)
?os: 封装一些对于操作系统的操作
?page: 页的实现,研究InnoDB文件结构,这个目录至关重要
?pars: 重载部分MySQL的SQL Parser(有待商榷)
?que: Query graph,基本上没啥用
?read: 读取游标的实现
?rem: 行管理操作(比较操作,打印等)
?row: 对于各种类型行数据操作的实现
?srv: InnoDB后台线程,启动服务,Master Thread,SQL队列等
?sync: InnoDB互斥变量(Mutex)的实现,基本同步机制
?thr: InnoDB封装的可移植线程库
?trx: 事务的实现
?usr: Session管理
?ut: 各种通用小工具

3、核心类库

?THD: 线程类
?Item: Item类(查询条目,函数,WHERE,ORDER,GROUP,ON子句等)
?TABLE: 表描述符
?TABEL_LIST: JOIN操作描述符
?Field: 列数据类型及属性定义
?LEX: 语法树
?Protocol: 通讯协议
?NET: 网络描述符
?handler: 存储引擎接口

4、核心函数库

4.1、内存操作:

?init_alloc_root: 内存池初始化,生成内存池根(MEM_ROOT)
?alloc_root: 申请内存池内存,从mem_root制定的内存池申请内存块
?free_root: 释放内存池,通过MyFlags指定哪种内存可以被释放

4.2、文件操作:

?my_open: 打开一个文件
?my_close: 关闭一个文件
?my_b_flush_io_cache: 讲数据从内存缓冲写到物理磁盘
?end_io_cache: 释放一个IO_CACHE对象

4.3、哈希操作:

?_hash_init: 初始化HASH描述符
?hash_search: 搜索哈希表,调用hash_first
?hash_first: 返回哈希表中找到的第一个行指针,否则返回0

4.4、字符串操作:

?strappend:填充字符串
?strmov: 移动字符串到新地址

5、主要函数

主要函数和流程包括:

1. 初始化系统变量和系统状态

2. 初始化服务器的各个模块

以下为源码层面各个函数的基本说明:

源码分析
main 
 mysqld_main(argc, argv) 
 | pre_initialize_performance_schema(); 初始化performance shcema相关内容
 | my_init() 
 | load_defaults(MYSQL_CONFIG_NAME, load_default_groups, &argc, &argv) 读取配置文件 
 | init_pfs_instrument_array 初始化performance shcema相关内容
 | handle_early_options 初始化部分变量,为mysqld初始化系统表等做准备
 | my_long_early_options变量设置,包括bootstrap、skip-grant-tables、help、verbose、version、initialize、initialize-insecure
 | init_sql_statement_names 初始化命令,为后续status统计操作数量做准备
 | sys_var_init() 初始化系统变量hash桶,将所有的系统变量插入到hash桶中(这里的变量为sys_vars.cc中定义的变量)
 | init_error_log 初始化error log 锁
 | mysql_audit_initialize 初始化audit plugin锁,为后续初始化audit plugin做准备
 | query_logger.init(); 初始化general log和slow log的锁
 | init_common_variables() 所有变量相关内容初始化,包括变量本身的值以及部分变量控制的特性
 | init_server_components() 服务器各个模块的初始化,包括
 | init_server_auto_options() 初始化UUID
 | if (gtid_state->read_gtid_executed_from_table() == -1) 从gtid_execute表中读取gtid_execute
 | if (opt_bin_log)
 | gtid_state->get_executed_gtids()/gtid_state->get_lost_gtids() .... 如果开启了binlog,则初始化gtid相关信息
 | 将gtid 信息更新到 mysql_bin_log中
 | 将表中记录的gtid信息与binlog同步(包括purge,crash recovery恢复等)
 | init_ssl()/network_init 初始化ssl和网络
 | create_pid_file(); 创建pid文件
 | acl_init(opt_noacl) 初始化用户名、密码等信息缓存,并将user表中的内容读取缓存
 | grant_init(opt_noacl) 初始化权限缓存,将tables_priv等表中的权限信息读取缓存
 | servers_init(0); 初始化mysql.servers表,并读入缓存
 | udf_init(); 初始化用户自定义函数
 | init_status_vars(); 初始化系统状态,system status排序
 | init_slave() 初始化slave相关的结构体
 如存在复制相关的信息,同时skip_slave_start未设置,则启动复制 
 | execute_ddl_log_recovery 执行ddl语句的crash recovery
 | start_signal_handler(); 创建信号处理线程,处理信号SIGTERM/SIGQUIT/SIGHUP
 | if (opt_bootstrap) error= bootstrap(mysql_stdin); 初始化数据目录、系统表
 | if (opt_init_file && *opt_init_file) read_init_file(opt_init_file) 从文件中初始化数据目录、系统表
 | mysqld_socket_acceptor->connection_event_loop(); 监听端口和sock文件,等待客户端连接
 init_common_variables() 所有变量相关的初始化
 | init_thread_environment 初始化全局mutex和condition
 | mysql_init_variables 设置部分全局变量的默认值
 | if (gethostname(glob_hostname,sizeof(glob_hostname)) < 0) ...... 生成pid文件
 | 设置默认存储引擎 
 | if (add_status_vars(status_vars)) 将全局变量status_vars中的系统 status存入all_status_vars中
 | get_options 将设置的系统变量的值更新到系统变量中
 | set_default_auth_plugin 设置默认的身份验证插件(通常为native_password)
 | set_server_version 设置mysql版本的后缀(-embedded、-log、-debug...)
 | init_errmessage/init_client_errs 初始化error message 
 | item_create_init/item_init 初始化所有的item类和函数(解析和后续执行使用)
 | 初始化 charset/collation
 | lex_init 初始化解析sql使用的lex
 | 初始化general log 和 slow log的日志名
get_options 将文件中、命令行中设置的参数,设置到系统参数中
 |将my_long_options存入all_options
 |将all_sys_vars存入all_options 所有的系统变量均已存入all_options中
 |将 {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}; 存入all_option 作为结束符
 |handle_options 
 |if (Connection_handler_manager::init()) 初始化连接管理模块
 |if (Global_THD_manager::create_instance()) 初始化线程管理模块
 init_server_components()
 | mdl_init 初始化mdl锁
 | table_def_init/hostname_cache_init/my_timer_initialize
 | init_server_query_cache query cache初始化
 | randominit 随机数初始化 
 | init_slave_list 初始化从机hash桶
 | transaction_cache_init() 事务缓存hash桶和锁初始化
 | delegates_init delegates用于执行回调函数
 | if (opt_bin_log) 如果变量中开启了binlog 
 | 生成binlog_index 和 binlog的文件名
 | if (opt_relay_logname) 如果变量中开启了relaylog
 | 生成relaylog_index 和 relay log的文件名
 | if (ha_init_errors()) 将handler模块的错误信息注册到mysqld的my_error中
 | if (gtid_server_init()) 初始化gitd结构体
 | if (plugin_init(&remaining_argc, remaining_argv ... 初始化所有的插件(包括编译、配置、命令行加载的参数)
 | query_logger.set_handlers(log_output_options); 初始化general log/slow log的日志处理模块
 | if (initialize_storage_engine(default_storage_engine, "".... 初始化默认的存储引擎
 | if (tc_log->open(opt_bin_log ? opt_bin_logname : opt_tc_log_file)) tc_log打开binlog,主要用于binlog和存储引擎的recovery使用,打开当前index中最后一个文件
 | if (ha_recover(0)) recovery
 | if (mysql_bin_log.open_binlog(opt_bin_logname, 0, mysql_bin_log打开binlog,生成新的binlog,在index文件中加入新的内容
 | mysql_bin_log.purge_logs_before_date(purge_time, true); 如果开启了复制,同时开启了binlog定期删除时间,删除过期的binlog
 | init_max_user_conn(void) 初始化连接hash桶
 | init_update_queries(); 初始化server_command_flags结构体,用于命令统计

入口函数在sql/main.cc文件中,里面只有一个函数,它又调用了mysqld_main,从这个函数开始到结束,就完成了mysqld的启动操作。

/* 
 main() for mysqld.
 Calls mysqld_main() entry point exported by sql library.
*/
extern int mysqld_main(int argc, char **argv);
int main(int argc, char **argv)
{
 return mysqld_main(argc, argv);
}

7、MySQL启动流程

主要代码在sql/mysqld.cc中,精简后的代码如下:

int main(int argc, char **argv) //标准入口函数
MY_INIT(argv[0]);//调用mysys/My_init.c->my_init(),初始化mysql内部的系统库
logger.init_base(); //初始化日志功能
init_common_variables(MYSQL_CONFIG_NAME,argc, argv, load_default_groups) //调用load_defaults(conf_file_name, groups, &argc, &argv),读取配置信息
user_info = check_user(mysqld_user);//检测启动时的用户选项
set_user(mysqld_user, user_info);//设置以该用户运行
init_server_components();//初始化内部的一些组件,如table_cache, query_cache等。
network_init();//初始化网络模块,创建socket监听
start_signal_handler();// 创建pid文件
mysql_rm_tmp_tables() || acl_init(opt_noacl)//删除tmp_table并初始化数据库级别的权限。
init_status_vars(); // 初始化mysql中的status变量
start_handle_manager();//创建manager线程
handle_connections_sockets();//主要处理函数,处理新的连接并创建新的线程处理

觉得有用的朋友多帮忙转发哦!后面会分享更多devops和DBA方面的内容,感兴趣的朋友可以关注下~

相关推荐

202心事咨询室 | 大学生因情感纠纷遭网暴,该如何自救?

专家:不必过度迎合外界认可,无需盲目扮演外向,内向的你正好踏实地学习本期来信人是一名因恋爱中隐瞒情感状态遭网络暴力的大学生。其在来信中坦言,长期讨好型人格、边界感模糊导致了人际关系崩坏。如今深陷舆论攻...

大学生必备神器:这个加速器让学习和游戏都起飞了

作为一个大学生,深知查学术文献的痛苦。最近发现了KO加速器这个神器,彻底解决了我访问学术网站的痛点,学习效率大大提升。那些年我们踩过的坑说起大学生活的网络痛点,相信每个人都有一肚子苦水:期末周赶论文时...

不抠图,怎么把英文图片转换为英文繁体图片?这4个工具试试!

当我们做跨境电商的时候,有时我们可能需要将英文图片转换为英文繁体图片。很多人可能不知道如何实现这一目标。有幸,有几个优秀的工具可以帮助我们达到这个目的,让我们一起来看看吧!1、看往ai图片工具看往ai...

Sublime Text 3 设置中文教程:没有中文选项?一招搞定界面汉化

刚装SublimeText3时,对着全英文界面犯愁——不是看不懂,就是觉得用着不亲切,想调成中文,翻遍设置也没找到“语言选项”。后来才知道,这款软件默认不自带中文包,得靠插件来汉化。试了...

《无人深空》简体中文及繁体中文切换方法

《无人深空》玩家们有不同的汉化需求。今天小编就给大家带来《无人深空》简体中文及繁体中文切换方法,一起来看吧。修改Binaries\CONFIG.ini内的Language=schinese改成Lang...

10秒教会你怎么英汉互译?_怎么汉翻译英

10秒教会你英汉互译怎么把汉字转换成英文。评论区的小伙伴问我怎么样把汉字变成英文,下面我就给大家操作一下。·首先打开微信,可以选择一个朋友,比如点开朋友在对话框里面,或者可以用一个文件传输助手,我今天...

电脑怎么设置中文?详细步骤请查收怎么给电脑设置中文

电脑作为现代科技的杰出代表,其各种功能令人叹为观止。其中,设置中文是电脑的基本功能之一,使得用户能够在母语环境中更加便捷地操作和交流。下面将详细介绍如何在电脑上设置中文语言,以满足用户的多样化需求。我...

真我V13如何设置简体中文 真我V13修改语言方法介绍

真我V13手机为用户们准备了多种语言,例如中文、英文、繁体以及其他外国语言等,但我们许多朋友一般还是使用简体中文的居多。下面一起瞧瞧真我V13设置简体中文的方法吧!真我V13修改语言方法介绍1、打开手...

输入法中的各种转换_输入法的转换快捷键

在输入法使用过程中,可能会遇到各种转换问题,有的转换在一种输入法间能够完成,有的则要借助于多种方法、多个平台、跨输入法来完成。熟悉输入法的各种转换问题,对轻松驾驭输入法进行信息处理会有很大帮助。1....

电脑打字繁体字怎么改回来_电脑打字繁体字怎么改回来快捷键

在电脑上改写繁体字可以通过使用中文输入法的转换功能或安装相关软件,如果是在线文字,可以使用在线繁简转换工具,如果是文字文件,可以使用相应的字体转换工具将文字文件改写成简体字。修改电脑字体详细教程:1....

如何转换 WPS文字中的繁体字和简体字?

在处理文档时,经常会遇到需要在了便捷的繁简体转换功能,让你轻松应对不同场景的需求。以下是详细的操作方法和技巧。一、使用菜单栏快速转换(一)转换整篇文档打开文档:在WPS文字中打开需要进行繁简体转换...

国家电网新一代电子商务平台ECP2.0供应商注册-平台注册篇问题

[平台注册】问题1:用户如何在ECP2.0平台上进行注册?用户登录国网新一代电子商务平台主页https://ecp.sgcc.com.cn/ecp2.0/portal/点击“注册”按钮,选择“供应商“...

Type-C小家电专用:受电端取电SINK芯片ECP5701

PD协议是一种充电协议,全称为“USBPowerDelivery(USBPD)”,是由USB-IF(USBImplementersForum)组织制定的一种标准协议。它是一种基于USB接口的...

现场爆满!国网ECP2.0 新系统投标业务能力提升班成都站开班

5月19日,由四川省电力企业协会举办的,电老虎网承办的【国网ECP2.0新系统投标业务能力提升班】在成都正式开班,为期三天。近百位学员参加了此次课程!这也是电老虎网举办投标业务能力提升班以来学员最多的...

1989年大营盘:我的初三补习年,苦里熬出不服输的光

一、九十年代的“补习潮”与我的“二次机会”九十年代的十八线小县城,“读书”是农村娃最现实的改命运路。那时“补习”是常态,有人为了考学甚至连补好几年——能考上小中专的是县城尖子生,考上高中的算二等生,而...

取消回复欢迎 发表评论: