【MySQL】传统主从复制,AB复制【实例演示】【shell脚本】

什么是主从复制

Master(主库):对外提供业务读写,所有新增、修改、删除操作都在主库执行。

Slave(从库):默认不给用户访问,专门同步主库数据,做在线热备;也可以搭配 MyCAT 做读写分离,分担主库读压力。也就是只负责一部分查询业务

主从复制 的作用

  1. 实时数据备份:不用每天手动全库备份,主库改数据,从库实时跟着同步,故障可以切从库恢复。

  2. 读写分离分担压力:写操作全走主库,查询读操作分给多个从库,降低主库负载。

2种 同步模式(异步/同步)

(1)异步复制(线上 99% 场景用这个)

流程:主库执行完增删改,直接返回给客户端,不等从库同步完成,后台慢慢把变更发给从库。

  • 优点:不阻塞业务,主库性能不受影响

  • 缺点:会有同步延迟,极端情况主库宕机,少量还没同步的数据会丢失

(2)同步复制

流程:主库执行 SQL 后,必须等所有从库同步完这条数据,才返回执行成功给客户端。

  • 优点:主从数据完全一致,零数据丢失

  • 缺点:写业务严重阻塞,并发高时性能暴跌,极少生产使用

补充:轮询 vs 回调(两种同步触发逻辑)

  1. 轮询:从库不停主动问主库「有没有新数据」好处:同步及时;坏处:主库没数据更新也会收到大量无效请求,浪费资源

  2. 回调:主库有新数据才主动通知从库来拉取好处:无无效请求,省资源;坏处:极端网络故障可能丢数据

主从异步复制完整原理

一句话总结原理

主库写变更→存 binlog;从库 IO 线程拉取 binlog 存中继日志;从库 SQL 线程重放中继日志,完成同步。

三种备份区分

  1. 逻辑备份:mysqldump导出 SQL 文件(冷备,停机 / 锁表)
  2. 物理备份:直接拷贝数据库 data 目录文件(冷备)
  3. 主从复制:在线热备,数据库不停机实时同步数据

核心文件

  1. Binlog(主库二进制日志) 主库所有的增删改,更新也就是INSERT/UPDATE/DELETE变更 SQL,全部记录到 binlog 里,是同步的数据源。
  2. **Relaylog(从库中继日志)**从库拉取到 binlog 内容,先临时存进 relaylog,再重放执行,相当于中转站。

完整同步流程

  1. 从库 IO 线程:主动发起连接,请求主库最新 binlog 日志

  2. 主库 Binlog Dump 线程:收到请求,读取本地 binlog 新增内容,传输给从库 IO 线程

  3. 从库 IO 线程 :拿到日志,写入本地relaylog中继文件;同时记录同步位点(文件名 + 偏移量)存到master.info,标记同步到哪了

  4. 从库 SQL 线程:持续监听 relaylog 更新,读取日志里的 SQL 语句,在从库本地重放执行,最终和主库数据完全一致

传统一主一从(AB 复制)搭建前置环境

  • 主库:192.168.88.101 mysql-node1
  • 从库:192.168.88.102 mysql-node2

安装系统依赖包

复制代码
dnf install vim wget rsync telnet net-tools -y

设置主机名 + /etc/hosts 域名映射

主服务器

复制代码
hostnamectl set-hostname mysql-node1
vim /etc/hosts
# 添加
192.168.88.101 mysql-node1
192.168.88.102 mysql-node2

从服务器

复制代码
hostnamectl set-hostname mysql-node2
vim /etc/hosts
# 添加
192.168.88.101 mysql-node1
192.168.88.102 mysql-node2

配置静态 IP

两台服务器固定 IP,不能动态变 IP,否则主从连接会断掉。

Linux 系统安全优化(关闭防火墙、SELINUX)

防火墙、安全拦截会阻断主从之间 3306 数据库端口通信,搭建主从必须关闭,不然同步报错连不上

复制代码
# 关闭SELINUX
sed -i -r 's/SELINUX=[ep].*/SELINUX=disabled/g' /etc/selinux/config
setenforce 0
# 关闭防火墙开机自启+临时关闭
systemctl stop firewalld && systemctl disable firewalld
iptables -F

