文章目录
前言
MySQL支持Centos、Red Hat、 Ubuntu、Windows、Mac等系统,具体支持的系统版本信息可以查看MySQL官方说明。MySQL的安装方式也有很多,例如在Centos上可以使用yum、rpm、二进制文件、源码编译安装等,个人比较喜欢二进制安装的方式,既可以方便的指定安装位置,又没有源码安装那么麻烦。而且源码安装的方式也很通用,在centos与mac上的安装方式基本相同。
安装步骤
环境介绍:
系统版本: CentOS Linux release 7.6.1810 (Core)
MySQL版本: mysql-5.7.32
1.下载MySQL
https://downloads.mysql.com/archives/community/
根据不同的系统版本下载不同版本的mysql
例如: 下载linux版本的二进制安装包
例如:下载mac版本的二进制安装包
如果下载MySQL安装包较慢,可以使用迅雷下载,会比直接用浏览器下载快的多。
2.安装mysql
2.1安装mysql依赖
如果没有libaio则mysql初始化和启动就会报错 (mac系统可以省略这一步)
yum install libaio
2.2 修改资源限制
vi /etc/security/limits.conf
# 在文件末尾加入下面参数
* soft nofile 100001
* hard nofile 100002
* soft memlock unlimited
* hard memlock unlimited
* soft nproc 65535
* hard nproc 65535
2.3 重启服务器
reboot
2.4 解压mysql安装包
tar -xvf mysql-5.7.32-el7-x86_64.tar.gz
解压后可以看到如下目录
bin # mysql的可执行程序(例如:mysql、mysqld、mysql、mysqld_safe等)
docs # mysql的帮助手册
man # unix的man手册
include # 放置一些头文件(例如:mysql.h、sql_common.h等)
lib # 存放一些库文件
share # 用于存放字符集、语言等信息
support-files # 其它支持文件
2.5 创建mysql用户、目录信息
cd mysql-5.7.32-el7-x86_64
groupadd mysql
useradd -r -g mysql -s /bin/false mysql
mkdir data etc tmp
touch etc/my.cnf mysqld_err.log
chown -R mysql:mysql /data/mysql-5.7.32-el7-x86_64
chmod 755 -R /data/mysql-5.7.32-el7-x86_64
2.6 初始化mysql
bin/mysqld --initialize --basedir=/data/mysql-5.7.32-el7-x86_64 --datadir=/data/mysql-5.7.32-el7-x86_64/data --user=mysql
在执行mysqld --initialize的时候一定要设置basedir为解压后的mysql目录 ,使用–initialize或者–initialize-insecure初始化数据库都可以,看自己喜好。
–initialize: 创建默认数据库并退出。创建一个超级用户和过期的密码并存储在日志中。
–initialize-insecure: 创建默认数据库并退出。创建一个超级用户和空密码。
执行完了后大概是下面的样子
2021-06-10T10:05:21.688225Z 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).
2021-06-10T10:05:21.974571Z 0 [Warning] InnoDB: New log files created, LSN=45790
2021-06-10T10:05:22.046242Z 0 [Warning] InnoDB: Creating foreign key constraint system tables.
2021-06-10T10:05:22.111192Z 0 [Warning] No existing UUID has been found, so we assume that this is the first time that this server has been started. Generating a new UUID: 5e3a942a-c9d3-11eb-aaf8-525400933ed6.
2021-06-10T10:05:22.117654Z 0 [Warning] Gtid table is not ready to be used. Table 'mysql.gtid_executed' cannot be opened.
2021-06-10T10:05:22.566092Z 0 [Warning] CA certificate ca.pem is self signed.
2021-06-10T10:05:22.731437Z 1 [Note] A temporary password is generated for root@localhost: :viiStZFk21R
复制上面的密码,一会用来登录mysql
3.创建mysql配置文件
创建mysql配置文件之前我们先来稍微了解一下我们的配置应该如何传递给mysqld
。
我们可以在启动mysqld的时候通过命令行指定启动参数,例如:
mysqld --port=3306
,但是每次启动的时候都要指定很长一串配置,比较不方便,所以我们也可以将配置写到配置文件中。
配置文件中的启动选择被划分为了很多组,每个组有一个组名,用
[]
括起来,类似下面这样
[server]
具体的配置...
[mysqld]
具体的配置...
[mysqld_safe]
具体的配置...
[client]
具体的配置...
[mysql]
具体的配置...
[mysqladmin]
具体的配置...
在配置文件中指定的配置于命令行语法,但是配置文件中只能使用长形式的配置。(例如-P是短形式的配置,–port就是长形式的配置)。并且配置文件中指定的启动选项不能加
--
前缀,=
周围可以有空白字符(启动命令行中=
周围不允许有空白字符),配置文件中还可以使用#
添加注释。
配置文件中不同的选项组是给不同的启动命令使用的,不过有两个组比较特别
[server]
可以给所有的服务器命令使用,[client]
可以给所有的客户端命令使用。
启动命令 | 类别 | 能读取的组 |
---|---|---|
mysqld | 服务器 | [mysqld]、[server]、[mysqld-5.7] |
[mysqld_safe] | 服务器 | [mysqld]、[server]、[mysqld_safe] |
mysql.server | 服务器 | [mysqld]、[server]、[mysql.server] |
mysql | 客户端 | [mysql]、[client] |
mysqladmin | 客户端 | [mysqladmin]、[client] |
mysqldump | 客户端 | [mysqldump]、[client] |
所以我们直接使用client
和server
组就行,通过二进制安装后默认是没有配置文件的,需要我们自己创建一个,将下面的配置放到我们的数据库配置文件中etc/my.cnf
,端口可以改成自己想要的。当然下面配置的目录别忘了换成你自己实际的目录。
测试环境可以直接使用下面配置模板,但是线上环境需要根据机器配置再调整一下参数
[client]
port = 8906
default-character-set = utf8mb4
socket = /data/mysql-5.7.32-el7-x86_64/tmp/mysql.sock
[server]
user = mysql
port = 8906
slow_query_log = 1
long-query-time = 1
log_timestamps = SYSTEM
max_connections = 5000
character-set-server = utf8mb4
basedir = /data/mysql-5.7.32-el7-x86_64
tmpdir = /data/mysql-5.7.32-el7-x86_64/tmp
datadir = /data/mysql-5.7.32-el7-x86_64/data
socket = /data/mysql-5.7.32-el7-x86_64/tmp/mysql.sock
log-error = /data/mysql-5.7.32-el7-x86_64/mysqld_err.log
pid-file = /data/mysql-5.7.32-el7-x86_64/mysqld.pid
# 跳过域名解析,设置为ON后会减少域名解析步骤,第一次连接时可能会加快连接速度
# 授权表也就不能使用主机名授权了
skip_name_resolve = ON
# innodb页大小
# 页是InnoDB存储引擎磁盘管理的最小单位,每个页默认16KB
# 设置完成后,不可修改,除非通过mysqldump导入和导出产生新的库
# 一个区会分配64个连续的页,所以一个区的大小是16k * 64 = 1M
# 一个区内页与页之间必须是连续的,区与区之间不要求连续
innodb_page_size = 16384
# buffer pool会包含缓存页和一些控制信息,控制信息大概占用每个缓存页的5%左右
# 所以buffer pool会占用设置的105%左右
# 默认128MB,
# buffer pool不能设置的占用机器内存比例过高,因为buffer pool实际占设置的105%左右,mysql其他操作会占用一些,操作系统也会占用一些,还要预留一些给os cache使用
# 如果机器只跑一个mysql服务,可以配置为机器内存的50%-60%比较合适
# innodb_buffer_pool_size必须是innodb_buffer_pool_chunk_size * innodb_buffer_pool_instances的倍数
# 如果我们设置的不是倍数,mysql会自动帮我们调整为倍数
# 主要是为了保证每个buffer pool中的chunk数量相同
innodb_buffer_pool_size = 128M
# buffer实际上就是一块在内存里的数据结构,由一堆缓存页和描述数据块和free、flush、lru链表组成
# mysql是可以多线程处理请求的,那么操作lru flush free链表肯定就会有线程安全问题,肯定是要加锁的
# 虽然基于内存的锁也很快,但是对于激烈的竞争锁的场景下,性能肯定严重下降
# 设置多个buffer_pool相当于对数据结构进行了分段,降低锁的竞争
# 比如buffer pool设置了16G, 4个buffer_pool_instances,就相当于每个buffer pool大小大概有4G
# 但是也并不是buffer pool设置的越多越好,管理buffer pool也是需要开销的,因此buffer pool总大小小于1G的时候设置多个buffer pool是不生效的
innodb_buffer_pool_instances = 1
# 在MySQL5.7.5之前是不能在运行期间调整buffer pool的大小的
# MySQLl5.7.5之后为了可以让buffer pool扩容,搞了一个chunk
# buffer pool是由chunk组成的,这样当给buffer pool扩容的时候,只需要增加chunk就行了
# 如果mysql没有chunk,buffer pool是一块连续的内存空间,扩容的时候只能申请一块新的内存地址
# 然后将之前buffer pool的数据拷贝到新的buffer pool中,这样效率比较低
innodb_buffer_pool_chunk_size = 128M
# MySQL重启后buffer pool内存中的数据都会被清空,此时buffer pool内存中的数据需要预热
# 否则突然来了很多请求,会造成很大的IO压力
# 打开这个参数后,当mysql被正常关闭后会把buffer pool中的数据自动dump出来,以便下次启动可以选择是不是加载
innodb_buffer_pool_dump_at_shutdown = ON
# buffer pool保存的数据文件名字
innodb_buffer_pool_filename = ib_buffer_pool
# MySQL关闭是从每个buffer pool中最近使用页面保存的百分比
innodb_buffer_pool_dump_pct = 25
# 中止buffer pool加载操作
# 使用 SET GLOBAL innodb_buffer_pool_load_abort=ON;
innodb_buffer_pool_load_abort = OFF
# MySQL启动时加载buffer pool
innodb_buffer_pool_load_at_startup = ON
# 在线保存buffer pool使用
# 如果在MySQL服务器运行时要保存buffer pool
# 使用 SET GLOBAL innodb_buffer_pool_dump_now=ON; 语句
# 查询buffer pool保存进度: SHOW STATUS LIKE 'Innodb_buffer_pool_dump_status';
innodb_buffer_pool_dump_now = OFF
# 在线恢复buffer pool状态
# 使用 SET GLOBAL innodb_buffer_pool_load_now=ON;
# 查询buffer pool加载进度: SHOW STATUS LIKE 'Innodb_buffer_pool_load_status';
innodb_buffer_pool_load_now = OFF
# redo log buffer大小
innodb_log_buffer_size = 32M
# 每个redo log文件大小
# 如果线上环境的TPS较高,建议加大至1G以上,如果压力不大可以调小
innodb_log_file_size = 1G
# 可以有多少个redo log文件, redo log是循环写的
innodb_log_files_in_group = 3
# 线性预读技术,根据缓冲池中按顺序访问的页面来预测可能很快需要哪些页面
# 一个区(extent)由64个页(page)组成
# 当一个区内的56个页被顺序读到innodb buffer pool中后,会将下一个区通过异步的方式加载到innodb buffer pool中,以便优化IO性能
# 没有这个参数之前,仅仅访问到一个区内最后一个页的时候,才会异步加载下一个区
innodb_read_ahead_threshold = 56
# 随机预读技术,根据缓冲池中已有的页面来预测何时可能很快需要页面,而不管这些页面的读取顺序如何
# 如果在innodb buffer pool中找到来自相同范围的13个连续页面,则InnoDB异步发出请求以预取该范围的剩余页面
innodb_random_read_ahead = OFF
# innodb buffer pool大小是有限的,如果需要读取新的页到buffer pool中,但是buffer pool的free链表已经没有空闲的缓存页了
# 这时候就会触发淘汰策略,把旧的缓存页从buffer poll中移除,然后把新的缓存页放进来
# 所以buffer pool中有一个LRU链表 (最近最少使用原则)
# 但是mysql还有预读技术, 但是如果太多page通过预读技术读到LRU头部后,但是这些page都没有用到,反而把一些常用的page淘汰了,这显然不合适
# 所以buffer pool中的LRU链表按照一定比例分成了两截,分别是
# 使用率比较高的缓存页,这一部分链表叫做热数据(young区域)
# 使用率比较低的缓存页,这一部分链表叫做冷数据(old区域)
# innodb_old_blocks_pct 这个参数用来设置old区域在LRU链表中所占的比例,大约占3/8
# 当磁盘上某个page在初次加载到buffer pool时,会被放到LRU old区域的头部,这样对预读到buffer pool但是后续不访问的页面就会被从
# old区域淘汰,而不会影响young区域使用比较频繁的page
# 当读扫描不能完全放入buffer pool的大表时,可以设置为较小的值,防止一次读取就会耗费buffer pool很大一部分,例如5%
# 当扫描小表时,在buffer pool内移动页面的开销较小,可以尝试增大,例如50%
innodb_old_blocks_pct = 37
# 第一次被加载到buffer pool的page会放到LRU的old区域的头部,不能刚加载进来就访问了它一次,就把它放到young区域的头部,这不合理
# 所以这个参数是设置一个page被加载进来后,隔了多少毫秒后再次被访问,才会放到LRU young区域的头部
innodb_old_blocks_time = 1000
# redo log刷盘策略,可选值:0,1,2
# 0: 提交事务时,InnoDB不会立即触发将缓存日志写到磁盘文件的操作,每秒会写入到os cache中,并调用fsync刷入磁盘(MySQL或服务器崩溃后会丢失1s数据)
# 1: 每次提交事务时,InnDB会立即将数据写入磁盘中(最安全,服务器或MySQL崩溃后不会丢失数据)
# 2: 提交时写入到os cache中,每秒调用fsync刷新到磁盘中(MySQL崩溃不会丢失数据,服务器崩溃会丢失1s数据)
# 推荐设置为1
innodb_flush_log_at_trx_commit = 1
# 后台线程会定时从LRU链表尾部开始扫描一些页,如果从里面发现脏页,会把它们刷新到磁盘
# innodb_lru_scan_depth是每次扫描的数量
innodb_lru_scan_depth = 1024
# binlog刷盘策略, 可选值:0,n
# 0: 只会将数据写入os cache中,不会调用fsync将binlog刷新到磁盘中,由操作系统决定什么时候进行刷新
# 1: 每次都将binlog同步刷新到磁盘(不会丢失数据)
# 2: 每2次会fsync一次
# 3: 每3次fsync一次 ...
# mysql5.7默认参数为1,
sync_binlog = 1
4.配置环境
centos系统可以配置到~/.bashrc
中。mac系统如果用的是zsh可以配置到~/.zprofile
中
export MYSQL_HOME=/data/mysql-5.7.32-el7-x86_64
export PATH=$MYSQL_HOME/bin:$PATH
将新增的变量信息加载到当前shell
source ~/.bashrc
因为mysql配置文件加载顺序的原因, ~/.my.cnf最后加载。
ln -s /data/mysql-5.7.32-el7-x86_64/etc/my.cnf ~/.my.cnf
5.启动MySQL
5.1 启动MySQL服务器之前,我们先来了解一下bin目录中的执行文件
在MySQL的安装目录下有一个bin目录,里面放着很多可执行文件,并且里面分为了客户端程序和服务器程序
服务器程序
- mysqld: MySQL后台进程(即MySQL服务器进程)。该进程运行后,客户端才能通过连接服务器来访问数据库(但是我们一般不直接使用mysqld)
- mysqld_safe: 服务器启动脚本。推荐使用
mysqld_safe
来启动MySQL服务器,mysqld_safe
里面也是调用了mysqld
,但是当mysqld
异常停止后,mysqld_safe
会重启mysqld
,还可以将服务器程序的异常信息重定向到日志中,这样可以方便我们找出错误发生的原因。 - mysql.server: (这个程序其实在
support-files
目录下,只不过拿到这里一起介绍了),mysql.server
里面调用了mysqld_safe
,功能比mysqld_safe更强大。mysql.server start
这样就可以启动,mysql.server stop
这样就可以关闭MySQL服务器。 - mysql_multi: 服务器启动脚本,可以启动或停止系统上安装的MySQL实例。
- myisamchk: 用来描述、检查、优化和维护MyISAM表的实用工具。
客户端程序
- mysql: MySQL客户端命令行工具
- mysqlaccess: 检查访问主机名、用户名和数据库组合的权限脚本
- mysqladmin: 执行管理操作的程序,例如创建或删除数据库,重载授权表,将表刷新到硬盘上,以及重新打开日志文件。mysqladmin还可以用来检索版本、进程,以及服务器的状态信息。
- mysqlbinlog: 将二进制日志读取的工具。在二进制日志文件中包含执行过的语句,可用来帮助系统从崩溃中恢复。
- mysqldumpslow: 用来分析慢查询日志的工具。
- mysqlcheck: 检查、修复、分析以及优化表的表维护客户程序。
- mysqldump: 将mysql数据库转储到一个文件(例如SQL语句或tab分隔符文本文件)的客户程序
- mysqlhotcopy: 当服务器在运行时,快速备份MyISAM或ISAM表的工具
- mysqlimport: 使用LOAD DATA INFILE 将文本文件导入相关表的客户程序
5.2 启动mysql服务器
在linux中,MySQL会按照下列路径顺序来寻找配置文件
/etc/my.cnf
/etc/mysql/my.cnf
/usr/local/mysql/etc/my.cnf
$MYSQL_HOME/my.cnf
~/.my.cnf
~/.mylogin.cnf # (仅限于客户端配置,由mysql_config_editor生成)
启动mysqld
这时候我们就可以启动MySQL了,执行mysqld
命令就可以启动mysql,不过一般情况下我们并不直接使用mysqld命令启动mysql,一般会用$MYSQL_HOME/support-files/mysql.server
或者mysqld_safe
。萌新习惯用mysqld_safe
。
mysqld_safe --defaults-file=~/.my.cnf &
建议一定要使用
--defaults-file
参数指定配置文件位置,因为虽然mysql会按照前面说到的顺序搜寻配置文件,后面读到的参数会覆盖前面的参数,不过如果我们自定义的参数没有覆盖到前面的参数,会导致一些我们不想要的参数加进来,可能会发生不符合预期的事情,甚至有一些参数也不能被覆盖。会导致启动mysql出现问题。
对了,执行启动命令后如果没有提示任何错误消息,就代表着启动成功,就像她的不回复,其实也是一种回复。
登录mysql并修改密码(使用刚刚复制的密码登录)
mysql -uroot -p
修改mysql密码
mysql -uroot -p
mysql> set password=password('mengxin');
mysql> flush privileges;
此时mysql默认只能从localhost登录,如果我们在测试环境中想配置成可以允许任意ip访问,需要修改mysql库中的user表的host字段,%
代表允许从任意ip访问。
use mysql;
update user set host='%' where host='root';
配置本机免密登录
mysql_config_editor set -h 127.0.0.1 -P 8906 -u root -p
如果每次使用mysql命令客户端登录mysql都要输入密码的话,可就太麻烦了,但是把密码直接配置到配置文件中又不安全,我们就可以使用mysql_config_editor命令帮助我们记住密码(会生成一个~/.mylogin.cnf文件),还可以使用–login-path参数配置多个数据库地址。
我们一起来看一下mysqld_safe是怎么帮助我们监测mysqld程序的吧
mysqld_safe中定义了一个循环,启动的时候调用了evel_log_error
函数,并把启动的参数传给它,并在eval "$cmd"
的位置执行mysqld命令后hang在这里,如果程序退出,则会根据pid_file是否存在来判断mysql是否是意外退出,如果是的话则会执行一系列清理工作后重新启动mysql。这样mysqld_safe就可以帮助我们重启意外退出的mysqld进程。
...
eval_log_error () {
cmd="$1"
case $logging in
file)
if [ -w / -o "$USER" = "root" ]; then
cmd="$cmd > /dev/null 2>&1"
else
cmd="$cmd >> "`shell_quote_string "$err_log"`" 2>&1"
fi
;;
syslog)
cmd="$cmd --log-syslog=1 --log-syslog-facility=$syslog_facility '--log-syslog-tag=$syslog_tag' > /dev/null 2>&1"
;;
both)
if [ -w / -o "$USER" = "root" ]; then
cmd="$cmd --log-syslog=1 --log-syslog-facility=$syslog_facility '--log-syslog-tag=$syslog_tag' > /dev/null 2>&1"
else
cmd="$cmd --log-syslog=1 --log-syslog-facility=$syslog_facility '--log-syslog-tag=$syslog_tag' >> "`shell_quote_string "$err_log"`" 2>&1"
fi
;;
*)
echo "Internal program error (non-fatal):" \
" unknown logging method '$logging'" >&2
;;
esac
#echo "Running mysqld: [$cmd]"
eval "$cmd"
}
...
...
while true
do
start_time=`date +%M%S`
eval_log_error "$cmd"
# hypothetical: log was renamed but not
# flushed yet. we'd recreate it with
# wrong owner next time we log, so set
# it up correctly while we can!
if [ $want_syslog -eq 0 -a ! -f "$err_log" -a ! -h "$err_log" ]; then
if test -w / -o "$USER" = "root"; then
logdir=`dirname "$err_log"`
case $logdir in
/var/log)
(
umask 0137
set -o noclobber
> "$err_log" && chown $user "$err_log"
) ;;
*) ;;
esac
else
(
umask 0137
set -o noclobber
> "$err_log"
)
fi
fi
end_time=`date +%M%S`
if test ! -f "$pid_file" # This is removed if normal shutdown
then
break
else # self's mysqld crashed or other's mysqld running
PID=`cat "$pid_file"`
if kill -0 $PID > /dev/null 2> /dev/null
then # true when above pid belongs to a running mysqld process
log_error "A mysqld process with pid=$PID is already running. Aborting!!"
exit 1
fi
fi
if test -f "$pid_file.shutdown" # created to signal that it must stop
then
log_notice "$pid_file.shutdown present. The server will not restart."
break
fi
# sanity check if time reading is sane and there's sleep
if test $end_time -gt 0 -a $have_sleep -gt 0
then
# throttle down the fast restarts
if test $end_time -eq $start_time
then
fast_restart=`expr $fast_restart + 1`
if test $fast_restart -ge $max_fast_restarts
then
log_notice "The server is respawning too fast. Sleeping for 1 second."
sleep 1
sleep_state=$?
if test $sleep_state -gt 0
then
log_notice "The server is respawning too fast and no working sleep command. Turning off trottling."
have_sleep=0
fi
fast_restart=0
fi
else
fast_restart=0
fi
fi
if true && test $KILL_MYSQLD -eq 1
then
# Test if one process was hanging.
# This is only a fix for Linux (running as base 3 mysqld processes)
# but should work for the rest of the servers.
# The only thing is ps x => redhat 5 gives warnings when using ps -x.
# kill -9 is used or the process won't react on the kill.
numofproces=`ps xaww | grep -v "grep" | grep "$ledir/$MYSQLD\>" | grep -c "pid-file=$pid_file"`
log_notice "Number of processes running now: $numofproces"
I=1
while test "$I" -le "$numofproces"
do
PROC=`ps xaww | grep "$ledir/$MYSQLD\>" | grep -v "grep" | grep "pid-file=$pid_file" | sed -n '$p'`
for T in $PROC
do
break
done
# echo "TEST $I - $T **"
if kill -9 $T
then
log_error "$MYSQLD process hanging, pid $T - killed"
else
break
fi
I=`expr $I + 1`
done
fi
if [ ! -h "$pid_file" ]; then
rm -f "$pid_file"
fi
if [ ! -h "$safe_mysql_unix_port" ]; then
rm -f "$safe_mysql_unix_port"
fi
if [ ! -h "$pid_file.shutdown" ]; then
rm -f "$pid_file.shutdown"
fi
log_notice "mysqld restarted"
done
总结
一般新部署的MySQL由于没有数据,大概率不会报错,如果有问题很有可能是配置文件导致的,尤其在测试环境中可能一台服务器不止一个mysql,如果没有指定--defaults-file
导致掺杂了一些我们不想要的配置进来,就很可能会有问题,所以启动的时候一定要指定defaults-file
。如果依然启动失败,可以查看mysql的error-log。