Mysql二进制部署脚本 | Readme

Mysql二进制部署脚本,在Ubuntu上自动化单实例、多实例mysql的部署。

Gist上 基于python的单mysql二进制的部署脚本 | github gist的说明文档。

mysql_binary_install.py 是一个单文件 MySQL Generic 二进制安装工具,在 Linux 本机完成安装、初始化、设置 root 密码、注册 systemd 服务,以及卸载或清理安装残留。每次执行管理一个实例,多次执行可部署不同端口的实例。

边界:

  • 脚本不自动下载 MySQL 安装包,不搭建复制、MGR、Router,也不配置防火墙、远程 SSH 或主机调优。
  • 不包含 远程SSH配置,主从复制、MGR、Router、防火墙、主机调优逻辑。
  • 自动补齐运行时动态库可能调用 APT、DNF 或 YUM。脚本使用 Python 标准库,通过 ldd 检查 mysqld、mysql 的动态库,必要时自动安装可识别的系统依赖包;这要求软件源可用。离线部署应提前准备好动态库和解压工具。未知依赖、软件源没有候选包等情况需要人工处理。

条件:

  • 提前准备可信来源的 MySQL Community Generic .tar.xz 或 .tar.gz 安装包,以及官方提供的 32 位 MD5。MD5 用于比对文件,不能替代可信来源或签名验证。
  • Linux 主机,Python 3.10 或以上;实际安装、卸载需要 root 或 sudo。不支持windows / macos,dry-run执行也必须在 Linux 上执行。
  • 使用 systemd 管理服务;主机需要提供 tar、chown、getent、id、groupadd、useradd、runuser、systemctl,创建软件入口还会使用 ln。解压 .tar.xz 需要对应的解压支持。
  • 安装包架构需与主机匹配,脚本识别 x86_64 和 aarch64;若文件名标明 glibc 版本,主机 glibc 不得低于该版本。保留官方包名,避免架构检查失败。
  • 软件入口的父目录必须已经存在;配置文件、目标 systemd unit 不得已存在,数据目录必须不存在或为空,端口必须空闲。
  • 默认 buffer pool 为 1G,应按主机可用内存调整。脚本对磁盘可用空间低于 10 GiB、物理内存低于 512 MiB 只发出提醒,不会据此阻止安装。

安装

默认安装配置

部署路径:

项目 3306 实例 非 3306 实例(以 3307 为例)
软件目录 basedir /usr/local/mysql 软链接到 实际二进制解压缩的位置 /usr/local/mysql
数据目录 datadir /var/lib/mysql /var/lib/mysql-3307
mysql 配置文件 /etc/xx.cnf /etc/my.cnf /etc/my-3307.cnf
Unix socket /var/lib/mysql/mysql.sock
也就是 ${datadir}/mysql.sock
/var/lib/mysql-3307/mysql.sock
systemd service 服务名 mysqld.service mysqld-3307.service
systemd service unit 文件 /etc/systemd/system/mysqld.service /etc/systemd/system/mysqld-3307.service

默认部署路径:

  • 二进制包 解压缩到:/usr/local/mysql-8.0.46-linux-glibc2.28-x86_64 中。

  • myqsl的软件目录 basedir:软链接 /usr/local/mysql link 到 /usr/local/mysql-8.0.46-linux-glibc2.28-x86_64。多个mysql实例可以共用一个 二进制包解压缩的位置。

  • mysql的数据目录 datadir:/var/lib/mysql{}/

    • 3306端口:/var/lib/myqsl
    • 非3306端口:/var/lib/mysql-xxxx
  • UnixSocket:${datadir}/mysql.sock 也就是 /var/lib/mysql/mysql.scok

默认cnf配置:参考render_config()函数,生成单实例的my.cnf

  • bind-address默认监听 127.0.0.1,default-character-set/character-set-server字符集 utf8mb4,排序规则collation-server utf8mb4_unicode_ci。

  • server-id 默认使用端口值,时区default-time-zone 为 +08:00,最大连接数max_connections为 500。

  • buffer-pool大小由innodb-buffer-pool-size控制,大小1G。

  • redo log的持久化策略为1,事务提交时落盘:`innodb_flush_log_at_trx_commit = 1`

  • relay-log存放在datadir/relay-bin中。

  • binlog默认开启,相关配置如下:

    • log-bin 位置放在 /var/lib/mysql/binlog/mysql-bin。
    • sync_binlog:设置为1,事务提交时 落盘。
    • 默认 开启gtid,gitd_mode=ON, enforce_gtid_consistency = ON
    •     if options.binlog == "ON":
              lines += [
                  "",
                  "# --- binlog 配置 ---",
                  f"log-bin = {options.datadir / 'binlog' / 'mysql-bin'}",
                  "binlog_format = ROW",
                  "sync_binlog = 1",
                  "# 从库回放的事务也写入自己的 binlog,级联复制和故障切换必需",
                  (
                      "log_slave_updates = ON"
                      if options.mysql_version == "5.7"
                      else "log_replica_updates = ON"
                  ),
                  "# GTID 核心参数",
                  "# 所有事务都必须有gtid",
                  "gtid_mode = ON",
                  "# 禁止不兼容gtid的sql",
                  "enforce_gtid_consistency = ON",
              ]
              if options.mysql_version == "5.7":
                  lines.append("expire_logs_days = 7")
              else:
                  lines.append("binlog_expire_logs_seconds = 604800")
          else:
              # 明确写 skip-log-bin,避免主机默认配置意外开启 binlog。
              lines.append("skip-log-bin")
      