时间同步 chrony

主从服务器时间必须一致,否则日志时间戳错乱、同步异常;chrony 自动同步网络标准时间。

复制代码
dnf -y install chrony
systemctl enable chronyd --now

搭建思路

1,master、slave必须安装相同版本的MySQL数据库软件

复制代码
#查看当前版本号
mysql --version

2,master端必须开启二进制日志,slave端必须开启relay log中继日志

主库 binlog(二进制日志)

所有增 / 删 / 改操作都会记录到 binlog,主从同步的数据源,不开 binlog 就没有东西同步给从库。

从库 relay log(中继日志)

从库 IO 线程拉取主库 binlog 后,先临时存到 relay log 里,再由 SQL 线程重放执行。相当于 "中转站",从库必须开启才能完成同步流程。

3,master端和slave端的server-id号不能一致

server-id 是给每一台 MySQL 数据库实例分配的唯一数字编号,写在 my.cnf 配置文件里。整个主从集群里,每台机器这个数字绝对不能重复

4,同步master端数据之前,master端删除data数据目录下的auto.cnf文件

uto.cnf 是什么

文件里存了 MySQL 实例自动生成的全局唯一 UUID,数据库初始化时自动创建。

为什么要删

搭建主从时,如果直接把主库完整 data 文件夹复制到从库,主、从两台数据库 UUID 一模一样。MySQL 底层靠 UUID 区分实例,重复 UUID 会触发主从复制异常、连接报错。

操作逻辑

从库删掉auto.cnf,启动 MySQL 时会自动生成全新、独一无二的 UUID,解决冲突。

5,slave端配置向master来同步数据

1,单独新建一个账号

从库需要账号、密码登录主库,才能拉取 binlog 二进制日志。生产环境不能直接用 root 超级账号给从库连接,不安全。所以单独新建一个账号,只给它「replication slave」这一个权限,最小权限原则

复制代码
#单独新建一个账号
create user 'slave'@'%' identified by '123456';
grant replication slave on *.* to 'slave'@'%';

2,master 和 slave 初始数据一致

同步开启前,如果两台库现存的数据不一样,同步运行后会主键冲突、数据错乱、同步直接报错停止

主库执行这条命令导出全库备份文件,再把文件传到从库执行导入,两台库存量数据就一模一样了

复制代码
mysqldump --single-transaction --master-data
  • mysqldump:mysql 自带逻辑备份工具,导出整库 sql
  • --single-transaction:针对 innodb 引擎,不用锁表,备份期间业务正常读写
  • --master-data:自动记录备份那一刻主库的 binlog 文件名 + 同步位点,导入从库后不用手动记日志位置,方便后续同步

3,在 slave 库执行 change master to 绑定主库信息

告诉从库:主库的 ip 地址、同步账号、密码、从哪个 binlog 文件哪个位置开始同步数据。不执行这条语句,从库不知道去哪找主库,无法建立同步链路。

复制代码
change master to
master_host='192.168.88.101',
master_user='slave',
master_password='123456',
master_log_file='mysql-bin.000001',
master_log_pos=156;

执行完这条命令后,输入start slave;就能启动主从同步。

实战

现在有两个安装了MySQL的服务器并且MySQL版本号一致,8.0.43

node1(192.168.88.101) mysql安装在/export/software

node3(192.168.88.104)mysql安装在/export/software

必须在同一路径下!!必须同一个版本

复制代码
show variables like 'basedir';
show variables like 'datadir';
  • basedir:MySQL 程序本体安装目录
  • datadir:数据库数据文件目录

环境准备

安装依赖

Delphi 复制代码
#两台服务器必装
dnf install vim wget rsync telnet net-tools -y

两个服务器设置主机名,我这里主服务器是node1 从服务器是node4

Delphi 复制代码
#主
hostnamectl set-hostname mysql-node1
#从
hostnamectl set-hostname mysql-node4
bash

配置ip与主机映射

两个服务器都

