本文共 11558 字,大约阅读时间需要 38 分钟。
MySQL初始化过程与源代码分析
MySQL 在整体架构上分为 Server 层和存储引擎层。
其中 Server 层,包括连接器、查询缓存、分析器、优化器、执行器等,存储过程、触发器、视图和内置函数都在这层实现。数据引擎层负责数据的存储和提取,如 InnoDB、MyISAM、Memory 等引擎。在客户端连接到 Server 层后,Server 会调用数据引擎提供的接口,进行数据的变更。
单点(Single),适合小规模应用,复制(Replication),适合中小规模应用,集群(Cluster),适合大规模应用。
Bin ----mysql可执行文件
COPYING ----版权说明文件
Docs ----mysql文档信息
Include ----mysql的头文件、
Lib ----库文件
Man ----mysql手册信息
README ----说明文件
Share -----支持文件
support-files -----脚本-例如启动脚本
Boost -- 是为C++语言标准库提供扩展的一些C++程序库的总称
BUILD ----编译安装、一些脚本的目录
Client -----客户端工具 mysql,mysqladmin
Cmake -----编译工具
CMakeLists.txt -----
cmd-line-utils ----- 命令行工具 readline,libedit 工具
config.h.cmake ----- cmake 使用的配置文件
configure.cmake ----- cmake 使用的配置文件
COPYING ----- 版权信息
Dbug ----- 提供调试用的宏定义
Docs ----mysql在不同平台下的参考手册
Doxyfile-perfschema ---- 第三方组件
Extra ---- 小工具 如 innochecksum,resolveip
Include ---- 包含头文件
INSTALL ---- 安装说明
Libbinlogevents ----库文件
Libbinlogstandalone ----库文件
Libevent ----库文件
Libmysql ----库文件
Libmysqld ----库文件
Libservices ----库文件
Man ----帮助手册
mysql-test ----mysql的测试工具套件
Mysys ----string,hash等,与跨平台相关的数据结构和算法。
mysys_ssl
Packaging -—针对不同OS启动停止相关的内容
Plugin -- mysgl相关的插件
Rapid --与身份认证相关的插件
README --说明文档
Regex --正则表达式实现,一些源码
Scripts --提供了一些脚本工具 mysql_install_db/mysqld_safe
Sql -- mysql server主要代码的实现,生成mysld文件
sql-common --存放了部分服务器端和客户端会用到的代码。
Storage --存储引擎所在的目录
Strings strings库包含很多字符串处理的函数
support-files --案例配置文件my .cnf,还有一些其它的脚本和工具
Testclients --测试文件所有的目录
Unittest 一一单元测试文件
VERSION 一一版本号
Vio 虚拟I0系统,network io的封闭,一些IO函数
Win --在win平台编译所需的文件和一些说明
Zlib --zlib算法库
Sql -- mysql server主要代码的实现,生成mysld文件
sql-common --存放了部分服务器端和客户端会用到的代码。
Storage --存储引擎所在的目录
1sourceinsight
2.写字板/记事本UE
3.gdb
2 一般使用notepad++ 就可以了
-- GDB for mysql:
1.识别故障
2.场景重现
3.创建测试案例确认bug
4 定位缺陷根源
5.测试和创建补丁修复bug.
--安装GDB
安装OS过程中选择开发包
yum install cmake make gcc gcc-c++ ncurses-devel bison gdb
如果编译安装MYSQL,需要加参教:-DWITH_DEBUG=1
mysqld
mysqld_safe
mysql.server
mysqld_mutil
进程被kill以后,不会重启。
mysqld --defaults-file=/mysql/data/3306/my.cnf --user=mysql &
5082
mysqld_safe是一个shell脚本,调用mysqld命令,进行服务器监听。如果mysqld进程掉了,会自动启mysqld。
mysqld_safe --defaults-file=/mysql/data/3306/my.cnf --user=mysql &
mysql.server > mysqld_safe > mysqld服务器程序
service mysql start
service mysql stop
service mysql restart
/mysql/app/mysql/support-files里面有mysql.server可以做成启动和停止脚本,也可以做出开机自启动。
需要修改的地方把basedir和datadir修改成争取的参数
basedir=/mysql/app/mysql
datadir=/mysql/data/3306/data
设置pid文件
mysqld_pid_file_path=/mysql/data/3306/mysql.pid
修改启动命令
$bindir/mysqld_safe --datadir="$datadir" --pid-file="$mysqld_pid_file_path" $other_args >/dev/null &
增加启动的参数文件
$bindir/mysqld_safe --defaults-file=/mysql/data/3306/my.cnf --datadir="$datadir" --pid-file="$mysqld_pid_file_path" $other_args >/dev/null &
把文件copy到/etc/init.d/
cp mysql.server /etc/init.d/mysql
制作完脚本以后-总是报错-吧/etc/my.cnf删除解决。
[root@mysql5 3306]# service mysql start
Starting MySQL.The server quit without updating PID file (/[失败]data/3306/mysql.pid).第一个是 rm -rf /etc/my.cnf
第二个是 $bindir/mysqld_safe --defaults-file=/mysql/data/3306/my.cnf --datadir="$datadir" --user=mysql --pid-file="$mysqld_pid_file_path" $other_args >/dev/null &
是主参数,需要再mysqld_safe以后马上就是。
net start mysql
net stop mysql
也可以手工点服务,启动和停止。
[root@mysql5 ~]# mysql --verbose --help | grep my.cnf
order of preference, my.cnf, $MYSQL_TCP_PORT,
/etc/my.cnf /etc/mysql/my.cnf /usr/local/mysql/etc/my.cnf ~/.my.cnf
读取my.cnf顺序,虽然指定了/mysql/data/3306/my.cnf,也会先去读取上面的文件。如果上面已经又配置配件了,就会造成异常。
源码:mysys_ssl lmy_default.cc
MySQL的启动方式通常分成三种:mysqld、mysqld_safe、mysqld_multi(主要用于多实例启动)
首先当我们使用service mysqld start或者/etc/init.d/mysqld start这样的方式启动的时候,其实是使用了mysql.server这个脚本。
这个脚本默认会调用mysqld_safe来启动mysqld,所以通常我们启动mysql之后查看进程的时候会发现有mysqld和mysqld_safe这两个进程存在。
这两种通常都是单实例的启动方式,当然也可以使用mysqld来启动多实例的。
而mysqld_multi用来启动多实例,也是通过先调用mysqld_safe和mysqld来启动mysql的。
默认的mysql的服务启动程序是mysql.server,mysql.server程序主要是会用到两个程序和一个函数,分别是my_print_defaults、 myslqd_safe和parse_server_arguments。
1、my_print_defaultsq读取my.cnf配置文件,输出参数传递给parse_server_arguments,该程序只读my.cnf中[mysqld]中的参数。
2、parse_server_arguments:该函数处理my_print_defaults传递过来的参数赋值给--basedir、--datadir、--pid-file、--server-startup-timeout
3、mysqld_safe:mysqld_safe程序调用mysqld程序来启动mysql服务,[mysqld_safe]会覆盖mysqld部分中的参数
4、mysqld_multi会读取配置文件中的[mysqld_muti],[mysqldN]下面的参数,N需要时一个整数,建议用端口号表示,该部分的配置会覆盖[mysqld]部分中的配置
5、在mysqld进程挂掉的时候,mysqld_safe进程会监测到并重新将mysqld启动起来。
mysql.server主要分3大部分:
变量初始化部分,函数申明部分,具体执行部分
cd /mysql/app/mysql/support-files/
cat /mysql/app/mysql/support-files/mysql.server
指定mysql安装程序及数据的路径,默认是/usr/local/mysql basedir=/mysql/app/mysql
datadir=/mysql/data/3306/data
定义mysql服务启动时间的限制,如果超过900S没有启动,脚本会退出。
service_startup_timeout=900
判断mysql是否启动
# Set some defaults
mysqld_pid_file_path=/mysql/data/3306/mysql.pid
判断指定目录是否为空
if test -z "$basedir"
then
basedir=/usr/local/mysql
bindir=/usr/local/mysql/bin
if test -z "$datadir"
then
datadir=/usr/local/mysql/data
fi
sbindir=/usr/local/mysql/bin
libexecdir=/usr/local/mysql/bin
else
bindir="$basedir/bin"
if test -z "$datadir"
then
datadir="$basedir/data"
fi
sbindir="$basedir/sbin"
libexecdir="$basedir/libexec"
fi
#
# Use LSB init script functions for printing messages, if possible
#
# Use LSB init script functions for printing messages, if possible
#
lsb_functions="/lib/lsb/init-functions"
if test -f $lsb_functions ; then
. $lsb_functions
else
log_success_msg()
{
echo " SUCCESS! $@"
}
log_failure_msg()
{
echo " ERROR! $@"
}
Fi
首先判断函数是否存在,lsb_functions="/lib/lsb/init-functions"
不存在打印失败。会出现因为linux版本不一样,导致mysql启动失败的案例。可以修改脚本例如把lsb_functions="/lib/lsb/init-functions"变成 lsb_functions="/etc/init.ds/init-functions" 目前还没有遇到,肯定会遇到的。
原来的版本
$bindir/mysqld_safe --datadir="$datadir" --pid-file="$mysqld_pid_file_path" $other_args >/dev/null &
case "$mode" in
'start')
# Start daemon
# Safeguard (relative paths, core dumps..)
cd $basedir
echo $echo_n "Starting MySQL"
if test -x $bindir/mysqld_safe
then
# Give extra arguments to mysqld with the my.cnf file. This script
# may be overwritten at next upgrade.
$bindir/mysqld_safe --defaults-file=/mysql/data/3306/my.cnf --datadir="$datadir" --pid-file="$mysqld_pid_file_path" $other_args >/dev/null &
标红为增加的,正常是没有的。
wait_for_pid created "$!" "$mysqld_pid_file_path"; return_value=$?
# Make lock for RedHat / SuSE
if test -w "$lockdir"
then
touch "$lock_file_path"
fi
exit $return_value
else
log_failure_msg "Couldn't find MySQL server ($bindir/mysqld_safe)"
fi
;;
A.检查环境
B检查配置选项
C.启动mysqld及启动后的一些处理
A.安全性相对好
B.启动时指定一些关于mysqld_safe的参数,也可以放在my.cnf里面的[mysqd_safe]下面
C.ulimit -c $core_file_size
D.ulimit -n $size
E 检查环境,检查配置文件,检查指定的选项.
[root@mysql5 ~]# mysqld_safe --help
Usage: /mysql/app/mysql/bin/mysqld_safe [OPTIONS]
The following options may be given as the first argument:
--no-defaults Don't read the system defaults file
--defaults-file=FILE Use the specified defaults file
指定的参数文件
--defaults-extra-file=FILE Also use defaults from the specified file
不会去用
Other options:
--ledir=DIRECTORY Look for mysqld in the specified directory
--open-files-limit=LIMIT Limit the number of open files
--core-file-size=LIMIT Limit core files to the specified size
--timezone=TZ Set the system timezone
--malloc-lib=LIB Preload shared library LIB if available
--mysqld=FILE Use the specified file as mysqld
--mysqld-version=VERSION Use "mysqld-VERSION" as mysqld
--nice=NICE Set the scheduling priority of mysqld
--plugin-dir=DIR Plugins are under DIR or DIR/VERSION, if
VERSION is given
--skip-kill-mysqld Don't try to kill stray mysqld processes
--syslog Log messages to syslog with 'logger'
--skip-syslog Log messages to error log (default)
--syslog-tag=TAG Pass -t "mysqld-TAG" to 'logger'
--mysqld-safe-log- TYPE must be one of UTC (ISO 8601 UTC),
timestamps=TYPE system (ISO 8601 local time), hyphen
(hyphenated date a la mysqld 5.6), legacy
(legacy non-ISO 8601 mysqld_safe timestamps)
All other options are passed to the mysqld program.
1、查找basedir和ledir.
2、查找datadir和my.cnf。
3、对my.cnf做一些检查,具体检查哪些选项。
4、解析my.cnf中的组[mysqld]和[mysqld_safe]并和终端里输入的命令合并。
5、调用parse_arguments函数解析用户传递的所有参数($)。
6、对系统日志和错误日志的判断和相应处理具体,及选项--err-log参数的赋值。
8、启动mysqld.
7、对选项--user,--pid-file,--socket及--port进行处理及赋值,保证启动时如果不给出这些参数它也会有值。
a)启动时会判断一个进程号是否存在,如果存在那么就在错误日志中记录"A mysqld process already exists"并且退出。
b)如不存在就删除进程文件,如果删除不了,那么就在错误日志中记录"Fatal error:Can't remove the pid file"并退出。
9、启动时对表进行检查。如果启动的时候检查表的话设置key_buffer and sort_buffer会提高速度并且减少磁盘空间的使用。
10、如果启动时你什么参数都没有给,那么它会选用一些特定的参数启动。
11、如果服务器异常关闭,那么会restart。
mysql.server,mysqld_safe,mysqld
service mysql stop
Shutting down MySQL.... [确定]
mysqladmin -u root -p shutdown -S /mysql/data/3306/mysql.sock
Enter password:
Kill –不建议
1)发起shutdown
2)如果需要是否新建一个关闭线程shutdown thread,如果是客户端发起的关闭,就会建一个专用的关闭线程。
3) mysql server不再响应新的连接请求,关闭tcp/ip网络监听,关闭unix/linux的socket等通道。
4)逐渐关闭当前的连接/事务,空闲将立即被终止
5)mysql server进程关闭所有的线程,关闭所有的存储引擎,innodb会将buffer pool刷新到磁盘中,把当前的LSN记录到表空间中,然后再关所有的内部线程。
6) mysql进程退出
Mysql 5.0以上默认是1,1允许快速关闭DB。
show variables like 'innodb_fast%';
+----------------------+-------+
| Variable_name | Value |
+----------------------+-------+
| innodb_fast_shutdown | 1 |
+----------------------+-------+
1 row in set (0.00 sec)
0,代表当MYSQL关闭时,Innodb需要完成所有full purge和merge insert buffer操作,这需要花费时间来完成。如果做Innodb plugin升级,通常需要将这个参数调为0,,然后在关闭数据库
1, 是参数的默认值,不需要完成full purge和merge insert buffer操作,但是在缓冲池的一些数据脏页还是会刷新到磁盘。
2 表示 不需要完成full purge和merge insert buffer操作 ,也不将缓冲池中的数据脏页写回磁盘,。而是将日志都写入日志文件。这样不会有任何事物丢失,但是mysql在下次启动时,会执行恢复操作(recovery)
刷脏页75%左右 innodb_max_dirty_pages_pct=0,让innodb把所有的脏页刷新到磁盘中。
show variables like 'innodb_max%';
+--------------------------------+------------+
| Variable_name | Value |
+--------------------------------+------------+
| innodb_max_dirty_pages_pct | 75.000000 |
| innodb_max_dirty_pages_pct_lwm | 0.000000 |
| innodb_max_purge_lag | 0 |
| innodb_max_purge_lag_delay | 0 |
| innodb_max_undo_log_size | 2147483648 |
+--------------------------------+------------+
show processlist;
+----+------+-----------+------+---------+------+----------+------------------+
| Id | User | Host | db | Command | Time | State | Info |
+----+------+-----------+------+---------+------+----------+------------------+
| 3 | root | localhost | NULL | Query | 0 | starting | show processlist |
| 4 | root | localhost | NULL | Sleep | 6 | | NULL |
mysql> kill 4;
Query OK, 0 rows affected (0.00 sec)
select concat('KILL ',id, ' ; ') from information_schema.processlist where user='root';
+---------------------------+
| concat('KILL ',id, ' ; ') |
+---------------------------+
| KILL 3 ; |
+---------------------------+
1 row in set (0.00 sec)
show engine innodb status\G
History list length 0
---低于500,也就是没有被purge的事务是不是很少
Log sequence number 66341939
Log flushed up to 66341939
Pages flushed up to 66341939
Last checkpoint at 66341930
0 pending log flushes, 0 pending chkp writes
如果差值比较大,需要刷表
flush tables;
Query OK, 0 rows affected (0.00 sec)
如果是salve服务器,最好是先关io线程,等所有的中断日志relay log都应用完了后再关sql线程,如果有大事物,一定要等大事务结束后再关sql线程。
在关闭mysql服务器。
mysql --help | grep my.cnf
order of preference, my.cnf, $MYSQL_TCP_PORT,
/etc/my.cnf /etc/mysql/my.cnf /usr/local/mysql/etc/my.cnf ~/.my.cnf
转载地址:http://exbai.baihongyu.com/