单实例安装

预览安装

sudo python3 mysql_binary_install.py \
  --mysql-version 8.0 \
  --archive ~/mysql/Notes-Mysql/Mysql-Installer/mysql-8.0.37-linux-glibc2.28-x86_64.tar.xz \
  --md5sum 4ef87d5f5160a6565e767ec10002ce74 \
  --root-password 'b617@cumt' \
  --dry-run
  --verbose

预览会实际读取安装包、计算 MD5、检查包结构、系列版本、主机兼容性、路径和端口,但不会解压、安装依赖、初始化数据库或启动服务,也不会要求输入 root 密码。因此,预览成功不代表运行时依赖或服务启动一定成功。加上 --verbose 可查看拟生成的配置内容。

正式安装

sudo python3 mysql_binary_install.py \
  --mysql-version 8.0 \
  --archive ~/mysql/Notes-Mysql/Mysql-Installer/mysql-8.0.37-linux-glibc2.28-x86_64.tar.xz \
  --md5sum 4ef87d5f5160a6565e767ec10002ce74 \
  --root-password 'b617@cumt'
  • mysql-version:对应二进制包的mysql版本
  • md5sum:二进制包的md5和,用于校验是否相等。
  • root-password:默认创建的root账号密码,该密码用于 root@localhost 和本机 TCP 账号 [email protected]。

多实例安装

上面我们在3306端口默认安装,接下来在3307和3308端口进行多实例安装

sudo python3 mysql_binary_install.py \
  --archive ~/mysql/Notes-Mysql/Mysql-Installer/mysql-8.0.37-linux-glibc2.28-x86_64.tar.xz \
  --md5sum 4ef87d5f5160a6565e767ec10002ce74 \
  --root-password 'b617@cumt' \
  --port 3306 \
  --bind-address 0.0.0.0 \
  --server-id 101 \
  --report-host 127.0.0.1 \
  --report-port 3306

sudo python3 mysql_binary_install.py \
  --archive ~/mysql/Notes-Mysql/Mysql-Installer/mysql-8.0.37-linux-glibc2.28-x86_64.tar.xz \
  --md5sum 4ef87d5f5160a6565e767ec10002ce74 \
  --root-password 'b617@cumt' \
  --port 3307 \
  --bind-address 0.0.0.0 \
  --server-id 102 \
  --report-host 127.0.0.1 \
  --report-port 3307 \
  --datadir /var/lib/mysql-3307 \
  --config /etc/my-3307.cnf

sudo python3 mysql_binary_install.py \
  --archive ~/mysql/Notes-Mysql/Mysql-Installer/mysql-8.0.37-linux-glibc2.28-x86_64.tar.xz \
  --md5sum 4ef87d5f5160a6565e767ec10002ce74 \
  --root-password 'b617@cumt' \
  --port 3308 \
  --bind-address 0.0.0.0 \
  --server-id 103 \
  --report-host 127.0.0.1 \
  --report-port 3308 \
  --datadir /var/lib/mysql-3308 \
  --config /etc/my-3308.cnf

参数一览

安装参数