Delphi 复制代码
vim /etc/hosts
Delphi 复制代码
#在尾部追加如下内容
192.168.88.101   mysql-node1   node1
192.168.88.104   mysql-node4   node4

优化Linux系统

两个服务器都

Delphi 复制代码
sed -i -r 's/SELinux=[ep].*/SELinux=disabled/g' /etc/selinux/config
setenforce 0
systemctl stop firewalld &> /dev/null
systemctl disable firewalld &> /dev/null
iptables -F
iptables -t nat -F
iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT

时间同步,俩服务都

Delphi 复制代码
dnf -y install chrony
systemctl enable chronyd --now

初始化数据库(从库)

注意:建议主服务器的mysql服务器正常开启使用, 从服务器的,mysql服务器先不要初始化,后期需要从主服务器同步data数据过来,如果初始化,可能会造成数据不一致,导致主从复制启动失败

初始化

复制代码
/export/server/mysql/bin/mysqld --initialize --user=mysql --basedir=/export/server/mysql &>/tmp/mysqld.log

重置密码

复制代码
#===========获取临时密码==========
grep password /tmp/mysqld.log | awk '{print $NF}'

#=========无密码启动 mysql,用来改初始密码======
mysqld --user=mysql --skip-grant-tables --skip-networking &

#=======本地无密码登录 mysql=====
mysql

#========数据库内修改 root 密码(sql 语句)========
flush privileges;
alter user 'root'@'localhost' identified by '123456';
flush privileges;
exit;

#============重启 mysql 服务,正常带密码运行=========
pkill mysqld
systemctl start mysqld
systemctl status mysqld --no-pager
systemctl enable mysqld
mysql -uroot -p'123456'
#==========查看自带系统库========
show databases;

修改MySQL主从配置

master服务器

Delphi 复制代码
vim /etc/my.cnf

原来的不要了,只放我这个就行,注意只能有一个mysql

Delphi 复制代码
[mysqld]
# 基础路径
basedir=/export/software/mysql
datadir=/export/software/mysql/data
port=3306

# 字符集配置
character_set_server=utf8mb4
collation-server=utf8mb4_unicode_ci

# 错误日志
log-error=/export/software/mysql/master.err

# 二进制日志,用于主从复制 & 恢复
log-bin=/export/software/mysql/data/binlog
server-id=101
binlog_format=ROW
expire_logs_days=7
sync_binlog=1

# 跳过同步的系统库
binlog-ignore-db=information_schema
binlog-ignore-db=mysql
binlog-ignore-db=performance_schema
binlog-ignore-db=sys

# InnoDB 引擎优化
default_storage_engine=InnoDB
innodb_buffer_pool_size=1G
innodb_log_file_size=256M
innodb_log_buffer_size=64M
innodb_flush_log_at_trx_commit=1 # 主库一般为1,每次事务提交都写日志并立刻刷盘
innodb_file_per_table=1 # 每个表一个独立的 .ibd 文件

# 连接配置
max_connections=500
max_connect_errors=1000000
table_open_cache=2000

# 慢查询日志
slow_query_log=1
slow_query_log_file=/export/software/mysql/slow.log
long_query_time=1

[client]
socket=/tmp/mysql.sock

创建日志文件并授权,不然 MySQL 启动会因为没有文件而报错:

Delphi 复制代码
touch /export/software/mysql/master.err
chown mysql:mysql /export/software/mysql/master.err
Delphi 复制代码
chown -R mysql:mysql /export/software/mysql

重启

Delphi 复制代码
# 重启服务
systemctl restart mysqld

# 查看服务状态
systemctl status mysqld --no-pager

验证binlog是否成功开启

Delphi 复制代码
show variables like 'log_bin';

slave服务器,开启relaylog

Delphi 复制代码
vim /etc/my.cnf

添加到文件最下面

Delphi 复制代码
[mysqld]
# 基础路径
basedir=/export/software/mysql
datadir=/export/software/mysql/data
port=3306

# 字符集
character_set_server=utf8mb4
collation-server=utf8mb4_unicode_ci

# 错误日志
log-error=/export/software/mysql/slave.err

