MySQL 5.7 安装脚本

1.非交互式安装脚本,一键执行安装。

注意:
部分配置需要在脚本中修改

#!/bin/bash
##############################################################
# File Name: mysql_install.sh
# Time: 2020-06-07-21:25:55
# Author: wanhebin
# Organization: www.wanhebin.com
# Description: Binary Install Of MySQL
##############################################################

#加载系统函数库
[ -f /etc/init.d/functions ] && source /etc/init.d/functions

Version='5.7.30'
Base_Dir=/server/mysql
Data_Dir=${Base_Dir}/data
Tmp_Dir=${Base_Dir}/tmp

#下载二进制包
echo -e "\033[32m===========================开始下载mysql-${Version}二进制包============================\033[0m"
[ -f /tmp/mysql-${Version}-linux-glibc2.12-x86_64.tar.gz ] && rm -rf /tmp/mysql-${Version}-linux-glibc2.12-x86_64.tar.gz
wget -O /tmp/mysql-${Version}-linux-glibc2.12-x86_64.tar.gz https://cdn.mysql.com/archives/mysql-${Version%.*}/mysql-${Version}-linux-glibc2.12-x86_64.tar.gz

#安装依赖
echo -e "\033[32m===================================开始安装依赖====================================\033[0m"
yum -y install  gcc gcc-c++ cmake ncurses-devel libaio-devel autoconf openssl openssl-devel

#解压安装
echo -e "\033[32m====================================开始安装MySQL==================================\033[0m"
echo "正在准备......"
[ -d /tmp/mysql-${Version}-linux-glibc2.12-x86_64 ] && rm -rf /tmp/mysql-${Version}-linux-glibc2.12-x86_64
tar xf /tmp/mysql-${Version}-linux-glibc2.12-x86_64.tar.gz -C /tmp/