参数 默认值 说明
--mysql-version 8.0 系列版本,接受 5.7、8.x、9.x 格式;不接受 8.4.5 这样的补丁版本。具体补丁由安装包决定,接受参数格式不代表所有系列均经过部署验证
--archive 无 安装必填,本地 .tar.xz 或 .tar.gz 的绝对路径
--md5sum 无 安装必填,32 位十六进制 MD5,大小写均可
--port 3306 TCP 端口,范围 1~65535,同时决定默认路径和服务名
--basedir /usr/local/mysql mysql本地的软件入口,软链接到二进制包解压缩位置。
--datadir 按端口推导 数据目录;卸载时必须显式提供。
默认端口3306:/var/lib/mysql。
其他端口:/var/lib/mysql-3307, /var/lib/mysql-3308。
--socket <datadir>/mysql.sock Unix socket 路径;自定义时需保证父目录及权限适合 mysql 用户使用
--config 按端口推导 配置文件路径;卸载时必须显式提供
--bind-address 127.0.0.1 监听地址
--server-id 默认与 --port 相同 范围 1~4294967295
--report-host 不写入 复制上报地址
--report-port 设置 report-host 时使用实例端口,否则不写入 上报端口,范围 1~65535,也可单独指定
--time-zone +08:00 固定偏移,如 +08:00,或 SYSTEM 跟随系统时区
--root-password 交互输入并确认 非交互安装必须提供;预览可省略
--charset utf8mb4 服务端及客户端字符集
--collation utf8mb4_unicode_ci 服务端排序规则,需与字符集及目标版本兼容
--binlog ON 仅接受大写 ON、OFF;ON 时配置 binlog+GTID,OFF 时写入 skip-log-bin 且不写入启用 GTID 的配置
--innodb-buffer-pool-size 1G 整数,可带 K/M/G 单位,如 512M、2G;不支持 1.5G
--max-connections 500 正整数

所有路径参数必须是绝对路径,不能含 ..;脚本支持展开 ~,但 sudo 环境下建议直接写完整路径。软件和数据目录不能相同或互相包含,配置文件不能放在数据目录内。路径检查通常拒绝经过符号链接,软件入口的最终链接除外。

卸载参数

参数 说明
--uninstall / --cleanup 同一开关,卸载完整实例或识别并清理未完成安装
--confirm-delete-data 卸载必填,原样重复数据目录的绝对路径,即使预览也需要
--purge-basedir 卸载时额外删除软件入口和实际软件目录,默认不删除
--confirm-delete-basedir 配合 --purge-basedir,原样重复 basedir 的绝对路径
--dry-run 预览安装或卸载,不执行对应系统变更;日志文件例外见前文
--log-file 额外日志文件的绝对路径,父目录会自动创建
--verbose 输出 DEBUG 日志,包括生成的配置内容
--version 显示工具版本
-h / --help 查看命令行帮助

连接与服务管理

服务安装后立即启动并设置开机自启,脚本当前不会写入 /etc/profile.d/mysql.sh 或自动设置 PATH,如果需要方便本地使用,可以使用alias自定义快捷命令加入**zshrc/bashrc**中。

alias mysql3306='/usr/local/mysql/bin/mysql -uroot -h127.0.0.1 -P3306 -pb617@cumt'

这里的mysql是二进制包中的mysql客户端工具,通过mysql -uroot -hxxx -P3306 -p来连接,这里定义后直接mysql3306进入服务器终端。

使用systemd来管理:

sudo systemctl status mysqld.service --no-pager
# 可以简写成 systemctl status mysqld-3307, mysqld-3308, mysqld(对应mysqld-3306)
sudo systemctl restart mysqld.service
sudo systemctl stop mysqld.service
sudo systemctl start mysqld.service
sudo journalctl -u mysqld.service -n 100 --no-pager
sudo tail -n 100 /var/lib/mysql/mysql-error.log

卸载

# dry run 
sudo python3 mysql_binary_install.py --uninstall \
  --datadir /var/lib/mysql \
  --config /etc/my.cnf \
  --confirm-delete-data /var/lib/mysql
  --dry-run

# 确认目标后,执行卸载
# --basedir: 指定了 basedir,但是不会删除basedir,这里只是指定
sudo python3 mysql_binary_install.py --uninstall \
  --datadir /var/lib/mysql \
  --config /etc/my.cnf \
  --confirm-delete-data /var/lib/mysql

# 卸载3307
# --basedir: 指定了 basedir,但是不会删除basedir,这里只是指定
sudo python3 mysql_binary_install.py --uninstall \
  --port 3307 \
  --basedir /usr/local/mysql \
  --datadir /var/lib/mysql-3307 \
  --config /etc/my-3307.cnf \
  --confirm-delete-data /var/lib/mysql-3307

# 卸载3308 
# --basedir: 指定了 basedir,但是不会删除basedir,这里只是指定
sudo python3 mysql_binary_install.py --uninstall \
  --port 3308 \
  --basedir /usr/local/mysql \
  --datadir /var/lib/mysql-3308 \
  --config /etc/my-3308.cnf \
  --confirm-delete-data /var/lib/mysql-3308

如果需要删除mysql软件目录,可以在卸载命令中添加:

--purge-basedir \
--confirm-delete-basedir /usr/local/mysql