# 开启 binlog(从库也可以作为其他从库的主库)
# log-bin=/export/server/mysql/data/binlog

# relay log
relay-log=/export/software/mysql/data/relaylog
relay-log-index=/export/software/mysql/data/relaylog.index
# 普通用户和超级管理员用户都只能读数据【前提是你的同步还开启着】
read-only=1
skip-slave-start=1   # 避免宕机重启自动拉起复制线程,需手动控制

# 复制过滤(避免同步系统库)
replicate-wild-ignore-table=mysql.%
replicate-wild-ignore-table=information_schema.%
replicate-wild-ignore-table=performance_schema.%
replicate-wild-ignore-table=sys.%

# server-id 必须唯一
server-id=102

# InnoDB 参数(从库查询压力可能更大)
default_storage_engine=InnoDB
innodb_buffer_pool_size=1G
innodb_log_file_size=256M
innodb_log_buffer_size=64M
innodb_flush_log_at_trx_commit=2   # 从库一般可设为 2,提高复制性能;每次事务提交,写日志,但不立即刷盘
innodb_file_per_table=1 # 每个表一个独立的 .ibd 文件

# 连接配置
max_connections=500
table_open_cache=2000
max_connect_errors=1000000

# 慢查询日志(从库跑报表时有用)
slow_query_log=1
slow_query_log_file=/export/software/mysql/slow.log
long_query_time=1

# 复制优化
relay_log_recovery=1   # 防止 relay log 损坏导致复制中断
sync_relay_log=0       # 提高复制性能
sync_relay_log_info=0
sync_master_info=0

[client]
socket=/tmp/mysql.sock

注意:确保两处 socket 保持一致

从slave服务器配置完成后,也需要提前创建slave.err错误日志文件

Delphi 复制代码
mkdir /export/software/mysql/data/relaylog
chown -Rf mysql:mysql /export/software/mysql
Delphi 复制代码
systemctl restart mysqld
systemctl status mysqld

创建同步账号

在主库(master)中创建账号

Delphi 复制代码
#创建用户slave
create user 'slave'@'%' identified by '123456';
select user,host from mysql.user;
#授权
grant replication slave, replication client on *.* to 'slave'@'%';
flush privileges;
  • replication slave允许从库连接主库,读取二进制日志,拉取数据进行同步。

  • replication client允许查看主从复制状态、binlog 文件名与位置,用来排错、监控延迟。

从库,检验一下能不能连上

Delphi 复制代码
mysql -uslave -p'123456' -h192.168.88.101

-h 后面永远写主库 IP(101)

同步两个数据库数据

冷备份主库全量数据,保证主从数据起点完全一致

  1. 先给主库加全局只读锁 flush tables with read lock;锁住所有表,禁止写入(insert/update/delete),保证数据不再变动。
  2. 把主库整个 data 目录用 rsync 完整拷贝到从库。
  3. 删除从库 data 里的 auto.cnf,避免主从 UUID 重复导致同步报错。

主库停服务

Delphi 复制代码
systemctl stop mysqld
pkill mysqld

主服务器的数据同步给从服务器

把主库 node1 里完整的数据库目录:/export/software/mysql/data完整复制覆盖到从库 node3 的目录:/export/server/mysql/data

让主库、从库的数据文件完全一模一样,保证主从起点一致,不会出现数据不一致。

用 rsync 停库拷贝数据,不需要再加锁;

从库删东西

Delphi 复制代码
systemctl stop mysqld
pkill mysqld

#删掉当前data,准备接新的
rm -rf /export/software/mysql/data
mkdir /export/software/mysql/data

主库开始拷贝

Delphi 复制代码
rsync -av --delete /export/software/mysql/data/ mysql-node4:/export/software/mysql/data/
systemctl restart mysqld

从库删auyo.cnf

  1. 文件作用

auto.cnf 里面记录着这一套 MySQL 实例的唯一 UUID 编号。主库拷贝过来之后,主库和从库的 UUID 会变成完全相同。

  1. 为什么必须删掉

