如果你因为某些老旧项目、内部系统或者特定软件兼容性问题,不得不面对 MySQL 5.6.51,那你大概率最后会把目光落在官方发布的 Linux Generic 二进制包上。这个名为mysql-5.6.51-linux-glibc2.12-x86_64.tar.gz的压缩包,几乎适用于所有现代 x86_64 Linux 发行版,不依赖系统自带的包子管理器,部署路径完全可控。它适合需要在脱离发行版默认软件源、锁定数据库版本或自定义安装目录的场景下手工安装 MySQL 的运维和开发,也是一份能让你彻底搞清楚 MySQL 安装逻辑的有效入口。
今天这篇就把安装全过程拆开揉碎地讲一遍,从“为什么要用 Generic 包”到“初始化、启动、安全加固、常见报错”,全部结合我实际操作中踩过的坑来写。你可以直接把它当成一份可复现的作业指南,也可以事后翻回来做问题排查手册。这里不搞花架子,全部是实打实的命令和步骤。
1. 为什么选 Generic 二进制包而不是系统源安装
1.1 不同发行版源里的 MySQL 处境很尴尬
很多人一开始图省事,直接用yum install mysql-server或apt install mysql-server,结果发现:CentOS 7 自带的源里是 MariaDB,Ubuntu 各版本源里的 MySQL 版本会随着系统发布迭代,根本没法精确锁定到 5.6.51。如果你面对的是一个内部老系统,程序代码里写死了某些 5.6 独有的参数行为,或者依赖mysql-5.6版本的客户端连接协议,那么从系统源安装出来的数据库很可能不兼容。这种“版本错配”的坑,比安装本身更让人头疼。
Generic 包是 MySQL 官方直接编译好的“通用二进制”版本。它不会动你的系统源,不往/usr/lib里塞依赖库,也不会抢占系统默认的/var/lib/mysql位置。所有文件都集中在压缩包内,你可以解压到任意路径,并自定义数据目录。对于只想跑一个独立实例、甚至多实例并存的场景,这种自由度是系统源给不了的。
1.2 什么时候不建议用 Generic 包
不过话说回来,Generic 包不是银弹。如果你的需求只是本地开发快速起一个 MySQL,且系统源里的版本完全够用,那我建议你直接用apt install mysql-server,省时省力。Generic 包需要手动处理的东西很多:依赖库、用户权限、初始化脚本、开机自启、SELinux 策略,每一样都可能把你绊一跤。
此外,Generic 包在更新升级方面也偏“手工党”。官方已经结束了 5.6 系列的常规维护,安全补丁非常有限,生产环境除非有强兼容性约束,否则我不建议新项目选它。但如果你确实需要它,下面是完整路线。
2. 安装前的环境准备与依赖确认
2.1 确认系统和架构
执行安装之前,先确认你到底在什么环境上操作。用下面三条命令:
cat /etc/os-release uname -m free -h df -h /usr/localos-release告诉你发行版和版本号,uname -m确认是不是x86_64。Generic 包提供了x86_64和i686版本,现在绝大多数服务器都是x86_64。内存建议至少 1G 以上,磁盘则要看你的数据量规划,不过仅仅是安装 MySQL 本身,解压后大约占用 800M 左右,数据目录另算。
这里有个很多人忽略的地方:因为 5.6 是旧版本,它在较新内核和较新 glibc 上运行一般没问题,但如果在过于精简的容器镜像里运行,很可能缺库。
2.2 缺失依赖库的处理
MySQL 5.6 Generic 包依赖几个动态库,最常遇到的是libaio.so.1和libnuma.so.1。启动时报错通常会这样:
error while loading shared libraries: libaio.so.1: cannot open shared object file解决方式按发行版来:
Debian/Ubuntu:
apt update apt install -y libaio1 libnuma1CentOS/RHEL/Fedora:
yum install -y libaio numactl-libs有的精简系统还会缺libncurses.so.5,5.6 本身用不到,但部分工具可能依赖。如果你装完执行mysql --version报错里面有libncurses,就再补包。通过ldd mysql可以一次性看到所有动态依赖是否满足,建议养成检查依赖的习惯:
cd /usr/local/mysql/libexec ldd mysqld看到not found就说明少了库,先补依赖再继续,别硬启动。
2.3 创建专用的运行用户
安全方面,坚决不要用 root 运行 mysqld。MySQL 官方也强调要用独立的低权限用户运行服务。创建方式通常如下:
groupadd mysql useradd -r -g mysql -s /bin/false mysql-s /bin/false让该用户无法登录 shell,降低人为误操作和攻击风险。安装目录和数据目录后续都归这个用户所有。如果系统里已经存在名为 mysql 的用户或组,检查一下属主和是否被其他服务占用,避免冲突。
2.4 清理历史痕迹和数据目录
如果你是在一台已经装过 MySQL/MariaDB 的机器上重新安装,务必先停掉旧服务并清理旧数据。检查是否已有进程:
ps -ef | grep mysqld ss -lntp | grep 3306如果端口被占用,先处理旧进程,否则即使装完也起不来。另外,如果之前安装的系统版 MySQL 残留了/etc/my.cnf,可能会干扰 Generic 包实例。建议先把残留配置文件备份后移走,或者安装后强制指定覆盖配置,避免莫名其妙被旧参数带偏。
3. 下载官方 Generic 包并校验
3.1 下载地址和镜像选择
MySQL 官方下载页可以拿到 5.6.51 的 Generic 包,常见文件名是:
mysql-5.6.51-linux-glibc2.12-x86_64.tar.gz如果你在服务器上直接下载,可以用类似这样的命令:
wget https://dev.mysql.com/get/Downloads/MySQL-5.6/mysql-5.6.51-linux-glibc2.12-x86_64.tar.gz外网速度慢的话,建议找国内 CDN 或厂商镜像源。注意检查文件名里的glibc2.12,它表示编译时链接的是 glibc 2.12 版本的库,只要你的系统 glibc 版本不低于 2.12 就能运行。CentOS 6/7、Ubuntu 16/18 等老系统都能满足,现代系统更没问题。
3.2 校验文件完整性
下载完成后千万不要急着解压,先做完整性校验。MySQL 官网每个下载包旁边都会提供 MD5 和 SHA256 校验值。执行:
md5sum mysql-5.6.51-linux-glibc2.12-x86_64.tar.gz sha256sum mysql-5.6.51-linux-glibc2.12-x86_64.tar.gz把输出结果和官网给出的值逐字对比。这一步看起来多余,但网络传输中文件损坏真的很常见,而且有人曾经因为下载了被篡改的包导致数据库崩溃。稳妥做一次,不亏。
3.3 解压和建立软链接
将包解压到/usr/local,然后给当前版本目录做一个不带版本号的软链接,便于以后升级路径切换:
tar -zxf mysql-5.6.51-linux-glibc2.12-x86_64.tar.gz -C /usr/local cd /usr/local ln -s mysql-5.6.51-linux-glibc2.12-x86_64 mysql注意,如果/usr/local/mysql已存在,ln 会报错。需要先确认是不是之前残留的目录,如果是,备份后删除再链接。因为我们要把所有命令行工具目录bin和脚本目录support-files统一放在软链接路径下,后续改版本只需要替换软链接,不用动环境变量。
另外解压后建议把安装目录属主修改为 mysql 用户:
chown -R mysql:mysql /usr/local/mysql chown -R mysql:mysql /usr/local/mysql-5.6.51-linux-glibc2.12-x86_644. 初始化数据目录与配置文件 my.cnf
4.1 先规划数据目录位置
默认数据目录是/usr/local/mysql/data,但生产环境我一般都把数据目录单独挂载到数据盘,比如/data/mysql/data。这样做的好处是,系统盘毁了数据还在,而且后期迁移和数据盘扩容更灵活。
创建数据目录并授权:
mkdir -p /data/mysql/data chown -R mysql:mysql /data/mysql4.2 编辑 my.cnf
MySQL 5.6 启动时会按顺序读取/etc/my.cnf、/etc/mysql/my.cnf、/usr/local/mysql/my.cnf这些路径。最常见的是放在/etc/my.cnf。写一个最小可用配置:
[mysqld] user = mysql port = 3306 socket = /tmp/mysql.sock basedir = /usr/local/mysql datadir = /data/mysql/data pid-file = /data/mysql/data/mysql.pid log-error = /var/log/mysql-error.log character-set-server = utf8mb4 collation-server = utf8mb4_general_ci [client] socket = /tmp/mysql.sock default-character-set = utf8mb4这里有几个关键点:
socket定义本地连接的文件路径,客户端如果不指定 host,默认就会用/tmp/mysql.sock。pid-file建议放在数据目录下,启动时脚本能自动找到 pid。log-error一定要显式指定,否则 MySQL 可能把错误日志写到数据目录里,出问题时找起来麻烦。- 5.6 对 utf8mb4 支持相对保守,但如果业务确实需要,可以设置,不过索引长度限制要注意,5.6 版本 utf8mb4 下索引最大长度是 767 字节,遇到过长的 varchar 索引会报错,这是 5.6 的典型限制。
如果你的服务器内存较大,可以在[mysqld]里加上innodb_buffer_pool_size = 2G这类调优参数,但第一次安装建议保持最小配置,等成功跑起来后再调整,避免因参数误配导致启动失败。
4.3 初始化数据目录 mysql_install_db
5.6 的初始化工具是scripts/mysql_install_db,注意千万不能用 5.7 的mysqld --initialize来初始化 5.6,初始化机制完全不同。执行:
/usr/local/mysql/scripts/mysql_install_db --basedir=/usr/local/mysql --datadir=/data/mysql/data --user=mysql由于我的环境变量 PATH 里可能还没有 mysql 命令,这里直接写绝对路径。执行后会在数据目录下生成mysql系统库、ibdata1等文件。输出末尾看到类似 “OK” 的字样就成功了。如果报错,常见的两个原因:
- 缺少依赖库,
mysql_install_db本质是调用mysqld --bootstrap,所以同样需要libaio等依赖。 - 数据目录权限不对,或者目录非空。确保
/data/mysql/data为空且属主是 mysql。
初始化完成后再次确认目录属主:
chown -R mysql:mysql /data/mysql/data4.4 设置 PATH 环境变量
为了让mysql、mysqldump等命令全局可用,可以在/etc/profile末尾加入:
export PATH=/usr/local/mysql/bin:$PATH执行source /etc/profile后,输入mysql --version应该能看到:
mysql Ver 14.14 Distrib 5.6.51, for Linux (x86_64) using EditLine wrapper注意这里显示的是 EditLine wrapper,说明是 Generic 包自带的客户端。如果没有输出,检查环境变量路径和二进制是否存在。
5. 启动 MySQL 服务与配置开机自启
5.1 使用 support-files/mysql.server 脚本启动
Generic 包的support-files目录下自带mysql.server脚本。这个脚本会自动读取/etc/my.cnf里的basedir、datadir、user等参数,调用mysqld_safe拉起服务。可以直接执行:
/usr/local/mysql/support-files/mysql.server start查看启动状态:
/usr/local/mysql/support-files/mysql.server status如果返回:
SUCCESS! MySQL running (pid xxxxx)说明启动成功。如果没成功,立即去看log-error配置的错误日志,比如/var/log/mysql-error.log。常见的启动报错我放在后面专门讲。
5.2 配置系统服务脚本(chkconfig 方式)
CentOS 6 时代常用chkconfig管理服务,CentOS 7/8 则主要用 systemd。为了兼容,可以把mysql.server拷贝到/etc/init.d/下:
cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysql chmod +x /etc/init.d/mysql然后如果是老系统:
chkconfig --add mysql chkconfig mysql on如果是 systemd 系统,我们更推荐写一个标准的 service 单元文件。
5.3 编写 systemd service 单元
新建/etc/systemd/system/mysql.service:
[Unit] Description=MySQL 5.6.51 Server After=network.target [Service] Type=forking User=mysql Group=mysql PIDFile=/data/mysql/data/mysql.pid ExecStart=/usr/local/mysql/support-files/mysql.server start ExecStop=/usr/local/mysql/support-files/mysql.server stop ExecReload=/usr/local/mysql/support-files/mysql.server reload PrivateTmp=true Restart=on-failure LimitNOFILE=65535 [Install] WantedBy=multi-user.target然后执行:
chown mysql:mysql /data/mysql/data systemctl daemon-reload systemctl enable mysql systemctl start mysql注意:PIDFile必须和 my.cnf 里的pid-file保持一致,否则 systemd 认为启动失败。另外PrivateTmp=true会让进程使用独立的 /tmp 命名空间,而 mysql 默认的 socket 是/tmp/mysql.sock,这会导致客户端无法连接!如果遇到 socket 找不到的问题,可以把PrivateTmp=false,或者把 socket 路径改到其他目录,比如/data/mysql/data/mysql.sock。这里建议保留PrivateTmp=true,同时将 my.cnf 中的 socket 改为/data/mysql/data/mysql.sock,这样服务重启时 socket 文件还能随数据目录一起持久化。
5.4 验证服务生命周期
启动后可以用:
mysqladmin -uroot ping如果返回mysqld is alive,说明服务正常。还可以检查端口有没有监听:
ss -lntp | grep 3306然后测试本地连接:
mysql -uroot -S /data/mysql/data/mysql.sock注意这里我用的是-S明确指定 socket 文件,避免客户端默认找/tmp/mysql.sock找不到。如果成功进入 MySQL 命令行,说明整套链路是通的。
6. 初始安全配置:密码、远程访问与生产建议
6.1 初始 root 密码为空怎么办
刚安装完的 5.6 Generic 包,root 用户默认密码是空,并且默认只允许本机通过 socket 连接。所以第一次登录不需要密码:
mysql -uroot -S /data/mysql/data/mysql.sock进入后第一步就是改 root 密码。5.6 的mysql.user表里字段是Password,不支持用ALTER USER ... IDENTIFIED BY(那是 5.7 之后才有的语法)。正确做法:
SET PASSWORD FOR 'root'@'localhost' = PASSWORD('your-strong-password'); FLUSH PRIVILEGES;如果之前用SET PASSWORD FOR 'root'@'127.0.0.1'也一并处理,或者统一修改。注意 5.6 的密码字段长度限制是 41 位,用PASSWORD()函数正好生成 41 位哈希值。
6.2 清理空账号和匿名用户
MySQL 发行版默认可能带有空账号,为了防止任何人无密码连接,执行:
DELETE FROM mysql.user WHERE User=''; DELETE FROM mysql.user WHERE Host='%' AND User='root'; FLUSH PRIVILEGES;mysql.user表里 Host 为%的 root 表示任意主机可连,默认不存在,但这句保险起见执行一下没有坏处。
6.3 创建业务专用账号并授权
生产环境尽量不要让业务代码直接使用 root。创建一个专用账号,例如:
CREATE USER 'app'@'192.168.10.%' IDENTIFIED BY 'app-pass-2026'; GRANT SELECT, INSERT, UPDATE, DELETE ON appdb.* TO 'app'@'192.168.10.%'; FLUSH PRIVILEGES;注意授权主机范围要大于等于实际客户端所在网段,避免全网开放。如果你需要远程管理,另外创建管理账号,并限制来源 IP。对于不使用的远程 root 连接,千万别轻易开起来。
6.4 防火墙与端口放行
如果必须允许远程连接,修改 my.cnf 中的bind-address,默认是127.0.0.1,只能本地。改成服务所在的实际内网 IP,不要改成0.0.0.0,除非你真的要所有网段都能连。然后操作系统防火墙放行 3306:
firewall-cmd --permanent --add-port=3306/tcp firewall-cmd --reload或者使用 iptables:
iptables -A INPUT -p tcp --dport 3306 -j ACCEPT service iptables save除了防火墙,还要注意云厂商的安全组策略,别只放行了系统防火墙而忽略了安全组。我见过不少人折腾半天发现是云安全组没开端口。
6.5 建议执行 mysql_secure_installation
5.6 Generic 包自带mysql_secure_installation脚本,执行后按步骤可以设置 root 密码、删除匿名用户、禁止 remote root 登录、删除 test 数据库。虽然手动操作一遍也能达到同样效果,但脚本交互式引导不容易漏项。执行:
/usr/local/mysql/bin/mysql_secure_installation前提是已经能用 root 连接到 MySQL,脚本每一步会提示输入 root 密码。如果你已经手工安全加固过,脚本会自动判断状态并提示跳过。
7. 安装后的验证与性能初调
7.1 版本和变量检查
进入 MySQL 后,先看版本和一些关键变量是否与预期一致:
SHOW VARIABLES LIKE 'version%'; SHOW VARIABLES LIKE 'innodb_buffer_pool_size'; SHOW VARIABLES LIKE 'character_set_server';5.6.51 的版本号应该显示5.6.51-log或直接5.6.51。字符集确认已经生效为 utf8mb4,否则建表时默认字符集可能不正确,后续改起来很麻烦。
7.2 数据目录文件结构
退出后检查数据目录:
ls -l /data/mysql/data可以看到mysql、performance_schema两个系统目录,以及ibdata1、ib_logfile0、ib_logfile1等文件。5.6 默认每个 redo log 大小是 48M,两个共 96M。日志初始化后不允许随意调整大小,如果后续要调大 redo log,需要先安全停机再参数改、删除旧 redo log 后重启。这个坑很多人遇到,我建议安装初期就把 redo log 调到你未来预期的大小,比如 1G,避免后期折腾。
7.3 检查错误日志
错误日志是 MySQL 排障的第一现场。启动成功后查看/var/log/mysql-error.log,确认里面没有严重警告:
tail -n 50 /var/log/mysql-error.log正常情况下应该只看到 InnoDB 初始化和ready for connections的记录。如果看到[ERROR]开头的行,说明配置有问题,优先解决。
7.4 安全关机和重启测试
MySQL 的关闭方式很有讲究。生产环境不要直接kill -9 mysqld,要用:
mysqladmin -uroot -p shutdown或者系统服务方式:
systemctl stop mysql关闭后再次启动,确保整个生命周期重复可用。我这里遇到过一个坑:直接 kill 进程后,InnoDB 崩溃恢复虽然能启动,但如果有未刷盘的事务,恢复过程会消耗时间,严重时直接卡住。所以无论如何要走正常 shutdown 流程。
7.5 关键性能参数初调
MySQL 5.6 的可调参数非常多,这里只给几个立竿见影的:
innodb_buffer_pool_size:默认 128M,如果内存足够,建议设为物理内存的 50%-70%,这是 InnoDB 性能最核心的参数。max_connections:默认 151,根据应用连接池大小调高,但要控制不要超过系统文件描述符上限。innodb_flush_log_at_trx_commit:默认 1 安全性最高,如果追求性能可设为 2,但最多丢失 1 秒事务。生产环境除非是辅助库,否则不建议调成 0。query_cache_size:5.6 默认没有开启 query cache,你可能会看到have_query_cache=YES,但实际缓存未用。5.6 版本开 query cache 在某些场景能提升性能,但它也是全局锁的隐患,新项目不建议依赖。
调整参数后需要重启生效。改参数前先备份 my.cnf,千万别把所有参数一股脑塞进去,每个参数的变化都可能有连锁反应。
8. 常见问题速查表与避坑技巧
8.1 问题排查表
| 症状 | 常见原因 | 解决方法 |
|---|---|---|
./mysql_install_db: error while loading shared libraries: libaio.so.1 | 缺少 libaio 依赖 | apt install libaio1或yum install libaio |
/usr/local/mysql/bin/mysqld: error while loading shared libraries: libnuma.so.1 | 缺 numactl 库 | yum install -y numactl-libs |
Can't open and lock privilege tables: Table 'mysql.user' doesn't exist | 未执行初始化,或数据目录为空 | 执行scripts/mysql_install_db初始化 |
/etc/my.cnf: [ERROR] Can't find message-file或Can't read from messagefile | basedir 路径不对 | 检查 my.cnf 中 basedir 是否指向/usr/local/mysql |
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock' | socket 路径不一致或 MySQL 未启动 | 用ps -ef看进程,用-S指定实际 socket |
mysql.server start: PID file ... not found | pid-file 路径和脚本读不一致 | 修改 my.cnf,pid-file 必须在 datadir 或其子目录下 |
Starting MySQL... The server quit without updating PID file | 最常见原因是权限、配置、端口冲突 | 查看 log-error 定位具体原因 |
[ERROR] InnoDB: Unable to lock ./ibdata1 | 数据目录被多个进程锁定 | 检查是否有旧 mysqld 进程残留 |
ERROR 1130: Host 'x.x.x.x' is not allowed to connect | 用户主机限制或 root 未授权远程 | 创建专用远程账号或修改 Host |
ERROR 1820: You must set password before using the database | 5.6 初始化默认空密码,连接后必须先改密码 | 执行SET PASSWORD后再操作 |
systemd 启动后mysqladmin ping失败,但进程存在 | PrivateTmp=true导致 socket 路径隔离 | 将 socket 改到非 /tmp 路径,或设置PrivateTmp=false |
| MySQL 启动时内存占用过高,OOM | buffer pool 设置过大 | 调小innodb_buffer_pool_size,重启 |
8.2 我实际踩过的三个典型坑
第一个坑是 socket 路径。第一次用 systemd 启动的时候,我配置了PrivateTmp=true,结果客户端mysql -uroot怎么都连不上,提示找不到/tmp/mysql.sock。查了好久才发现 systemd 给进程开了独立挂载命名空间,进程看到的/tmp不是主机的/tmp。后来我把 socket 定义到数据目录下面,问题解决。以后凡是遇到 socket 诡异消失,先看 systemd 私有 tmp 和 AppArmor/SELinux。
第二个坑是mysql.server start报The server quit without updating PID file。这个提示太泛了,我一开始反复调整 PIDFile 路径都没用,最后打开log-error才看到是Can't create/write to file '/var/log/mysql-error.log',因为/var/log的权限问题导致 mysqld 创建不了日志文件。用 root 创建好日志文件并改变属主后就好了。
touch /var/log/mysql-error.log chown mysql:mysql /var/log/mysql-error.log第三个坑是初始化后 root 密码为空,但我用mysql -uroot直接本地免密登录后执行了SET PASSWORD,结果忘记刷新FLUSH PRIVILEGES。当时测试工具连接时一直报密码错误。后来发现 5.6 修改密码后要刷新授权表,虽然默认缓存机制会在重启后失效,但接手排障的人可等不了你重启,所以务必养成改完权限就执行的习惯。
9. 最后的个人体会和扩展建议
MySQL 5.6.51 这个版本放在今天确实属于“老古董”了,官网维护很早就终止,可为什么还有这么多人要装它?我接触过几个场景:某些银行外部系统认证组件只允许特定版本,某套老业务核心逻辑依赖 5.6 的查询计划和分页实现,还有历史数据归档项目必须按旧库版本做迁移。说白了,装它不是因为喜欢,而是不得不兼容。
在实际维护这类“旧版本新装”的实例时,我给你的建议是:安装流程每一步都留下记录,尤其是 my.cnf 的完整备份和初始化命令。因为旧版本工具链的 bug 和兼容性问题特别多,你今天成功装好了,不代表换台机器还能一键复现。把安装手册固化下来,后面做容灾和扩容会省很多事。
如果你想在这个实例上做更多扩展,可以试试双实例部署:同一个二进制包,通过不同 socket 和端口启动两个独立实例,分别跑不同业务库。Generic 包天然支持这种玩法,只要把数据目录、配置文件、socket 和 pid 都分离即可。我实际操作过,一台 8G 内存的机器可以同时跑两个低负载 5.6 实例,互相不干扰。还有一点,5.6 的备份常用mysqldump,逻辑备份对于小数据量没问题,一旦库过大,建议走 LVM 快照或物理备份方案,比逻辑导出靠谱得多。最后再提醒一句:生产环境第一次跑起来后,务必做一次完整登录测试、授权测试和重启测试,确认没问题后再交给业务接入。数据库装好只是开始,稳定运行才是硬道理。