# 即
# 只有确认软件目录不再被其他实例共享时,才额外删除软件目录
sudo python3 mysql_binary_install.py --uninstall \
  --datadir /var/lib/mysql \
  --config /etc/my.cnf \
  --confirm-delete-data /var/lib/mysql \
  --purge-basedir \
  --confirm-delete-basedir /usr/local/mysql

对应安装

sudo python3 mysql_binary_install.py \
  --archive ~/mysql/Notes-Mysql/Mysql-Installer/mysql-8.0.37-linux-glibc2.28-x86_64.tar.xz \
  --md5sum 4ef87d5f5160a6565e767ec10002ce74 \
  --root-password 'b617@cumt' \
  --port 3306 \
  --bind-address 0.0.0.0 \
  --server-id 101 \
  --report-host 127.0.0.1 \
  --report-port 3306

sudo python3 mysql_binary_install.py \
  --archive ~/mysql/Notes-Mysql/Mysql-Installer/mysql-8.0.37-linux-glibc2.28-x86_64.tar.xz \
  --md5sum 4ef87d5f5160a6565e767ec10002ce74 \
  --root-password 'b617@cumt' \
  --port 3307 \
  --bind-address 0.0.0.0 \
  --server-id 102 \
  --report-host 127.0.0.1 \
  --report-port 3307 \
  --datadir /var/lib/mysql-3307 \
  --config /etc/my-3307.cnf

sudo python3 mysql_binary_install.py \
  --archive ~/mysql/Notes-Mysql/Mysql-Installer/mysql-8.0.37-linux-glibc2.28-x86_64.tar.xz \
  --md5sum 4ef87d5f5160a6565e767ec10002ce74 \
  --root-password 'b617@cumt' \
  --port 3308 \
  --bind-address 0.0.0.0 \
  --server-id 103 \
  --report-host 127.0.0.1 \
  --report-port 3308 \
  --datadir /var/lib/mysql-3308 \
  --config /etc/my-3308.cnf

安装失败清理

安装失败后,脚本根据失败阶段处理:

  1. 初始化流程成功返回前失败: 自动尝试回滚本次新建的datadir数据目录、软件链接和mycnf配置。已有目录、系统账号和已安装的依赖包不会自动删除。
  2. 初始化流程成功返回后失败:保留数据和配置,需要检查日志后,手动执行清理。

mysqlinstall-instance-id 是脚本为本次安装生成的 UUID,用来确认配置、数据和服务属于同一个实例,避免删错数据库。它会出现在三处:

位置 写入时间与形式
配置文件,例如/etc/my.cnf 初始化前写入:# mysqlinstall-instance-id: UUID
systemd unit 初始化后注册服务时写入同样的注释
数据目录内.mysqlinstall-instance-id 全部安装验证通过后才写入,文件内容为 UUID
❯ cat /etc/my.cnf
# mysqlinstall-instance-id: 0f3655c1-420b-4966-88d6-180e01faa1b5
[client]
port = 3306
socket = /var/lib/mysql/mysql.sock

[mysql]
default-character-set = utf8mb4

[mysqld]
...

❯ cat /etc/systemd/system/mysqld.service
# mysqlinstall-instance-id: 0f3655c1-420b-4966-88d6-180e01faa1b5
[Unit]
Description=MySQL Server (mysqld)
After=network.target

/var/lib/mysql                                                              with root@aios
❯ cat .mysqlinstall-instance-id
0f3655c1-420b-4966-88d6-180e01faa1b5

因此,安装失败时没有数据目录标记文件是正常的;配置文件里的标记是清理的必要依据。

手动清理时,先预览:

sudo python3 mysql_binary_install.py --cleanup \
  --port 3306 \
  --basedir /usr/local/mysql \
  --datadir /var/lib/mysql \
  --config /etc/my.cnf \
  --confirm-delete-data /var/lib/mysql \
  --dry-run

确认目标正确、需要的数据已备份后,移除 --dry-run 再执行。这会永久删除整个数据目录。 自定义端口和路径必须改成安装时的实际值。

实际清理流程是:

  1. 检查配置文件mycnf的 instance-id,以及 basedir、datadir、port 是否与清理参数一致。
  2. 数据目录标记和 unit 如果存在,检查它们的 instance-id 是否一致;缺失则按未完成安装处理。
  3. 停止并禁用对应服务,检查服务和 PID 是否仍在运行。
  4. 删除数据目录、配置文件和对应 unit,并重载 systemd。

如果配置文件已丢失、没有 instance-id,或者标记不一致,脚本会拒绝清理。这时需要人工确认残留归属,不能靠补写或修改标记绕过检查。