MySQL 主从架构里,不允许主库、从库 UUID 一模一样。一旦重复,从库启动同步时会直接报错,IO 线程无法正常运行。

  1. 删除之后会发生什么

删掉文件,重启从库 MySQL 服务:数据库会自动重新生成一个全新、独一无二的 UUID,主从 ID 不再冲突。

Delphi 复制代码
rm -f /export/software/mysql/data/auto.cnf
systemctl restart mysqld

故障原因

rsync 把主库 data 目录同步过来之后,data 文件夹所有者还是 root,mysql 用户没有读写权限,所以启动直接失败。

Delphi 复制代码
chown -R mysql:mysql /export/server/mysql
systemctl restart mysqld
systemctl status mysqld

在slave端开启同步

主服务器先看一下binlog写到哪了 一会测试要用到

Delphi 复制代码
show master status;

拿到结果后

File(日志文件名)和 Position(数字)复制下来,去从库执行 change master to

Delphi 复制代码
change replication source to
master_host='192.168.88.101',
master_user='slave',
master_password='123456',
master_log_file='binlog.000083',
master_log_pos=157;

===================================================================

从服务器如果登录不上MySQL的话

Delphi 复制代码
systemctl stop mysqld
pkill mysqld
chown -R mysql:mysql /export/server/mysql
chmod -R 700 /export/server/mysql

如果两个MySQL服务器的安装路径不一样,也会出现报错

Delphi 复制代码
#=========停止服务,清空旧数据======
systemctl stop mysqld
pkill mysqld

rm -rf /export/server/mysql/data
mkdir /export/server/mysql/data
#==============赋予目录权限===========
chown -R mysql:mysql /export/server/mysql
#=========全新初始化 MySQL(生成干净实例)============
/export/server/mysql/bin/mysqld --initialize --user=mysql \
--basedir=/export/server/mysql \
--datadir=/export/server/mysql/data

#========启动数据库,修改 root 密码======
systemctl start mysqld
grep 'temporary password' /export/server/mysql/slave.err
mysql -u -p临时密码
alter user root@'localhost' identified by '123456';

同步完 data 之后,第一时间删除 3 个文件, 这一步把保存旧 binlog 路径的文件彻底删掉,数据库再也不会去读 /export/software/mysql/data/

Delphi 复制代码
cd /export/server/mysql/data
rm -f master.info
rm -f relay-log.info
rm -f relaylog.*
rm -f auto.cnf
Delphi 复制代码
#my.cnf 临时注释掉 relay-log 中继日志
# relay-log=xxx
# relay-log-index=xxx
Delphi 复制代码
#从库权限修复
chown -R mysql:mysql /export/server/mysql
mysql -uroot -p123456
show databases;
Delphi 复制代码
#启动 MySQL,登录执行清空复制元数据
reset slave all;

========================================================================

开启同步,检查状态

从服务器

Delphi 复制代码
start slave;
show slave status\G
  1. start slave;
  • 作用:启动从库主从复制线程,让从节点开始拉取主库的二进制日志,同步数据。
  1. show slave status\g
  • 作用:查看从库复制的运行状态(主从复制最核心的排查命令)。
  • \g 和分号 ; 作用一样,都是结束语句,\g 会把查询结果竖排展示,字段分行,方便阅读
  1. slave_io_running 值为 yes:从库 I/O 线程正常,正在连通主库、拉取 binlog 日志。
  2. slave_sql_running 值为 yes:SQL 线程正常,正在执行日志里的 SQL、同步数据。

两个都为 yes,代表主从复制正常

============================报错connecting=============================

两边防火墙给关了

Delphi 复制代码
systemctl stop firewalld
systemctl status firewalld
Delphi 复制代码
=================从库停止================
stop slave;
=================主库删除用户重建=========
drop user if exists 'slave'@'%';
create user 'slave'@'%' identified with mysql_native_password by '123456';
grant replication slave on *.* to 'slave'@'%';
flush privileges;
===============从库再试一下============
change master to
master_host='192.168.88.101',
master_port=3306,
master_user='slave',
master_password='123456',
master_log_file='binlog.000083',
master_log_pos=157;
==============查看状态===============
start slave;
show slave status\g

