MYSQL-DBA
MySQL简介
MySQL 相关产品介绍
Oracle MySQL Cloud Service (commercial)商业付费软件,基于 MySQL 企业版和 Oracle 云服务提供企业级的 MySQL 数据库服务
MySQL Enterprise Edition (commercial)商业付费软件,除了提供 MySQL 数据库服务之外,又包含了 connector (程序连接接口),partition (表分区),企业级的 monitor (监控),HA (高可用),backup (备份),Scalability (扩展) 等服务
MySQL Cluster CGE (commercial)商业付费软件,基于 MySQL Cluster 和企业版拥有的各项功能提供企业级的高并发、高吞吐的数据库服务
MySQL Community Edition免费社区软件,提供基础的数据库服务和其他衍生服务
MySQL 社区软件相关产品介绍
MySQL Community Server:MySQL社区服务器最流行的开源数据库管理软件
MySQL Cluster MySQL Cluster:基于 MySQL 数据库而实现的集群服务,自身能提供高并发高负载等特性
MySQL Fabric:MySQL Fabric MySQL 官方提供的关于 MySQL 数据库高可用和数据分片的解决方案
MySQL Connectors MySQL连接:为应用程序提供 JDBC/ODBC 等访问 MySQL 数据库的接口服务
mysql5.0之上各版本之间区别
MySQL 5.1(2008 年发布 )
新增功能:增加了 Event scheduler(事件调度器,可定时执行任务 )、Partitioning(表分区功能,利于大数据量管理 )、Pluggable storage engine API(可插拔存储引擎 API,方便扩展存储引擎 ) 、Row - based replication(基于行的复制,改善复制性能 );支持 Global 级别动态修改 general query log 和 slow query log。
存储引擎特性:类似增加崩溃恢复功能的 MyISAM,使用表级锁,能实现读写不冲突,即写操作时可读,但多个写操作不能并发 。
MySQL 5.5(2010 年 12 月发布 )
存储引擎变更:默认存储引擎从 MyISAM 改为 InnoDB 。
性能提升:提高默认线程并发数等参数控制 ;可处理高达 128K 的并发事务,改善事务处理中元数据锁定 ;增加删除缓冲和清除缓冲等 ;引入性能架构监控运行时性能。
功能增强:支持半同步复制,提高数据复制安全性;增加与 InnoDB 压缩和事务处理锁定有关的 INFORMATION_SCHEMA 表 ;表和索引 RANG 和 LIST 分区范围扩展到非整数列和日期 ,且支持多列分区 。
MySQL 5.6(2013 年 2 月发布 )
InnoDB 改进:可限制大量表打开时内存占用过多问题 ;性能加强 ;死锁信息可记录到 error 日志 。
复制功能优化:支持延时复制,便于特殊情况数据恢复 ;行级复制功能加强,降低资源开销 ;复制事件采用 crc32 校验,增强主从复制数据一致性 。
其他增强:表分区功能进一步增强 ;新增 log_bin_basename ,方便监管 binlog 位置 。
MySQL 5.7(2015 年发布 )
性能大幅提升:查询性能相比 5.6 提升约 1 倍 ,降低建立数据库连接时间 。
安装程序改进:安装相关调整,如废弃 mysql_install_db ,使用 mysqld –initialize 替代 。
MySQL 8.0(后续版本 )
性能提升:读写、I/O 密集型、高竞争等工作负载性能比 5.7 快 2 倍 。
安全性增强:增加隐藏用户密码、强密码策略、加密密码传输、更好身份验证等功能 。
数据类型扩充:添加更多数据类型,满足现代应用对非结构化数据存储和操作需求 。
管理功能丰富:提供更好的管理监控、健康监测、性能优化、复制、备份恢复、分区等选项 。
集成优化:具备更好的 MySQL Router 选项以及连接命令 。
MySQL 各版本的发布时间线
1995 年:MySQL 1.0 发布(仅供内部使用 )。
1996 年:MySQL 3.11.1 发布 ,直接跳过了 MySQL 2.x 版本 。
1999 年:MySQL AB 公司成立 ;同年发布 MySQL 3.23,该版本集成了 Berkeley DB 存储引擎。
2000 年:ISAM 升级为 MyISAM 存储引擎 ;同年,MySQL 基于 GPL 协议开放源码。
2002 年:MySQL 4.0 发布,集成了 InnoDB 存储引擎。
2005 年:MySQL 5.0 发布 ,开始支持游标、存储过程、触发器、视图、XA 事务等特性。
2008 年:Sun 以 10 亿美金收购 MySQL AB ;同年,发布 MySQL 5.1 ,开始支持定时器(Event scheduler)、分区、基于行的复制等特性 。
2010 年:MySQL 5.5 发布 ,InnoDB 成为默认的存储引擎 。
2013 年:MySQL 5.6 发布 ,支持全局事务等 。
2015 年:MySQL 5.7 发布 ,提升性能,支持 CTE(通用表表达式)、窗口函数、JSON 支持、Instant DDL(即时数据定义语言操作)等现代化功能 。
2016 年:MySQL 8.0.0 版本发布 。
2018 年:MySQL 8.0 正式发布,引入诸多新特性 。
2020 年:MySQL HeatWave 推出 ,支持内存加速和机器学习功能 。
2024 年:发布 MySQL 8.4 LTS(长期支持版)和 9.0 。
操作系统与 MySQL 版本适配度
操作系统 | 系统版本 | MySQL 5.6 | MySQL 5.7 | MySQL 8.0 | MySQL 9.0 |
---|---|---|---|---|---|
Windows 窗户 | Windows 7 | ✔ | ❌ | ❌ | ❌ |
Windows 8 及以上 | ✔ | ✔ | ✔ | ✔ | |
Windows 10 及以上 | ✔ | ✔ | ✔ | ✔ | |
Linux | Debian/Ubuntu 系列 | ✔(最高适配到 Ubuntu 17.04 ) | ✔(最高适配到 Ubuntu 18.04 ) | ✔ | ✔ |
RedHat/CentOS 系列 | ✔ | ✔ | ✔ | ✔ | |
macOS 操作系统 | - | ✔ | ✔ | ✔ | ✔ |
MySQL文档
https://dev.mysql.com/doc/
MySQL安装
MySQL8+Linux为例
二进制安装(RPM、ZIP、Tar)
https://dev.mysql.com/downloads/repo/yum/
https://dev.mysql.com/doc/mysql-apt-repo-quick-guide/en/
请参考以上网站
源码安装
参考官网文档
二进制解压安装
下载
mysql-8.0.14-linux-glibc2.12-x86_64.tar.xz
解压
mysql-8.0.14-linux-glibc2.12-x86_64.tar.xz
mysql8.0的目录结构
bin:存放 MySQL 的可执行文件,如
mysqld
(服务器守护进程 )、mysql
(命令行客户端 )等,用于启动服务器、执行 SQL 语句等操作。docs:存储 MySQL 相关的文档资料,如用户手册、技术参考等,方便用户查阅了解 MySQL 功能特性、使用方法和技术细节。
etc:一般放置 MySQL 的配置文件,如
my.cnf
或my.ini
(Windows 系统 ),用于配置 MySQL 服务器的参数,像连接设置、缓存大小、字符集等,决定 MySQL 的运行方式和性能表现。include:包含供开发人员使用的头文件,在进行 MySQL 相关的 C/C++ 等语言开发时,这些头文件用于声明函数、数据结构等,方便与 MySQL 进行交互开发 。
lib:存放 MySQL 的库文件,是 MySQL 运行过程中依赖的一些库,如存储引擎相关库等,为 MySQL 提供底层功能支持。
man:存储 MySQL 的手册页文件,在 Linux 系统下,通过
man
命令可以查看相关手册,获取 MySQL 命令和工具的使用说明。share:包含一些共享资源文件,如错误消息文件、字符集文件等 ,用于在 MySQL 运行过程中提供错误提示、字符编码转换等功能。
support - files:提供一些辅助文件,如初始化脚本、配置文件模板等 ,可用于初始化数据库、设置配置文件等操作,帮助用户更方便地部署和管理 MySQL。
配置安装
1、创建mysql用户和组(以mysql用户启动)
groupadd mysql
useradd mysql -g mysql
2、创建data目录
mkdir /usr/local/mysql/data
3、修改解压包权限
chown –R mysql mysql解压目录
chgrp –R mysql mysql解压目录
4、安装mysql
bin/mysqld --initialize --user=mysql --datadir /usr/local/mysql/data ## 初始化数据目录
cp -f support-files/my-default.cnf/etc/my.cnf ## 将默认配置文件复制到指定目录
bin/mysqld_safe --datadir=/usr/local/mysql/data --user=mysql & ## 启动 MySQL 服务
cp support-files/mysql.server/etc/init.d/mysql.server ## 将 MySQL 加入到服务自启动
/etc/init.d/mysql.server start ##启动mysql服务
5、开启防火墙端口
firewall-cmd --permanent --add-port=3306/tcp
firewall-cmd --reload
6、设置环境变量
vi ~/.bash_profile
####
PATH=$PATH:$HOME/bin:/usr/local/mysql/bin
解析support-files里文件
magic:是一个用于文件类型识别的文件。它包含了一些规则和模式,
file
命令等工具可以借助它来判断文件的类型,比如判断某个文件是文本文件、二进制文件,还是与 MySQL 相关的特定格式文件等,在系统对文件进行分类和处理时起到辅助识别作用 。mysql - log - rotate:是用于 MySQL 日志轮转的脚本。日志轮转是指定期将旧的日志文件进行归档(如重命名、压缩等 ),并创建新的日志文件继续记录日志。通过这个脚本,可以实现 MySQL 日志文件的自动管理,避免日志文件过大占用过多磁盘空间,同时方便对历史日志进行保存和后续分析 。
mysql.server :是 MySQL 服务的启动脚本。它可以用来启动、停止、重启 MySQL 服务。在系统启动时,若要让 MySQL 自动启动,通常会配置该脚本。它会检查 MySQL 相关的配置,初始化必要的环境,然后调用
mysqld
等程序来启动 MySQL 服务器 。mysqld_multi.server :用于管理多个 MySQL 服务器实例的脚本。当系统中运行着多个不同配置、不同端口等的 MySQL 实例时,可通过这个脚本来统一管理它们的启动、停止、重启等操作,方便在多实例环境下对 MySQL 进行运维管理 。
magic
#
# Add the following to the end of your /etc/magic file to get the 'file'
# command to recognize some MySQL files.
#
0 beshort 0xfe01 MySQL table definition file
>2 byte x Version %d
0 belong&0xffffff00 0xfefe0300 MySQL MISAM index file
>3 byte x Version %d
0 belong&0xffffff00 0xfefe0700 MySQL MISAM compressed data file
>3 byte x Version %d
0 belong&0xffffff00 0xfefe0500 MySQL ISAM index file
>3 byte x Version %d
0 belong&0xffffff00 0xfefe0600 MySQL ISAM compressed data file
>3 byte x Version %d
0 string \376bin MySQL replication log
该文件是用于扩展系统中**/etc/magic文件的规则。/etc/magic**文件是用于文件类型识别的配置文件,file
命令会依据其中定义的规则来判断文件类型。将这段内容添加到/etc/magic
文件末尾后,file
命令就能识别特定的 MySQL 相关文件类型。
具体规则解析
MySQL 表定义文件识别
0 beshort 0xfe01 MySQL table definition file
0:表示从文件起始位置开始检查。
**beshort:**这是一种数据匹配类型,用于匹配 2 字节的短整数(big - endian 格式,即大端序 )。
0xfe01:是期望匹配到的具体 2 字节数值。当文件起始位置的 2 字节内容为0xfe01时,file命令就会将该文件识别为MySQL table definition file(MySQL 表定义文件 )。
2. MySQL MISAM 索引文件识别
0 belong&0xffffff00 0xfefe0300 MySQL MISAM index file
0:从文件起始位置开始。
**belong&0xffffff00:**belong用于匹配 4 字节整数,&0xffffff00表示对匹配到的 4 字节整数进行按位与操作,屏蔽掉后 8 位 。
0xfefe0300:是经过上述按位与操作后期望匹配到的数值。若匹配成功,文件会被识别为MySQL MISAM index file(MySQL MISAM 索引文件 )。
>3 byte x Version %d
3:表示从文件第 4 个字节开始检查(偏移量为 3 )。
byte:匹配 1 字节数据。
x:表示匹配任意字节值。这里匹配到的字节值会用于后续格式化输出Version %d,用于显示文件版本信息。
3. MySQL MISAM 压缩数据文件识别
0 belong&0xffffff00 0xfefe0700 MySQL MISAM compressed data file
原理同 MISAM 索引文件识别规则的起始部分。从文件起始位置开始,匹配经过按位与操作后值为0xfefe0700的 4 字节整数,匹配成功则识别为MySQL MISAM compressed data file`(MySQL MISAM 压缩数据文件 )。
3 byte x Version %d:同上述版本信息匹配规则,从第 4 个字节开始匹配任意 1 字节值用于显示版本。
4. MySQL ISAM 索引文件识别
0 belong&0xffffff00 0xfefe0500 MySQL ISAM index file
从文件起始位置开始,匹配经过按位与操作后值为0xfefe0500
的 4 字节整数,匹配成功识别为MySQL ISAM index file(MySQL ISAM 索引文件 )。
3 byte x Version %d:同样是从第 4 个字节开始匹配版本信息相关字节。
5. MySQL ISAM 压缩数据文件识别
0 belong&0xffffff00 0xfefe0600 MySQL ISAM compressed data file
从文件起始位置开始,匹配经过按位与操作后值为0xfefe0600的 4 字节整数,匹配成功识别为MySQL ISAM compressed data file(MySQL ISAM 压缩数据文件 )。
3 byte x Version %d:从第 4 个字节开始匹配版本信息字节。
6. MySQL 复制日志文件识别
0 string \376bin MySQL replication log
0:从文件起始位置开始。
string:用于匹配字符串。\376bin:要匹配的具体字符串内容。当文件起始位置能匹配到\376bin这个字符串时,file命令会将该文件识别为MySQL replication log(MySQL 复制日志 )。
mysql-log-rotate
# Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License, version 2.0,
# as published by the Free Software Foundation.
#
# This program is also distributed with certain software (including
# but not limited to OpenSSL) that is licensed under separate terms,
# as designated in a particular file or component or in included license
# documentation. The authors of MySQL hereby grant you an additional
# permission to link the program and your derivative works with the
# separately licensed software that they have included with MySQL.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License, version 2.0, for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
# The log file name and location can be set in
# /etc/my.cnf by setting the "log-error" option
# in either [mysqld] or [mysqld_safe] section as
# follows:
#
# [mysqld]
# log-error=/usr/local/mysql/data/mysqld.log
#
# In case the root user has a password, then you
# have to create a /root/.my.cnf configuration file
# with the following content:
#
# [mysqladmin]
# password = <secret>
# user= root
#
# where "<secret>" is the password.
#
# ATTENTION: The /root/.my.cnf file should be readable
# _ONLY_ by root !
/usr/local/mysql/data/mysqld.log {
# create 600 mysql mysql
notifempty
daily
rotate 5
missingok
compress
postrotate
# just if mysqld is really running
if test -x /usr/local/mysql/bin/mysqladmin && \
/usr/local/mysql/bin/mysqladmin ping &>/dev/null
then
/usr/local/mysql/bin/mysqladmin flush-logs
fi
endscript
}
这个脚本是一个 MySQL 日志轮转配置,用于管理 MySQL 错误日志文件。它通常被系统的日志轮转工具(如logrotate
)使用,确保 MySQL 日志文件不会无限增长,同时保持服务的正常运行。
脚本结构与功能
脚本采用了logrotate配置文件的语法,主要包含以下部分:
文件路径:
/usr/local/mysql/data/mysqld.log {
...
}
指定要轮转的日志文件路径。
2. 轮转策略配置:
notifempty # 当日志文件为空时不进行轮转
daily # 每天进行一次日志轮转
rotate 5 # 保留最近5个日志文件,超出的会被删除
missingok # 如果日志文件不存在,不报错继续执行
compress # 轮转后的日志文件进行压缩
轮转后操作:
postrotate
# 仅在MySQL服务器运行时执行
if test -x /usr/local/mysql/bin/mysqladmin && \
/usr/local/mysql/bin/mysqladmin ping &>/dev/null
then
/usr/local/mysql/bin/mysqladmin flush-logs
fi
endscript
这部分代码在日志轮转完成后执行,主要功能是:
检查mysqladmin工具是否存在且可执行
检查 MySQL 服务器是否正在运行(通过ping命令)
如果 MySQL 服务器运行,则执行flush-logs命令,通知 MySQL 服务器开始写入新的日志文件
使用说明与注意事项
配置位置:
日志文件路径可在**/etc/my.cnf中通过log-error**选项设置
示例配置:
[mysqld]
log-error=/usr/local/mysql/data/mysqld.log
认证设置:
如果 MySQL root 用户设置了密码,需要创建**/root/.my.cnf**文件
该文件需包含:
[mysqladmin]
password = <secret>
user = root
注意:此文件必须只能由 root 用户读取,否则 MySQL 会拒绝使用它
3. 安全提示:
/root/.my.cnf文件权限应为600(只有所有者可读可写)
脚本默认配置每天轮转日志并保留 5 个历史文件,可根据实际需求调整
mysql.server
#!/bin/sh
# Copyright Abandoned 1996 TCX DataKonsult AB & Monty Program KB & Detron HB
# This file is public domain and comes with NO WARRANTY of any kind
# MySQL daemon start/stop script.
# Usually this is put in /etc/init.d (at least on machines SYSV R4 based
# systems) and linked to /etc/rc3.d/S99mysql and /etc/rc0.d/K01mysql.
# When this is done the mysql server will be started when the machine is
# started and shut down when the systems goes down.
# Comments to support chkconfig on RedHat Linux
# chkconfig: 2345 64 36
# description: A very fast and reliable SQL database engine.
# Comments to support LSB init script conventions
### BEGIN INIT INFO
# Provides: mysql
# Required-Start: $local_fs $network $remote_fs
# Should-Start: ypbind nscd ldap ntpd xntpd
# Required-Stop: $local_fs $network $remote_fs
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: start and stop MySQL
# Description: MySQL is a very fast and reliable SQL database engine.
### END INIT INFO
# If you install MySQL on some other places than /usr/local/mysql, then you
# have to do one of the following things for this script to work:
#
# - Run this script from within the MySQL installation directory
# - Create a /etc/my.cnf file with the following information:
# [mysqld]
# basedir=<path-to-mysql-installation-directory>
# - Add the above to any other configuration file (for example ~/.my.ini)
# and copy my_print_defaults to /usr/bin
# - Add the path to the mysql-installation-directory to the basedir variable
# below.
#
# If you want to affect other MySQL variables, you should make your changes
# in the /etc/my.cnf, ~/.my.cnf or other MySQL configuration files.
# If you change base dir, you must also change datadir. These may get
# overwritten by settings in the MySQL configuration files.
basedir=
datadir=
# Default value, in seconds, afterwhich the script should timeout waiting
# for server start.
# Value here is overriden by value in my.cnf.
# 0 means don't wait at all
# Negative numbers mean to wait indefinitely
service_startup_timeout=900
# Lock directory for RedHat / SuSE.
lockdir='/var/lock/subsys'
lock_file_path="$lockdir/mysql"
# The following variables are only set for letting mysql.server find things.
# Set some defaults
mysqld_pid_file_path=
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
# datadir_set is used to determine if datadir was set (and so should be
# *not* set inside of the --basedir= handler.)
datadir_set=
#
# 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
PATH="/sbin:/usr/sbin:/bin:/usr/bin:$basedir/bin"
export PATH
mode=$1 # start or stop
[ $# -ge 1 ] && shift
other_args="$*" # uncommon, but needed when called from an RPM upgrade action
# Expected: "--skip-networking --skip-grant-tables"
# They are not checked here, intentionally, as it is the resposibility
# of the "spec" file author to give correct arguments only.
case `echo "testing\c"`,`echo -n testing` in
*c*,-n*) echo_n= echo_c= ;;
*c*,*) echo_n=-n echo_c= ;;
*) echo_n= echo_c='\c' ;;
esac
parse_server_arguments() {
for arg do
case "$arg" in
--basedir=*) basedir=`echo "$arg" | sed -e 's/^[^=]*=//'`
bindir="$basedir/bin"
if test -z "$datadir_set"; then
datadir="$basedir/data"
fi
sbindir="$basedir/sbin"
libexecdir="$basedir/libexec"
;;
--datadir=*) datadir=`echo "$arg" | sed -e 's/^[^=]*=//'`
datadir_set=1
;;
--pid-file=*) mysqld_pid_file_path=`echo "$arg" | sed -e 's/^[^=]*=//'` ;;
--service-startup-timeout=*) service_startup_timeout=`echo "$arg" | sed -e 's/^[^=]*=//'` ;;
esac
done
}
wait_for_pid () {
verb="$1" # created | removed
pid="$2" # process ID of the program operating on the pid-file
pid_file_path="$3" # path to the PID file.
i=0
avoid_race_condition="by checking again"
while test $i -ne $service_startup_timeout ; do
case "$verb" in
'created')
# wait for a PID-file to pop into existence.
test -s "$pid_file_path" && i='' && break
;;
'removed')
# wait for this PID-file to disappear
test ! -s "$pid_file_path" && i='' && break
;;
*)
echo "wait_for_pid () usage: wait_for_pid created|removed pid pid_file_path"
exit 1
;;
esac
# if server isn't running, then pid-file will never be updated
if test -n "$pid"; then
if kill -0 "$pid" 2>/dev/null; then
: # the server still runs
else
# The server may have exited between the last pid-file check and now.
if test -n "$avoid_race_condition"; then
avoid_race_condition=""
continue # Check again.
fi
# there's nothing that will affect the file.
log_failure_msg "The server quit without updating PID file ($pid_file_path)."
return 1 # not waiting any more.
fi
fi
echo $echo_n ".$echo_c"
i=`expr $i + 1`
sleep 1
done
if test -z "$i" ; then
log_success_msg
return 0
else
log_failure_msg
return 1
fi
}
# Get arguments from the my.cnf file,
# the only group, which is read from now on is [mysqld]
if test -x "$bindir/my_print_defaults"; then
print_defaults="$bindir/my_print_defaults"
else
# Try to find basedir in /etc/my.cnf
conf=/etc/my.cnf
print_defaults=
if test -r $conf
then
subpat='^[^=]*basedir[^=]*=\(.*\)$'
dirs=`sed -e "/$subpat/!d" -e 's//\1/' $conf`
for d in $dirs
do
d=`echo $d | sed -e 's/[ ]//g'`
if test -x "$d/bin/my_print_defaults"
then
print_defaults="$d/bin/my_print_defaults"
break
fi
done
fi
# Hope it's in the PATH ... but I doubt it
test -z "$print_defaults" && print_defaults="my_print_defaults"
fi
#
# Read defaults file from 'basedir'. If there is no defaults file there
# check if it's in the old (depricated) place (datadir) and read it from there
#
extra_args=""
if test -r "$basedir/my.cnf"
then
extra_args="-e $basedir/my.cnf"
fi
parse_server_arguments `$print_defaults $extra_args mysqld server mysql_server mysql.server`
#
# Set pid file if not given
#
if test -z "$mysqld_pid_file_path"
then
mysqld_pid_file_path=$datadir/`hostname`.pid
else
case "$mysqld_pid_file_path" in
/* ) ;;
* ) mysqld_pid_file_path="$datadir/$mysqld_pid_file_path" ;;
esac
fi
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 --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
;;
'stop')
# Stop daemon. We use a signal here to avoid having to know the
# root password.
if test -s "$mysqld_pid_file_path"
then
# signal mysqld_safe that it needs to stop
touch "$mysqld_pid_file_path.shutdown"
mysqld_pid=`cat "$mysqld_pid_file_path"`
if (kill -0 $mysqld_pid 2>/dev/null)
then
echo $echo_n "Shutting down MySQL"
kill $mysqld_pid
# mysqld should remove the pid file when it exits, so wait for it.
wait_for_pid removed "$mysqld_pid" "$mysqld_pid_file_path"; return_value=$?
else
log_failure_msg "MySQL server process #$mysqld_pid is not running!"
rm "$mysqld_pid_file_path"
fi
# Delete lock for RedHat / SuSE
if test -f "$lock_file_path"
then
rm -f "$lock_file_path"
fi
exit $return_value
else
log_failure_msg "MySQL server PID file could not be found!"
fi
;;
'restart')
# Stop the service and regardless of whether it was
# running or not, start it again.
if $0 stop $other_args; then
$0 start $other_args
else
log_failure_msg "Failed to stop running server, so refusing to try to start."
exit 1
fi
;;
'reload'|'force-reload')
if test -s "$mysqld_pid_file_path" ; then
read mysqld_pid < "$mysqld_pid_file_path"
kill -HUP $mysqld_pid && log_success_msg "Reloading service MySQL"
touch "$mysqld_pid_file_path"
else
log_failure_msg "MySQL PID file could not be found!"
exit 1
fi
;;
'status')
# First, check to see if pid file exists
if test -s "$mysqld_pid_file_path" ; then
read mysqld_pid < "$mysqld_pid_file_path"
if kill -0 $mysqld_pid 2>/dev/null ; then
log_success_msg "MySQL running ($mysqld_pid)"
exit 0
else
log_failure_msg "MySQL is not running, but PID file exists"
exit 1
fi
else
# Try to find appropriate mysqld process
mysqld_pid=`pidof $libexecdir/mysqld`
# test if multiple pids exist
pid_count=`echo $mysqld_pid | wc -w`
if test $pid_count -gt 1 ; then
log_failure_msg "Multiple MySQL running but PID file could not be found ($mysqld_pid)"
exit 5
elif test -z $mysqld_pid ; then
if test -f "$lock_file_path" ; then
log_failure_msg "MySQL is not running, but lock file ($lock_file_path) exists"
exit 2
fi
log_failure_msg "MySQL is not running"
exit 3
else
log_failure_msg "MySQL is running but PID file could not be found"
exit 4
fi
fi
;;
*)
# usage
basename=`basename "$0"`
echo "Usage: $basename {start|stop|restart|reload|force-reload|status} [ MySQL server options ]"
exit 1
;;
esac
exit 0
mysql.server是 MySQL 的守护进程启动 / 停止脚本,通常放置在**/etc/init.d**目录,用于在系统启动和关闭时管理 MySQL 服务。以下是对该脚本的详细解析:
该脚本用于启动和停止 MySQL 守护进程,通常放置在**/etc/init.d**目录,并通过软链接到系统启动和关闭相关目录,实现开机自启和关机停止
支持chkconfig与LSB的注释
# Comments to support chkconfig on RedHat Linux
# chkconfig: 2345 64 36
# description: A very fast and reliable SQL database engine.
# Comments to support LSB init script conventions
### BEGIN INIT INFO
# Provides: mysql
# Required-Start: $local_fs $network $remote_fs
# Should-Start: ypbind nscd ldap ntpd xntpd
# Required-Stop: $local_fs $network $remote_fs
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: start and stop MySQL
# Description: MySQL is a very fast and reliable SQL database engine.
### END INIT INFO
针对 RedHat Linux 的chkconfig注释,定义了服务在运行级别 2、3、4、5 启动,启动顺序为 64,停止顺序为 36 。
遵循 Linux Standard Base(LSB )初始化脚本规范的注释,声明了脚本提供的服务、启动依赖、停止依赖、默认启动和停止的运行级别等信息
配置文件与路径相关设置
# If you install MySQL on some other places than /usr/local/mysql, then you
# have to do one of the following things for this script to work:
# - Run this script from within the MySQL installation directory
# - Create a /etc/my.cnf file with the following information:
# [mysqld]
# basedir=<path-to-mysql-installation-directory>
# - Add the above to any other configuration file (for example ~/.my.ini)
# and copy my_print_defaults to /usr/bin
# - Add the path to the mysql-installation-directory to the basedir variable
# below.
#
# If you want to affect other MySQL variables, you should make your changes
# in the /etc/my.cnf, ~/.my.cnf or other MySQL configuration files.
# If you change base dir, you must also change datadir. These may get
# overwritten by settings in the MySQL configuration files.
basedir=
datadir=
说明如果 MySQL 安装在非/usr/local/mysql目录,需通过特定方式让脚本正常工作,如在安装目录运行脚本、在配置文件指定basedir
路径等。
定义了basedir(MySQL 安装目录 )和datadir(MySQL 数据目录 )变量,初始为空。
服务启动超时设置
# Default value, in seconds, afterwhich the script should timeout waiting
# for server start.
# Value here is overriden by value in my.cnf.
# 0 means don't wait at all
# Negative numbers mean to wait indefinitely
service_startup_timeout=900
定义了服务启动等待超时时间为 900 秒,该值可被my.cnf
中的设置覆盖
锁文件相关设置
# Lock directory for RedHat / SuSE.
lockdir='/var/lock/subsys'
lock_file_path="$lockdir/mysql"
定义了 RedHat 和 SuSE 系统下 MySQL 服务的锁文件目录和路径。
目录变量默认值设置
# The following variables are only set for letting mysql.server find things.
# Set some defaults
mysqld_pid_file_path=
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
# datadir_set is used to determine if datadir was set (and so should be
# *not* set inside of the --basedir= handler.)
datadir_set=
根据basedir是否设置,为bindir(可执行文件目录 )、datadir、sbindir(系统二进制文件目录 )、libexecdir(可执行文件目录 )等变量设置默认值。
datadir_set用于标记datadir是否已设置。
引入LSB函数或自定义日志函数
#
# 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
尝试引入**/lib/lsb/init-functions**中的函数用于打印消息,如果文件不存在,则自定义成功和失败消息的打印函数。
环境变量设置
PATH="/sbin:/usr/sbin:/bin:/usr/bin:$basedir/bin"
export PATH
设置PATH环境变量,包含常用系统目录和 MySQL 可执行文件目录,方便脚本执行相关命令
命令行参数处理
mode=$1 # start or stop
[ $# -ge 1 ] && shift
other_args="$*" # uncommon, but needed when called from an RPM upgrade action
# Expected: "--skip-networking --skip-grant-tables"
# They are not checked here, intentionally, as it is the resposibility
# of the "spec" file author to give correct arguments only.
将第一个命令行参数赋值给mode,用于确定操作模式(启动、停止等 )。
处理其他命令行参数,在 RPM 升级操作时可能会用到,这里不做具体检查。
输出格式判断
case `echo "testing\c"`,`echo -n testing` in
*c*,-n*) echo_n= echo_c= ;;
*c*,*) echo_n=-n echo_c= ;;
*) echo_n= echo_c='\c' ;;
esac
判断系统中echo命令的输出格式,设置echo_n和echo_c变量,用于后续打印消息时控制格式。
解析服务器参数函数
parse_server_arguments() {
for arg do
case "$arg" in
--basedir=*) basedir=`echo "$arg" | sed -e 's/^[^=]*=//'`
bindir="$basedir/bin"
if test -z "$datadir_set"; then
datadir="$basedir/data"
fi
sbindir="$basedir/sbin"
libexecdir="$basedir/libexec"
;;
--datadir=*) datadir=`echo "$arg" | sed -e 's/^[^=]*=//'`
datadir_set=1
;;
--pid-file=*) mysqld_pid_file_path=`echo "$arg" | sed -e 's/^[^=]*=//'` ;;
--service-startup-timeout=*) service_startup_timeout=`echo "$arg" | sed -e 's/^[^=]*=//'` ;;
esac
done
}
定义parse_server_arguments函数,用于解析命令行中以**--basedir=、--datadir=、--pid-file=、--service-startup-timeout=**开头的参数,并设置相应变量值。
等待 PID 文件状态函数
wait_for_pid () {
verb="$1" # created | removed
pid="$2" # process ID of the program operating on the pid-file
pid_file_path="$3" # path to the PID file.
i=0
avoid_race_condition="by checking again"
while test $i -ne $service_startup_timeout ; do
case "$verb" in
'created')
# wait for a PID-file to pop into existence.
test -s "$pid_file_path" && i='' && break
;;
'removed')
# wait for this PID-file to disappear
test ! -s "$pid_file_path" && i='' && break
;;
*)
echo "wait_for_pid () usage: wait_for_pid created|removed pid pid_file_path"
exit 1
;;
esac
# if server isn't running, then pid-file will never be updated
if test -n "$pid"; then
if kill -0 "$pid" 2>/dev/null; then
: # the server still runs
else
# The server may have exited between the last pid-file check and now.
if test -n "$avoid_race_condition"; then
avoid_race_condition=""
continue # Check again.
fi
# there's nothing that will affect the file.
log_failure_msg "The server quit without updating PID file ($pid_file_path)."
return 1 # not waiting any more.
fi
fi
echo $echo_n ".$echo_c"
i=`expr $i + 1`
sleep 1
done
if test -z "$i" ; then
log_success_msg
return 0
else
log_failure_msg
return 1
fi
}
wait_for_pid函数用于等待 PID 文件达到指定状态(创建或删除 ),在等待过程中检查服务器进程状态,若超时则打印失败消息并返回相应状态码。
查找my_print_defaults工具
# Get arguments from the my.cnf file,
# the only group, which is read from now on is [mysqld]
if test -x "$bindir/my_print_defaults"; then
print_defaults="$bindir/my_print_defaults"
else
# Try to find basedir in /etc/my.cnf
conf=/etc/my.cnf
print_defaults=
if test -r $conf
then
subpat='^[^=]*basedir[^=]*=\(.*\)$'
dirs=`sed -e "/$subpat/!d" -e 's//\1/' $conf`
for d in $dirs
do
d=`echo $d | sed -e 's/[ ]//g'`
if test -x "$d/bin/my_print_defaults"
then
print_defaults="$d/bin/my_print_defaults"
break
fi
done
fi
# Hope it's in the PATH ... but I doubt it
test -z "$print_defaults" && print_defaults="my_print_defaults"
fi
尝试查找my_print_defaults工具,优先在bindir
目录下查找,若不存在则从**/etc/my.cnf配置文件中寻找basedir**,并在相应目录查找该工具,若仍未找到则尝试在PATH中查找。
读取额外配置文件参数
#
# Read defaults file from 'basedir'. If there is no defaults file there
# check if it's in the old (depricated) place (datadir) and read it from there
#
extra_args=""
if test -r "$basedir/my.cnf"
then
extra_args="-e $basedir/my.cnf"
fi
parse_server_arguments `$print_defaults $extra_args mysqld server mysql_server mysql.server`
尝试从basedir目录读取my.cnf配置文件,若存在则设置extra_args变量。然后调用parse_server_arguments函数解析从my_print_defaults
工具获取的参数。
设置 PID 文件路径
#
# Set pid file if not given
#
if test -z "$mysqld_pid_file_path"
then
mysqld_pid_file_path=$datadir/`hostname`.pid
else
case "$mysqld_pid_file_path" in
/* ) ;;
* ) mysqld_pid_file_path="$datadir/$mysqld_pid_file_path" ;;
esac
fi
如果未指定mysqld_pid_file_path,则根据datadir和主机名生成默认的 PID 文件路径;否则,若路径不是绝对路径,则将其转换为基于datadir
的路径。
操作模式处理
启动模式(start)
'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 --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
;;
切换到basedir目录,打印启动消息。
检查mysqld_safe可执行文件是否存在,若存在则调用它启动 MySQL 服务器,并传递数据目录和 PID 文件路径等参数。
使用wait_for_pid函数等待 PID 文件创建,若成功则在锁文件目录创建锁文件,最后根据返回值退出脚本。
停止模式(stop)
'stop')
# Stop daemon. We use a signal here to avoid having to know the
# root password.
if test -s "$mysqld_pid_file_path"
then
# signal mysqld_safe that it needs to stop
touch "$mysqld_pid_file_path.shutdown"
mysqld_pid=`cat "$mysqld_pid_file_path"`
if (kill -0 $mysqld_pid 2>/dev/null)
then
echo $echo_n "Shutting down MySQL"
kill $mysqld_pid
# mysqld should remove the pid file when it exits, so wait for it.
wait_for_pid removed "$mysqld_pid" "$mysqld_pid_file_path"; return_value=$?
else
log_failure_msg "MySQL server process #$mysqld_pid is not running!"
rm "$mysqld_pid_file_path"
fi
# Delete lock for RedHat / SuSE
if test -f "$lock_file_path"
then
rm -f "$lock_file_path"
fi
exit $return_value
else
log_failure_msg "MySQL server PID file could not be found!"
fi
;;
检查 PID 文件是否存在,若存在则创建一个特殊文件告知mysqld_safe需要停止。
获取 PID 并尝试向进程发送信号,打印停止消息,使用wait_for_pid函数等待 PID 文件删除,若成功则删除锁文件,最后根据返回值退出脚本。
重启模式(restart)
'restart')
# Stop the service and regardless of whether it was
# running or not, start it again.
if $0 stop $other_args; then
$0 start $other_args
else
log_failure_msg "Failed to stop running server, so refusing to try to start."
exit 1
fi
;;
先尝试停止 MySQL 服务,若成功则启动服务,否则打印失败消息并退出。
重载模式(reload和force-reload)
'reload'|'force-reload')
if test -s "$mysqld_pid
mysqld_multi.server
#!/bin/sh
#
# A simple startup script for mysqld_multi by Tim Smith and Jani Tolonen.
# This script assumes that my.cnf file exists either in /etc/my.cnf or
# /root/.my.cnf and has groups [mysqld_multi] and [mysqldN]. See the
# mysqld_multi documentation for detailed instructions.
#
# This script can be used as /etc/init.d/mysql.server
#
# Comments to support chkconfig on RedHat Linux
# chkconfig: 2345 64 36
# description: A very fast and reliable SQL database engine.
#
# Version 1.0
#
basedir=/usr/local/mysql
bindir=/usr/local/mysql/bin
if test -x $bindir/mysqld_multi
then
mysqld_multi="$bindir/mysqld_multi";
else
echo "Can't execute $bindir/mysqld_multi from dir $basedir";
exit;
fi
case "$1" in
'start' )
"$mysqld_multi" start $2
;;
'stop' )
"$mysqld_multi" stop $2
;;
'report' )
"$mysqld_multi" report $2
;;
'restart' )
"$mysqld_multi" stop $2
"$mysqld_multi" start $2
;;
*)
echo "Usage: $0 {start|stop|report|restart}" >&2
;;
esac
这是一个用于管理多实例 MySQL 服务的启动脚本,由 Tim Smith 和 Jani Tolonen 编写,主要通过mysqld_multi
工具实现对多个 MySQL 实例的统一控制。脚本设计为可放置在/etc/init.d目录下作为系统服务使用,适用于需要运行多个 MySQL 实例的场景。
核心功能与结构
前提条件说明
脚本依赖
my.cnf
配置文件,且文件需包含以下配置段:
[mysqld_multi]:多实例管理全局配置
[mysqldN]:具体实例配置(N 为实例编号,如[mysqld1]
)
配置文件路径优先为/etc/my.cnf,其次为/root/.my.cnf。
2. 环境变量与路径设置
basedir=/usr/local/mysql
bindir=/usr/local/mysql/bin
basedir:MySQL 安装根目录(默认/usr/local/mysql)
bindir:可执行文件目录(默认指向安装目录下的bin)
3. 工具可用性检查
if test -x $bindir/mysqld_multi
then
mysqld_multi="$bindir/mysqld_multi";
else
echo "Can't execute $bindir/mysqld_multi from dir $basedir";
exit;
fi
检查
mysqld_multi
工具是否存在且可执行:
若存在,将工具路径赋值给mysqld_multi变量
若不存在,打印错误信息并退出脚本
命令行操作解析
case "$1" in
'start' )
"$mysqld_multi" start $2
;;
'stop' )
"$mysqld_multi" stop $2
;;
'report' )
"$mysqld_multi" report $2
;;
'restart' )
"$mysqld_multi" stop $2
"$mysqld_multi" start $2
;;
*)
echo "Usage: $0 {start|stop|report|restart}" >&2
;;
esac
操作模式说明:
start [N]:启动编号为 N 的 MySQL 实例(如start 1启动[mysqld1])
stop [N]:停止编号为 N 的 MySQL 实例
report [N]:查看实例 N 的运行状态报告
restart [N]:先停止实例 N,再启动实例 N
参数传递:
$1为操作类型(如start)
$2为实例编号或参数(如1)
默认行为:若参数错误,输出使用帮助信息到标准错误流
配置文件示例
要使脚本正常工作,my.cnf需包含以下配置:
[mysqld_multi]
mysqld = /usr/local/mysql/bin/mysqld_safe
mysqladmin = /usr/local/mysql/bin/mysqladmin
user = root
password = <root密码>
[mysqld1]
port = 3306
socket = /tmp/mysql1.sock
datadir = /data/mysql1
pid-file = /data/mysql1/mysqld.pid
[mysqld2]
port = 3307
socket = /tmp/mysql2.sock
datadir = /data/mysql2
pid-file = /data/mysql2/mysqld.pid
多实例管理原理
mysqld_multi通过读取[mysqldN]
配置段获取每个实例的端口、数据目录等参数
启动实例时,会调用mysqld_safe并传递对应配置
停止实例时,通过mysqladmin
发送停止信号
状态报告通过检查进程和 PID 文件生成
使用场景与注意事项
适用场景:
需要在同一服务器运行多个 MySQL 实例(如不同业务隔离)
测试环境需要模拟多节点部署
开发环境需要同时运行不同版本的 MySQL
注意事项:
每个实例需配置独立的端口、Socket 和数据目录
[mysqld_multi]段需配置有效的认证信息(
user
和password
)建议为每个实例设置独立的系统用户,避免权限冲突
生产环境中建议通过
--user
参数指定低权限用户运行实例与单实例脚本的区别
单实例脚本(如
mysql.server
)直接操作单个mysqld
进程多实例脚本通过
mysqld_multi
协调多个实例的生命周期配置文件需要为每个实例单独定义参数,而非全局配置
通过该脚本,管理员可便捷地管理多个 MySQL 实例的启停和状态查询,无需为每个实例单独编写启动脚本,提高多实例环境的运维效率。
备注:
快捷链接
ln -s /usr/local/mysql-8.0.14-linux-glibc2.12-x86_64/* /usr/local/mysql
#移除软链接 移除软链接时,直接使用链接名称,不要在末尾添加斜杠 rm -r /usr/local/mysql 删除源目录(谨慎操作!)
rm /usr/local/mysql
ln -s /usr/local/mysql-8.0.14-linux-glibc2.12-x86_64/* /usr/local/mysql
ln -s /usr/local/mysql-8.0.14-linux-glibc2.12-x86_64/etc/my.cnf /etc/my.cnf