#移动目录 
[ -d ${Base_Dir%/*} ] || mkdir -p ${Base_Dir%/*}
[ -d ${Base_Dir}-${Version} ] && rm -rf ${Base_Dir}-${Version}
mv /tmp/mysql-${Version}-linux-glibc2.12-x86_64 ${Base_Dir}-${Version}

#创建软连接
rm -rf ${Base_Dir} && ln -s ${Base_Dir}-${Version} ${Base_Dir}

#创建用户
useradd -M -s /sbin/nologin mysql 2> /dev/null

#拷贝并修改动脚本
\cp ${Base_Dir}/support-files/mysql.server /etc/init.d/mysqld
sed -i "s@^basedir=@basedir=${Base_Dir}@g" /etc/init.d/mysqld
sed -i "s@^datadir=@datadir=${Data_Dir}@g" /etc/init.d/mysqld
sed -i 's@^PATH.*@PATH="$PATH:/sbin:/usr/sbin:/bin:/usr/bin:$basedir/bin"@g' /etc/init.d/mysqld

#修改配置文件
[ -f "/etc/my.cnf" ] && \cp /etc/my.cnf{,.bak}
cat>/etc/my.cnf<<EOF
[client]
#password = 
port = 3306
socket = ${Tmp_Dir}/mysql.sock

[mysqld]
port = 3306
socket = ${Tmp_Dir}/mysql.sock
basedir = ${Base_Dir}
datadir = ${Data_Dir}
pid_file = ${Tmp_Dir}/mysql.pid 
log_error = ${Data_Dir}/mysql.err
#general_log = ON
#general_log_file = ${Data_Dir}/mysql_general.log
binlog_cache_size = 32K
thread_stack = 256K
join_buffer_size = 256K
query_cache_type = 1
max_heap_table_size = 128M
default_storage_engine = InnoDB
performance_schema_max_table_instances = 400
table_definition_cache = 400
skip-external-locking
key_buffer_size = 64M
max_allowed_packet = 100G
table_open_cache = 256
sort_buffer_size = 1024K
net_buffer_length = 4K
read_buffer_size = 1024K
read_rnd_buffer_size = 256K
myisam_sort_buffer_size = 16M
thread_cache_size = 32
query_cache_size = 64M
tmp_table_size = 128M
sql-mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES

secure_file_priv=${Tmp_Dir}/

explicit_defaults_for_timestamp = true
#skip-name-resolve
max_connections = 500
max_connect_errors = 100
open_files_limit = 65535

log-bin=mysql-bin
binlog_format=row
server-id = 1
max_binlog_size=512M
expire_logs_days = 10
slow_query_log=1
slow-query-log-file = ${Data_Dir}/mysql-slow.log
long_query_time=3
#log_queries_not_using_indexes=on

innodb_data_home_dir = ${Data_Dir}
innodb_data_file_path = ibdata1:10M:autoextend
innodb_log_group_home_dir = ${Data_Dir}
innodb_buffer_pool_size = 256M
innodb_log_file_size = 128M
innodb_log_buffer_size = 32M
innodb_flush_log_at_trx_commit = 1
innodb_lock_wait_timeout = 50
innodb_max_dirty_pages_pct = 90
innodb_read_io_threads = 2
innodb_write_io_threads = 2

[mysqldump]
quick
max_allowed_packet = 500M

[mysql]
no-auto-rehash

[myisamchk]
key_buffer_size = 64M
sort_buffer_size = 1M
read_buffer = 2M
write_buffer = 2M

[mysqlhotcopy]
interactive-timeout
EOF

#初始化数据库
mkdir ${Base_Dir}/tmp
chown -R mysql:mysql ${Base_Dir}*
if [ ${Version%.*} == 5.7 ];then
    ${Base_Dir}/bin/mysqld --initialize-insecure --user=mysql --basedir=${Base_Dir} --datadir=${Data_Dir}
fi
if [ ${Version%.*} == 5.6 ];then
    ${Base_Dir}/scripts/mysql_install_db --user=mysql --basedir=${Base_Dir} --datadir=${Data_Dir} &> /dev/null
fi
chown -R mysql:mysql ${Base_Dir}*


#显示动态条
i=0;
str=""
arr=("|" "/" "-" "\\")
while [ $i -le 100 ]
do
  let index=i%4
  let indexcolor=i%8
  let color=30+indexcolor
  printf "\e[0;$color;1m[%-100s][%d%%]%c\r\e[0m" "$str" "$i" "${arr[$index]}"
  sleep 0.1
  let i++
  str+='='
done
printf "\n"

echo -e "\033[32m===============================配置mysql启动unit文件================================\033[0m"
#配置mysql服务的unit文件
cat>/usr/lib/systemd/system/mysql.service<<EOF
[Unit]
Description=MySQL Server
Documentation=man:mysqld(8)
Documentation=https://dev.mysql.com/doc/refman/en/using-systemd.html
After=network.target
After=syslog.target

[Install]
WantedBy=multi-user.target

[Service]
User=mysql
Group=mysql
ExecStart=${Base_Dir}/bin/mysqld --defaults-file=/etc/my.cnf
LimitNOFILE = 5000
EOF

if [ $? -eq 0 -a -f /usr/lib/systemd/system/mysql.service ];then
    action "mysql服务的unit文件配置成功!" /bin/true
else
    action "mysql服务的unit文件配置失败!" /bin/false
fi

#重载系统中的unit文件
systemctl daemon-reload

#配置mysql命令的环境变量
echo "export PATH=${Base_Dir}/bin:\$PATH" > /etc/profile.d/mysql.sh
source /etc/profile

#启动、自启mysql服务
echo -e "\033[32m==============================启动mysql并设置开启自启===============================\033[0m"
systemctl start mysql.service
systemctl enable mysql.service
if [ $? -eq 0 ];then
    action "mysql服务启动成功!" /bin/true
else 
    action "mysql服务启动失败!!!" /bin/false
fi

2. 交互式安装脚本

#!/bin/bash
##############################################################
# File Name: mysql_install.sh
# Revision Time: 2023-12-29
# Author: wanhebin
# Organization: www.wanhebin.com
# Description: Binary Install Of MySQL
##############################################################

################################### 定义函数 ###################################
# 定义命令执行是否成功函数
Cmd_Is_True() {
    if [ $? -ne 0 ]; then
            echo -e "\033[31m${1}\033[0m"
            exit 1
    fi
}

# 判断输入Version是否合法
Version_Is_True() {
    Version_1=`echo $Version | awk -F'.' '{print $1}'`
    Version_2=`echo $Version | awk -F'.' '{print $2}'`
    Version_3=`echo $Version | awk -F'.' '{print $3}'`
    Text_Version='[ERROR]\t"msg":"输入不符合规定,或不支持安装此版本!"'
    if [[ ! $Version_1 =~ ^[5]$ ]]; then
        echo -e "\033[31m$Text_Version\033[0m"
        exit 1
    fi
    if [[ ! $Version_2 =~ ^[67]$ ]]; then
        echo -e "\033[31m$Text_Version\033[0m"
        exit 1
    fi
    if [ $Version_2 -eq 6 ]; then
        if [[ ! $Version_3 =~ ^[0-9][0-9]$ || $Version_3 -lt 37 ]]; then
            echo -e "\033[31m$Text_Version\033[0m"
            exit 1
        fi
    fi
    if [ $Version_2 -eq 7 ]; then
            if [[ ! $Version_3 =~ ^[0-9][0-9]$ || $Version_3 -lt 19 ]]; then
            echo -e "\033[31m$Text_Version\033[0m"
                    exit 1
            fi
    fi
}

# 判断目录是否符合规定
Dir_Is_True() {
    if [[ $Base_Dir =~ ^[[:space:]]*$ ]]; then
            Text_Dir='"[ERROR]\t"msg":"安装路劲输入有误!"'
        echo -e "\033[31m$Text_Dir\033[0m"
            exit 1
    fi
}

# 提示确认系统是否已存在MySQL服务
Mysql_Exits() {
    echo ""

}


# 定义菜单函数
menu(){
cat<<EOF
脚本当前支持安装的MySQL版本:
===========================================================
    MySQL 5.6 可支持的安装版本:5.6.37 ~ 5.6.51
    MySQL 5.7 可支持的安装版本:5.7.19 ~ 5.7.40
===========================================================

EOF
}
#################################################################################

# 加载系统函数库
[ -f /etc/init.d/functions ] && source /etc/init.d/functions

# 打印说明
menu

read -p "输入您要安装的MySQL版本(例如:5.7.40):" Version
echo "您输入的版本是: $Version"
# 判断是否为输入是否合规
Version_Is_True

read -p "输入您要安装的目录(例如:/data/service/mysql):" Base_Dir
echo "您输入的安装目录是: $Base_Dir"
# 判断是否为输入是否合规
Dir_Is_True

#Version='5.7.40'
#Base_Dir=/server/mysql
Data_Dir=${Base_Dir}/data
Tmp_Dir=${Base_Dir}/tmp

sleep 3

# 安装必须软件
yum install -y wget

# 下载二进制包
echo -e "\n开始下载mysql-${Version}二进制包..."
[ -f /tmp/mysql-${Version}-linux-glibc2.12-x86_64.tar.gz ] && rm -rf /tmp/mysql-${Version}-linux-glibc2.12-x86_64.tar.gz
wget -O /tmp/mysql-${Version}-linux-glibc2.12-x86_64.tar.gz https://cdn.mysql.com/archives/mysql-${Version%.*}/mysql-${Version}-linux-glibc2.12-x86_64.tar.gz
# 执行判断命令执行函数
Cmd_Is_True '[ERROR]: MySQL二进制包下载失败,请重新执行脚本!'

# 安装依赖
echo -e "\n开始安装所需依赖..."
yum -y install  gcc gcc-c++ cmake ncurses-devel libaio-devel autoconf openssl openssl-devel ncurses-compat-libs

# 解压安装
echo -e "\n开始安装MySQL..."
[ -d /tmp/mysql-${Version}-linux-glibc2.12-x86_64 ] && rm -rf /tmp/mysql-${Version}-linux-glibc2.12-x86_64
tar xf /tmp/mysql-${Version}-linux-glibc2.12-x86_64.tar.gz -C /tmp/
Cmd_Is_True '[WARN] 解压MySQL二进制包过程存在异常,请重新执行脚本!'

# 移动目录 
[ -d ${Base_Dir%/*} ] || mkdir -p ${Base_Dir%/*}
[ -d ${Base_Dir}-${Version} ] && rm -rf ${Base_Dir}-${Version}
mv /tmp/mysql-${Version}-linux-glibc2.12-x86_64 ${Base_Dir}-${Version}

# 创建软连接
rm -rf ${Base_Dir} && ln -s ${Base_Dir}-${Version} ${Base_Dir}

# 创建用户
useradd -M -s /sbin/nologin mysql 2> /dev/null

# 拷贝并修改动脚本
\cp ${Base_Dir}/support-files/mysql.server /etc/init.d/mysqld
sed -i "s@^basedir=@basedir=${Base_Dir}@g" /etc/init.d/mysqld
sed -i "s@^datadir=@datadir=${Data_Dir}@g" /etc/init.d/mysqld
sed -i 's@^PATH.*@PATH="$PATH:/sbin:/usr/sbin:/bin:/usr/bin:$basedir/bin"@g' /etc/init.d/mysqld

# 修改配置文件
\cp /etc/my.cnf{,.bak}
cat>/etc/my.cnf<<EOF
[client]
#password = 
port = 3306
socket = ${Tmp_Dir}/mysql.sock

[mysqld]
port = 3306
socket = ${Tmp_Dir}/mysql.sock
basedir = ${Base_Dir}
datadir = ${Data_Dir}
pid_file = ${Tmp_Dir}/mysql.pid 
log_error = ${Data_Dir}/mysql.err
#general_log = ON
#general_log_file = ${Data_Dir}/mysql_general.log
binlog_cache_size = 32K
thread_stack = 256K
join_buffer_size = 256K
query_cache_type = 1
max_heap_table_size = 128M
default_storage_engine = InnoDB
performance_schema_max_table_instances = 400
table_definition_cache = 400
skip-external-locking
key_buffer_size = 64M
max_allowed_packet = 100G
table_open_cache = 256
sort_buffer_size = 1024K
net_buffer_length = 4K
read_buffer_size = 1024K
read_rnd_buffer_size = 256K
myisam_sort_buffer_size = 16M
thread_cache_size = 32
query_cache_size = 64M
tmp_table_size = 128M
sql-mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES

secure_file_priv=${Tmp_Dir}/

explicit_defaults_for_timestamp = true
#skip_name_resolve = ON
max_connections = 500
max_connect_errors = 100
open_files_limit = 65535

log_bin = mysql-bin
binlog_format = row
server_id = 1
gtid_mode = ON
enforce_gtid_consistency = ON
log_slave_updates = ON

# 增强半同步配置(需要先安装插件: semisync_master.so, semisync_slave.so)
#rpl_semi_sync_master_enabled = 1
#rpl_semi_sync_master_wait_no_slave = ON
#rpl_semi_sync_master_timeout = 10000
#rpl_semi_sync_master_wait_for_slave_count = 1
#rpl_semi_sync_master_wait_point = AFTER_SYNC
#rpl_semi_sync_slave_enabled = 1

max_binlog_size = 512M
expire_logs_days = 10
slow_query_log = 1
slow-query-log-file = ${Data_Dir}/mysql-slow.log
long_query_time = 3
#log_queries_not_using_indexes=on

innodb_data_home_dir = ${Data_Dir}
innodb_data_file_path = ibdata1:10M:autoextend
innodb_log_group_home_dir = ${Data_Dir}
innodb_buffer_pool_size = 256M
innodb_log_file_size = 128M
innodb_log_buffer_size = 32M
innodb_flush_log_at_trx_commit = 1
innodb_lock_wait_timeout = 50
innodb_max_dirty_pages_pct = 90
innodb_read_io_threads = 2
innodb_write_io_threads = 2

[mysqldump]
quick
max_allowed_packet = 500M

[mysql]
no-auto-rehash

[myisamchk]
key_buffer_size = 64M
sort_buffer_size = 1M
read_buffer = 2M
write_buffer = 2M

[mysqlhotcopy]
interactive-timeout
EOF

# 初始化数据库
mkdir ${Base_Dir}/tmp
chown -R mysql:mysql ${Base_Dir}*
if [ ${Version%.*} == 5.7 ];then
    ${Base_Dir}/bin/mysqld --initialize-insecure --user=mysql --basedir=${Base_Dir} --datadir=${Data_Dir}
    Cmd_Is_True '[ERROR] 初始化数据库异常,请检查!'
fi
if [ ${Version%.*} == 5.6 ];then
    ${Base_Dir}/scripts/mysql_install_db --user=mysql --basedir=${Base_Dir} --datadir=${Data_Dir} &> /dev/null
    Cmd_Is_True '[ERROR] 初始化数据库异常,请检查!'
fi
chown -R mysql:mysql ${Base_Dir}*


# 显示动态条
i=0;
str=""
arr=("|" "/" "-" "\\")
while [ $i -le 100 ]
do
  let index=i%4
  let indexcolor=i%8
  let color=30+indexcolor
  printf "\e[0;$color;1m[%-100s][%d%%]%c\r\e[0m" "$str" "$i" "${arr[$index]}"
  sleep 0.1
  let i++
  str+='='
done
printf "\n"

echo -e "\n配置mysql启动unit文件..."
# 配置mysql服务的unit文件
cat>/usr/lib/systemd/system/mysql.service<<EOF
[Unit]
Description=MySQL Server
Documentation=man:mysqld(8)
Documentation=https://dev.mysql.com/doc/refman/en/using-systemd.html
After=network.target
After=syslog.target

[Install]
WantedBy=multi-user.target

[Service]
User=mysql
Group=mysql
ExecStart=${Base_Dir}/bin/mysqld --defaults-file=/etc/my.cnf
LimitNOFILE = 5000
# Restart=always    # 这个配置指示systemd在MySQL服务停止后自动重新启动。
# RestartSec=30s        # 这个配置指定在重新启动之前等待的时间间隔。在这个例子中,设置为30秒。
EOF

if [ $? -eq 0 -a -f /usr/lib/systemd/system/mysql.service ];then
    action "mysql服务的unit文件配置成功!" /bin/true
else
    action "mysql服务的unit文件配置失败!" /bin/false
fi

# 重载系统中的unit文件
systemctl daemon-reload

# 配置mysql命令的环境变量
echo "export PATH=${Base_Dir}/bin:\$PATH" > /etc/profile.d/mysql.sh
source /etc/profile

echo -e "\n"
read -p "是否需要立即启动MySQL服务(输入 True 则立即启动MySQL服务,其他输入则为取消启动!):" Confirm
if [[ $Confirm != "True" ]]; then
        action "MySQl服务安装完成!" /bin/true
    exit 0
fi

# 启动、自启mysql服务
echo -e "\n启动mysql,并设置开启自启"
systemctl start mysql.service
systemctl enable mysql.service
if [ $? -eq 0 ];then
    action "mysql服务启动成功!" /bin/true
else 
    action "mysql服务启动失败!!!" /bin/false
fi


MySQL 8.0 安装脚本

#!/bin/bash
##############################################################
# FileName: mysql_install-v8.x.sh
# RevisionTime: 2024-03-13
# Author: wanhebin
# Description: MySQL 8.x binary installation script.
##############################################################


################################### 定义函数 ###################################
# 定义命令执行是否成功函数
CMD_IS_TRUE() {
    if [ $? -ne 0 ]; then
        echo -e "\033[31m${1}\033[0m"
        exit 1
    fi
}


# 判断输入Version是否符合规定
VERSION_IS_TRUE() {
    local Version_1=`echo $Version | awk -F'.' '{print $1}'`
    local Version_2=`echo $Version | awk -F'.' '{print $2}'`
    local Version_3=`echo $Version | awk -F'.' '{print $3}'`
    local Text_Version='[ERROR]\t"msg":"输入不符合规定,或不支持安装此版本!"'

    if [[ ! $Version_1 =~ ^[8]$ ]]; then
        echo -e "\033[31m${Text_Version}\033[0m"
        exit 1
    fi
    if [[ ! $Version_2 =~ ^[0]$ ]]; then
        echo -e "\033[31m${Text_Version}\033[0m"
        exit 1
    fi
    if [ $Version_2 -eq 0 ]; then
        if [[ ! $Version_3 =~ ^[0-9][0-9]$ || $Version_3 -lt 34 ]]; then
            echo -e "\033[31m${Text_Version}\033[0m"
            exit 1
        fi
    fi
}


# 判断目录是否符合规定
DIR_IS_TRUE() {
    if [[ $Base_Dir =~ ^[[:space:]]*$ ]]; then
        Text_Dir='"[ERROR]\t"msg":"安装路劲输入有误!"'
        echo -e "\033[31m$Text_Dir\033[0m"
        exit 1
    fi
}


# 定义软件包安装函数 
INSTALL_DEPENDENCIES() {
    echo "安装必需的软件包: wget..."
    yum install -y wget
    if [ $? -ne 0 ]; then
        echo "安装 wget 失败"
        return 1
        exit 1
    fi

    echo -e "\n开始安装所需依赖..."
    yum -y install gcc gcc-c++ cmake ncurses-devel libaio-devel autoconf openssl openssl-devel ncurses-compat-libs

    echo "所有必需的软件包和依赖都已成功安装。"
}


# 检测操作系统是否已安装MySQL服务
MYSQL_INSTALL_CHECK() {
    # 检测操作系统是否拥有MySQL服务相关端口、进程
    ProcessNum=$(ps -ef | grep -w [m]ysqld | wc -l)
    PortNum=$(netstat -tln | grep -w 3306 | wc -l)
    if [[ $ProcessNum -ge 1 || $PortNum -ge 1 ]]; then
        local Confirm=False
        read -p "操作系统可能已安装MySQL服务,请确认是否继续(True Or False): " Confirm
        if [[ $Confirm == "False" ]]; then
            echo -e "\033[31m已退出安装!!!\033[0m"
            exit 1
        fi
        # 尝试关闭MySQL服务
        systemctl stop mysql.service &>/dev/null
    fi

    # 检测输入的MySQL安装路径是否已存在
    if [ -d $Base_Dir ]; then
        local Confirm=False
        read -p "${Base_Dir} 目录已存在,继续将清空此目录(True Or False): " Confirm
        if [[ $Confirm == "False" ]]; then
            echo -e "\033[31m已退出安装!!!\033[0m"
            exit 1
        fi
    fi
}


# 定义下载函数,尝试不同的压缩格式、不同glibc版本
DOWNLOAD_MYSQL() {
    local version=$1
    local glibc_versions=("2.28" "2.17" "2.12") # 示例的glibc版本数组,需要根据实际情况调整
    local os_glibc_version=$(ldd --version | head -n1 | grep -oP '\d+(\.\d+)+') # 获取当前操作系统的glibc版本
    local exts=("gz" "xz") # 支持的压缩文件格式
    local found=0

    # 首先检查操作系统的 glibc 版本是否在预定义数组中
    if [[ "${glibc_versions[*]}" =~ "${os_glibc_version}" ]]; then
        # 如果当前系统的glibc版本在预定义的数组中,优先使用它
        glibc_versions=($os_glibc_version)
    else
        # 如果不在,则将操作系统的版本添加到尝试的列表前面
        glibc_versions=($os_glibc_version "${glibc_versions[@]}")
    fi

    for glibc_version in "${glibc_versions[@]}"; do
        for ext in "${exts[@]}"; do
            local url="https://cdn.mysql.com/archives/mysql-${version%.*}/mysql-${version}-linux-glibc${glibc_version}-x86_64.tar.${ext}"
            local http_status=$(curl -o /dev/null -I -L -s -w "%{http_code}" "$url")

            if [ "$http_status" -eq 200 ]; then
                echo "文件存在: $url"
                local file="/tmp/mysql-${version}-linux-glibc${glibc_version}-x86_64.tar.${ext}"
                echo "开始下载..."
                wget -O "$file" "$url" && found=1 && echo "${file} 下载成功"
                if [[ $found -eq 1 ]]; then
                    echo "已成功下载文件,终止其他下载尝试。"
                    return 0 # 成功下载后退出函数
                fi
            else
                echo "未找到文件: $url"
            fi
        done
        if [[ $found -eq 1 ]]; then break; fi # 成功下载后退出外层循环
    done

    if [[ $found -eq 0 ]]; then
        echo "无法找到兼容的MySQL二进制文件。请检查glibc版本或MySQL版本。"
        exit 1
    fi
}


# 定义菜单函数
MENU(){
cat<<EOF
脚本当前支持安装的 MySQL 版本:
===========================================================
    MySQL 8.0 可支持的安装版本:    8.0.34 ~ 8.0.35
===========================================================

EOF
}


#################################################################################

# 加载系统函数库
[ -f /etc/init.d/functions ] && source /etc/init.d/functions

# 打印说明
MENU

read -p "输入您要安装的MySQL版本(例如: 8.0.34): " Version
echo "您输入的版本是: $Version"
# 判断是否为输入是否合规
VERSION_IS_TRUE

read -p "输入您要安装的目录(例如: /data/service/mysql): " Base_Dir
echo "您输入的安装目录是: $Base_Dir"
# 判断是否为输入是否合规
DIR_IS_TRUE

# 提示确认系统是否已存在MySQL服务
MYSQL_INSTALL_CHECK

#Version='8.0.34'
#Base_Dir=/data/service/mysql
Data_Dir=${Base_Dir}/data
Tmp_Dir=${Base_Dir}/tmp

sleep 3

# 安装必须软件
INSTALL_DEPENDENCIES

# 下载二进制包
echo -e "\n开始下载mysql-${Version}二进制包..."
DOWNLOAD_MYSQL ${Version}

# 执行判断命令执行函数
CMD_IS_TRUE '[ERROR]: MySQL二进制包下载失败,请重新执行脚本!'


# 解压安装
echo -e "\n开始安装MySQL..."
[ -d /tmp/mysql-${Version}-linux-glibc${glibc_version}-x86_64 ] && rm -rf /tmp/mysql-${Version}-linux-glibc${glibc_version}-x86_64
file_gz="/tmp/mysql-${Version}-linux-glibc${glibc_version}-x86_64.tar.gz"
file_xz="/tmp/mysql-${Version}-linux-glibc${glibc_version}-x86_64.tar.xz"
if [[ -f "$file_gz" && -s "$file_gz" ]]; then
    tar xf /tmp/mysql-${Version}-linux-glibc${glibc_version}-x86_64.tar.gz -C /tmp/
    CMD_IS_TRUE '[WARN] 解压MySQL二进制包过程存在异常,请重新执行脚本!'
elif [[ -f "$file_xz" && -s "$file_xz" ]]; then
    tar xf /tmp/mysql-${Version}-linux-glibc${glibc_version}-x86_64.tar.xz -C /tmp/
    CMD_IS_TRUE '[WARN] 解压MySQL二进制包过程存在异常,请重新执行脚本!'
else
    echo "没有找到合适的压缩文件进行解压"
    exit 1
fi

# 移动目录
[ -d ${Base_Dir%/*} ] || mkdir -p ${Base_Dir%/*}
[ -d ${Base_Dir}-${Version} ] && rm -rf ${Base_Dir}-${Version}
mv /tmp/mysql-${Version}-linux-glibc${glibc_version}-x86_64 ${Base_Dir}-${Version}

# 创建软连接
rm -rf ${Base_Dir} && ln -s ${Base_Dir}-${Version} ${Base_Dir}

# 创建用户
useradd -M -s /sbin/nologin mysql 2> /dev/null

# 拷贝并修改动脚本
\cp ${Base_Dir}/support-files/mysql.server /etc/init.d/mysqld
sed -i "s@^basedir=@basedir=${Base_Dir}@g" /etc/init.d/mysqld
sed -i "s@^datadir=@datadir=${Data_Dir}@g" /etc/init.d/mysqld
sed -i 's@^PATH.*@PATH="$PATH:/sbin:/usr/sbin:/bin:/usr/bin:$basedir/bin"@g' /etc/init.d/mysqld

# 修改配置文件
\cp /etc/my.cnf{,.bak}
cat>/etc/my.cnf<<EOF
[client]
port = 3306
socket = ${Tmp_Dir}/mysql.sock


[mysqld]
port = 3306
socket = ${Tmp_Dir}/mysql.sock
basedir = ${Base_Dir}
datadir = ${Data_Dir}
pid_file = ${Tmp_Dir}/mysql.pid
log_error = ${Data_Dir}/mysql.err

# 事务隔离级别,默认为 REPEATABLE READ(强一致)。这里设置为 READ-COMMITTED(高并发)。
transaction_isolation = 'READ-COMMITTED'
transaction_prealloc_size = 4096

# 默认字符集编码设置,保留utf8mb4,这是MySQL 8推荐的字符集
character-set-server = utf8mb4
collation-server = utf8mb4_general_ci

# 开启只读模式,一般用于配置在从库
#read_only = 1

# 慢查询配置
slow_query_log = 1
slow_query_log_file = ${Data_Dir}/mysql-slow.log
long_query_time = 1

# BINLOG 相关配置
enforce_gtid_consistency = ON
gtid_mode = ON
log_bin = mysql-bin
log_replica_updates = ON
binlog_format = row
binlog_expire_logs_seconds = 1296000
max_binlog_size = 1024M

# 增强半同步配置(需要先安装插件: semisync_master.so, semisync_slave.so)
#rpl_semi_sync_master_enabled = 1
#rpl_semi_sync_master_wait_no_slave = ON
#rpl_semi_sync_master_timeout = 10000
#rpl_semi_sync_master_wait_for_slave_count = 1
#rpl_semi_sync_master_wait_point = AFTER_SYNC
#rpl_semi_sync_slave_enabled = 1

# 时区配置,默认为 UTC
#default-time-zone = +08:00

auto_increment_increment = 1
auto_increment_offset = 1
automatic_sp_privileges = ON
back_log = 3000                    # 控制在服务器暂时无法接受新连接请求时,操作系统队列中可以积压的连接数量
binlog_cache_size = 2M
binlog_checksum = CRC32
binlog_order_commits = ON
binlog_transaction_dependency_tracking = WRITESET
binlog_row_event_max_size = 8K
binlog_row_image = FULL
binlog_rows_query_log_events = OFF
binlog_stmt_cache_size = 32K
block_encryption_mode = AES-128-ECB
bulk_insert_buffer_size = 8M
character_set_filesystem = BINARY
character_set_server = utf8mb4
collation_server = utf8mb4_0900_ai_ci
concurrent_insert = AUTO
connect_timeout = 10
default_storage_engine = INNODB
default_week_format = 0

# MySQL 8.0中,默认使用 caching_sha2_password 作为认证插件,而在MySQL 5.7中,默认使用 mysql_native_password 。
# 为了考虑兼容性问题,这里选择 mysql_native_password
default_authentication_plugin = mysql_native_password
default_password_lifetime = 0

join_buffer_size = 256K            # 默认配置的值最低适用于1C2G,请根据该公式调整 {MIN(DBInitMemory*128,262144)}
interactive_timeout = 7200
max_heap_table_size = 64M
performance_schema_max_table_instances = 8000
key_buffer_size = 64M
max_allowed_packet = 1G
sort_buffer_size = 848K
net_buffer_length = 16K
read_buffer_size = 8192
read_rnd_buffer_size = 512K
myisam_sort_buffer_size = 8M
sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
table_definition_cache = 2048        # 默认配置的值最低适用于1C2G,请根据该公式调整 {MAX(DBInitMemory*512/1000,2048)}
table_open_cache = 2048                # 默认配置的值最低适用于1C2G,请根据该公式调整 {MAX(DBInitMemory*512/1000,2048)}
table_open_cache_instances = 2        # 默认配置的值最低适用于1C2G,请根据该公式调整 {MIN(DBInitMemory/1000,16)}
thread_cache_size = 512
thread_handling = one-thread-per-connection
thread_stack = 512K
#thread_pool_oversubscribe = 10
#thread_pool_size = 1            # 默认配置的值最低适用于1C2G,请根据该公式调整 {MIN(DBInitCpu,64)}    (仅支持企业版)

innodb_file_per_table = ON
innodb_buffer_pool_size = 1G    # 默认配置的值最低适用于1C2G,请根据该公式调整 {DBInitMemory*786432}
innodb_redo_log_capacity = 1G
innodb_log_buffer_size = 32M
innodb_flush_log_at_trx_commit = 1
innodb_thread_concurrency = 0
innodb_lock_wait_timeout = 50
innodb_max_dirty_pages_pct = 75
innodb_read_io_threads = 4        # 默认配置的值最低适用于1C2G,请根据该公式调整 {MAX(DBInitCpu/2,4)}
innodb_write_io_threads = 4        # 默认配置的值最低适用于1C2G,请根据该公式调整 {MAX(DBInitCpu/2,4)}

#skip_name_resolve = ON
max_connections = 1000            # 默认配置的值最低适用于1C2G,请根据该公式调整 {MIN(DBInitMemory/4+500,100000)}
max_connect_errors = 999999999
max_error_count = 64
max_execution_time = 0
open_files_limit = 65535        # 推荐设置为65535或更高。可通过执行 ulimit -n 命令查看操作系统限制

# 启用插件
#plugin-load-add = thread_pool.so    # 线程池插件    (仅支持企业版)


[mysqldump]
quick
max_allowed_packet = 1G


[mysql]

EOF


# 初始化数据库
mkdir ${Base_Dir}/tmp
chown -R mysql:mysql ${Base_Dir}*
if [ ${Version%.*} == 8.0 ];then
    ${Base_Dir}/bin/mysqld --defaults-file=/etc/my.cnf --user=mysql --initialize-insecure --basedir=${Base_Dir} --datadir=${Data_Dir}
    CMD_IS_TRUE '[ERROR] 初始化数据库异常,请检查!'
fi
chown -R mysql:mysql ${Base_Dir}*


# 显示动态条
i=0;
str=""
arr=("|" "/" "-" "\\")
while [ $i -le 100 ]
do
  let index=i%4
  let indexcolor=i%8
  let color=30+indexcolor
  printf "\e[0;$color;1m[%-100s][%d%%]%c\r\e[0m" "$str" "$i" "${arr[$index]}"
  sleep 0.1
  let i++
  str+='='
done
printf "\n"


# 配置mysql服务的unit文件
echo -e "\n配置mysql启动unit文件..."
cat>/usr/lib/systemd/system/mysql.service<<EOF
[Unit]
Description=MySQL Server
Documentation=man:mysqld(8)
Documentation=https://dev.mysql.com/doc/refman/en/using-systemd.html
After=network.target
After=syslog.target

[Install]
WantedBy=multi-user.target

[Service]
User=mysql
Group=mysql
Type=forking
ExecStart=${Base_Dir}/bin/mysqld --defaults-file=/etc/my.cnf --daemonize
LimitNOFILE = 65535
Restart=on-failure    # 让systemd在MySQL异常退出时尝试重启服务
RestartSec=30s        # 这个配置指定在重新启动之前等待的时间间隔。在这个例子中,设置为30秒。
#ProtectHome=true
#ProtectSystem=full
#PrivateTmp=true
EOF
if [ $? -eq 0 -a -f /usr/lib/systemd/system/mysql.service ];then
    action "mysql服务的unit文件配置成功!" /bin/true
else
    action "mysql服务的unit文件配置失败!" /bin/false
fi


# 重载系统中的unit文件
systemctl daemon-reload


# 配置mysql命令的环境变量
echo "export PATH=${Base_Dir}/bin:\$PATH" > /etc/profile.d/mysql.sh
source /etc/profile

echo -e "\n"
Confirm=False
read -p "是否需要立即启动MySQL服务(输入 True 则立即启动MySQL服务,其他输入则为取消启动!): " Confirm
if [[ $Confirm != "True" ]]; then
    action "MySQl服务安装完成!" /bin/true
    exit 0
fi


# 启动、自启mysql服务
echo -e "\n启动MySQL,并设置开启自启"
systemctl enable mysql.service --now
if [ $? -eq 0 ];then
    action "MySQL服务启动成功!" /bin/true
else 
    action "MySQL服务启动失败!!!" /bin/false
fi