========================================================================

验证测试

master中创建数据库、数据表并插入数据

Delphi 复制代码
create database if not exists db_itheima2;
use db_itheima;

create table if not exists  students(
        id int primary key,
        name varchar(20)
) default charset=utf8;

insert into students values (1, 'Tom');
insert into students values (2, 'Rose');

select * from students;

从库验证

Delphi 复制代码
show databases;
use db_itheima2;
show tables;
select * from students;

shell脚本

配置Master主服务器

Delphi 复制代码
#!/bin/bash
#1.安装依赖软件
echo "正在安装依赖软件..."
yum -y install libaio &> /dev/null
if [ $? -ne 0 ];then
    echo "libaio安装失败"
    exit 1
fi

#2.判断是否有压缩包,如果有,则执行解压缩操作
echo "正在判断是否有压缩包,如果有进行解压缩操作..."
if [ -f mysql-8.0.43-linux-glibc2.28-x86_64.tar.xz ]; then
    tar -xf mysql-8.0.43-linux-glibc2.28-x86_64.tar.xz
    ls -l mysql-8.0.43-linux-glibc2.28-x86_64
fi

#3.判断系统中是否安装过mariadb软件,如果有对其进行卸载操作
echo "正在判断系统中是否安装过mariadb软件,如果有对其进行卸载操作..."
rpm -qa | grep mariadb | xargs -r dnf remove -y
[ -f /etc/my.cnf ] && rm -rf /etc/my.cnf

#4.创建mysql系统账号
id mysql &> /dev/null
[ $? -ne 0 ] && useradd -r -s /sbin/nologin mysql

#5.创建/export/server目录,然后移动mysql压缩包解压后的文件到/export/server目录下
rm -rf /export/server
mkdir -p /export/server
mv mysql-8.0.43-linux-glibc2.28-x86_64 /export/server/mysql
chown -Rf mysql:mysql /export/server/mysql
#6.进入mysql目录,对其进行初始化操作
echo "正在进入mysql目录,对其进行初始化操作..."
cd /export/server/mysql
bin/mysqld --initialize --user=mysql --basedir=/export/server/mysql --datadir=/export/server/mysql/data 2>&1 | tee /tmp/mysqld.log | grep password | awk '{print $NF}' > /tmp/mysql_temp_password.txt

#7.设置ssl加密传输连接
bin/mysql_ssl_rsa_setup --datadir=/export/server/mysql/data &> /dev/null

#8.设置my.cnf与mysqld.service文件
echo "正在设置my.cnf与mysqld.service文件..."
cat > /etc/my.cnf <<EOF
[mysqld]
port=3306
basedir=/export/server/mysql
datadir=/export/server/mysql/data
socket=/tmp/mysql.sock
character_set_server=utf8
collation-server=utf8_unicode_ci
EOF

cat > /etc/systemd/system/mysqld.service <<EOF
[Unit]
Description=MySQL Server
After=network.target

[Service]
User=mysql
Group=mysql
Type=forking

# MySQL 执行命令及路径
ExecStart=/export/server/mysql/bin/mysqld --daemonize --pid-file=/export/server/mysql/data/mysqld.pid
ExecStop=/export/server/mysql/bin/mysqladmin --defaults-file=/etc/my.cnf shutdown

# Ensure MySQL has sufficient time to start up
TimeoutSec=600

# PID 文件路径
PIDFile=/export/server/mysql/data/mysqld.pid

# Enable these options to auto-restart the service if it crashes
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

#9.刷新后台服务,然后启动mysqld
echo "正在刷新后台服务,然后启动mysqld..."
systemctl daemon-reload
systemctl start mysqld
systemctl enable mysqld

#10.重置mysql管理员密码为123456
echo "正在重置mysql管理员密码..."
cd /export/server/mysql
temp_password=`cat /tmp/mysql_temp_password.txt`
bin/mysqladmin -uroot password '123456' -p"$temp_password"

#11.把mysql的bin目录添加到环境变量中
echo 'export PATH=$PATH:/export/server/mysql/bin' >> /etc/profile
source /etc/profile

#13.弹出提示,MySQL安装成功
echo "MySQL安装成功,软件安装路径:/export/server/mysql,数据库初始密码:123456!"

配置Slave从服务器

只需要安装MySQL软件,不需要初始化(不会生成 data 文件夹),也不需要启动MySQL软件。

Delphi 复制代码
#!/bin/bash
#1.安装依赖软件
echo "正在安装依赖软件..."
yum -y install libaio &> /dev/null
if [ $? -ne 0 ];then
    echo "libaio安装失败"
    exit 1
fi

#2.判断是否有压缩包,如果有,则执行解压缩操作
echo "正在判断是否有压缩包,如果有进行解压缩操作..."
if [ -f mysql-8.0.43-linux-glibc2.28-x86_64.tar.xz ]; then
    tar -xf mysql-8.0.43-linux-glibc2.28-x86_64.tar.xz
    ls -l mysql-8.0.43-linux-glibc2.28-x86_64
fi

#3.判断系统中是否安装过mariadb软件,如果有对其进行卸载操作
echo "正在判断系统中是否安装过mariadb软件,如果有对其进行卸载操作..."
rpm -qa | grep mariadb | xargs -r dnf remove -y
[ -f /etc/my.cnf ] && rm -rf /etc/my.cnf

#4.创建mysql系统账号
id mysql &> /dev/null
[ $? -ne 0 ] && useradd -r -s /sbin/nologin mysql

#5.创建/export/server目录,然后移动mysql压缩包解压后的文件到/export/server目录下
rm -rf /export/server
mkdir -p /export/server
mv mysql-8.0.43-linux-glibc2.28-x86_64 /export/server/mysql

#6.进入mysql目录,对其进行初始化操作
echo "正在进入mysql目录,从服务器无需进行初始化操作..."
cd /export/server/mysql

#7.设置ssl加密传输连接
bin/mysql_ssl_rsa_setup --datadir=/export/server/mysql/data &> /dev/null

#8.设置my.cnf与mysqld.service文件
echo "正在设置my.cnf与mysqld.service文件..."
cat > /etc/my.cnf <<EOF
[mysqld]
port=3306
basedir=/export/server/mysql
datadir=/export/server/mysql/data
socket=/tmp/mysql.sock
character_set_server=utf8mb4
collation-server=utf8mb4_unicode_ci
EOF

cat > /etc/systemd/system/mysqld.service <<EOF
[Unit]
Description=MySQL Server
After=network.target

[Service]
User=mysql
Group=mysql
Type=forking

# MySQL 执行命令及路径
ExecStart=/export/server/mysql/bin/mysqld --daemonize --pid-file=/export/server/mysql/data/mysqld.pid
ExecStop=/export/server/mysql/bin/mysqladmin --defaults-file=/etc/my.cnf shutdown

# Ensure MySQL has sufficient time to start up
TimeoutSec=600

# PID 文件路径
PIDFile=/export/server/mysql/data/mysqld.pid

# Enable these options to auto-restart the service if it crashes
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

#9.刷新后台服务,但是不启动mysqld
echo "正在刷新后台服务,暂不启动mysqld..."
systemctl daemon-reload
systemctl enable mysqld

#10.把mysql的bin目录添加到环境变量中
echo 'export PATH=$PATH:/export/server/mysql/bin' >> /etc/profile
source /etc/profile

#11.弹出提示,MySQL安装成功
echo "MySQL安装成功,软件安装路径:/export/server/mysql,数据库暂未初始化,数据库暂未启动!"

**注意:**以上两个脚本执行都必须通过source mysql8.sh

问题:./mysql8.sh、sh/bash mysql8.sh 与 source mysql8.sh执行有何不同?

./mysql8.sh、sh/bash mysql8.sh都代表直接运行脚本,这两种方式运行脚本都会产生一个子进程,程序所在终端(主进程),两者之间相互独立,子进程环境变量无法影响父进程中的环境变量。

source执行脚本时,虽然也会产生一个子进程,但是不仅会影响子进程中的环境变量,也会影响父进程中的环境变量。