如果你常年在Linux服务器上折腾,早晚会遇到这样一个需求:某套老系统、某个历史数据迁移方案、或是某台即将退役的设备,必须安装 MySQL 5.6.51 Community Generic 版。明明新版本性能更好、维护更方便,但业务代码里的旧函数、老索引方式、甚至是慢查询日志的格式,全跟这个版本绑定了。这篇教程就是为这个场景准备的——从下载Generic二进制包、初始化数据目录,到配置my.cnf、注册成systemd服务,我按自己实际安装的顺序完整走一遍,适合还没装过、或者装完总在细节上报错的读者。
MySQL 5.6.51是5.6系列的收官版本,之后官方就把主要精力放到5.7和8.0上了。但它至今没有被淘汰,原因很现实:大量线上业务跑在5.6上,动数据库版本意味着业务代码、接口兼容、备份恢复方案全都要跟着验证。所以这不是一个"新潮"教程,而是一个"必要"教程。我把每一步的坑提前标出来,你照着做基本能一次通过。
1. 先搞清楚:为什么用Generic包,而不是yum或源码编译
很多人装MySQL第一反应是yum install mysql-server,或者从发行版软件源里装。这种做法在多数新项目上没问题,但在指定版本5.6.51的场景下行不通——主流Linux发行版的仓库早就把5.6移除了。至于源码编译,代价更高,环境依赖、编译器版本、BOOST库对不上就够你排查半天。Generic二进制包是MySQL官方为Linux提供的预编译产物,不需要本地编译,拿到就能用,这也是"Community Generic"这个名字的含义:社区版、通用平台二进制。
1.1 三种安装方式的利弊对比
先给出我最常对朋友讲的一张对照表,你自己判断该走哪条路:
| 安装方式 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| yum/apt包管理器 | 安装快,自动处理依赖,有系统级服务脚本 | 版本由仓库决定,很难装到5.6.51 | 新项目,不挑版本 |
| 源码编译 | 定制性强,可裁剪功能 | 编译耗时长,依赖众多,出错概率高 | 特殊硬件、特殊编译参数 |
| Generic二进制包 | 官方预编译,版本精确锁定,离线可装,不污染系统包管理 | 需要手动初始化数据和配置服务,对操作顺序有要求 | 指定版本、生产环境复现、离线服务器 |
我选择Generic包的核心理由有两个。一是版本精确可控,不会因为某天yum源更新把MySQL悄悄升上去;二是目录结构独立,装在哪、数据放哪、用哪个配置文件都是我自己的决定,一台机器上甚至能同时保留两个MySQL版本目录用于数据对比迁移。
1.2 Generic包的适用场景和隐藏前提
Generic包不是什么黑魔法,它就是一个用glibc编译好的MySQL程序集合。使用前必须先确认目标机器的glibc版本能兼容,否则启动阶段就会报类似libaio.so.1: cannot open shared object file的错误。
适合用Generic包的场景大致有三类:指定版本的老项目环境搭建、内网离线服务器安装(可以提前把tar包拷进去)、以及需要统一多台服务器MySQL目录结构的标准化部署。但前提是你要对Linux系统的基本操作、权限概念有一定了解——简单说,你会用useradd、chown、tar,就能跟着这篇走完。如果连/etc/my.cnf和/usr/local/mysql的关系都还没概念,建议先简单熟悉一下路径概念再动手。
2. 装之前先看环境:glibc版本、磁盘布局、依赖库
很多教程直接上来就下载解压,最后启动失败才回头查环境,白白浪费半小时。我在新服务器上装MySQL,第一步永远是做环境检查。这不是形式主义,5.6.51的二进制包对系统环境有硬性要求,把它放在最前面做,后面所有步骤都是一路顺风。
2.1 确认Linux发行版与glibc版本
MySQL 5.6.51的Generic包分两种平台:linux-glibc2.12和linux-glibc2.5。前者对系统版本要求更现代,后者通常给老旧的CentOS 5这类系统用。怎么知道自己机器对应哪个?执行一行命令:
ldd --version | head -n 1看输出的版本号,比如ldd (GNU libc) 2.17,就表示glibc 2.17,向下兼容glibc 2.12编译的程序,可以放心使用glibc2.12版本包。如果版本号低于2.12,则需要改用glibc2.5包。顺便看一眼CPU架构:
uname -m输出x86_64就选x86_64包,aarch64则要选ARM版(官方提供,但下载页要仔细找)。我在某项目上犯过这个错,拿着x86_64的tar包往ARM机器上解压,启动时直接报Exec format error,白折腾一场。
2.2 让安装目录和数据目录分离
这是很多人忽略的问题。MySQL的程序文件、数据文件、日志文件如果全部堆在一个磁盘分区,一旦数据量上涨把分区写满,整个数据库写操作直接hang住。建议至少分成两个路径:
- 安装目录:
/usr/local/mysql(放二进制程序) - 数据目录:
/data/mysql/data(放ibdata、ib_logfile和库表目录)
数据目录放在独立磁盘或数据盘挂载点,即使系统盘损坏,数据文件也能及时抢救。这个习惯从5.6一直沿用到8.0都不过时。如果你没有独立数据盘,至少要把目录单独建好、权限分配清楚,方便后续迁移。
2.3 预装基础依赖库
5.6.x初始化数据目录时要用到perl脚本,运行时则依赖几个系统库。我在干净的系统上装5.6.51,一般先执行:
yum install -y libaio numactl perl ncurses-compat-libs不同的包管理器命令不同,但核心就是libaio和perl这两样。libaio是MySQL使用异步I/O的必要库,缺了它启动日志会报libaio.so.1找不到。numactl在NUMA架构的多路服务器上也建议装上,可以防止内存分配异常。至于ncurses-compat-libs,主要是mysql客户端在部分新版系统上会用到旧版终端库,装上有备无患。
提示:在Ubuntu/Debian系统上,对应命令是
apt-get install -y libaio1 libnuma1 perl,包名细节略有不同,但依赖项本质一样。
3. 下载、校验与解压:别一股脑wget完了就解压
下载本身不难,难的是搞清楚该下哪个文件、下完之后怎么确认文件没损坏。MySQL官方下载页面把5.6.51放进了Archive(归档)区域,因为5.6已经停止维护,不会出现在首页的主推列表里。找的时候注意认准包名,不要误拿5.7或8.0的包。
3.1 认准包名:glibc2.12还是glibc2.17
在归档页面里,文件名一般是mysql-5.6.51-linux-glibc2.12-x86_64.tar.gz。别奇怪为什么glibc 2.17的机器也能用这个包——因为2.12是编译时的最低要求,更高版本自然向下兼容。所以选glibc2.12通常是最稳妥的选择,兼容性最广。如果你是在特别老旧的系统上,才需要找glibc2.5的变体。
下载命令示例:
wget https://cdn.mysql.com/archives/mysql-5.6/mysql-5.6.51-linux-glibc2.12-x86_64.tar.gz如果公司内网访问外网有限制,就在能联网的机器上下载,再通过内网传到目标服务器。这一步没什么技巧,但要注意传输完成后务必再做一次校验。
3.2 md5校验与tar解压
网络传输过程是有可能损坏文件的,直接解压后安装,你根本不知道是文件问题还是步骤问题。官方下载页每个包都提供了MD5值,先校验再解压:
md5sum mysql-5.6.51-linux-glibc2.12-x86_64.tar.gz比对输出的MD5和官网页面上显示的值是否一致。不一致就重新下载,别心存侥幸——解压出来的二进制可能缺少关键符号,启动时各种诡异报错,排查起来比重新下载痛苦十倍。
确认无误后解压:
tar -zxvf mysql-5.6.51-linux-glibc2.12-x86_64.tar.gz -C /usr/local/解压完成后,/usr/local/下会多出一个mysql-5.6.51-linux-glibc2.12-x86_64目录。
3.3 用软链接管理MySQL版本目录
直接拿这串长目录当安装路径,配置文件和启动脚本里到处都要改,非常难受。我习惯创建软链接:
ln -s /usr/local/mysql-5.6.51-linux-glibc2.12-x86_64 /usr/local/mysql这样做的好处是,后续所有配置都可以用/usr/local/mysql作为basedir。如果哪天要升级到5.6的补丁版,只需要解压新目录、把软链接指过去,my.cnf不用大改。这是一种很实用的版本管理思维,后面配置、启动、升级都能省下不少事。
4. 初始化数据目录:5.6版本独有的启动前准备
解压完的MySQL还不能直接启动,必须先把数据目录初始化好。这一步在5.6.51里和你熟悉的5.7、8.0完全不一样。5.7之后用mysqld --initialize,5.6.51用的还是老工具mysql_install_db,别搞混。
4.1 创建mysql用户与数据目录
我强调过多次,MySQL不允许用root身份直接运行,这一点官方有明确要求。创建一个专用系统用户:
useradd -r -s /bin/false mysql-s /bin/false表示该用户不能登录shell,只用来运行mysqld进程,安全系数更高。然后创建数据目录结构:
mkdir -p /data/mysql/data mkdir -p /data/mysql/logs mkdir -p /data/mysql/tmp chown -R mysql:mysql /data/mysql chmod -R 750 /data/mysql这里把logs和tmp也单独建好。很多人只建data目录,结果后面把pid文件、socket文件放哪都靠猜,日志乱成一堆。提前规划好处是my.cnf里每一项路径都有对应的目录,未来排查问题非常快。
4.2 mysql_install_db初始化(与5.7的区别)
初始化命令如下:
/usr/local/mysql/scripts/mysql_install_db \ --basedir=/usr/local/mysql \ --datadir=/data/mysql/data \ --user=mysql执行成功的标志是命令没有报错,最后会生成/data/mysql/data/mysql等系统库目录。这一步实际是在创建mysql、performance_schema等基础库,并生成初始权限表。
如果提示perl相关错误,说明你的系统缺少perl模块,回头装一下perl依赖再执行。如果是libaio相关错误,就说明2.3的依赖没装全。初始化命令本身不带随机root密码——这是5.6和5.7的重大区别。5.7初始化和首次启动后root会生成临时密码放到日志里,5.6则是root默认无密码,需要你启动后手动设置。
4.3 初始化完成后先看一眼目录内容
初始化完成后别急着启动,先检查:
ls -l /data/mysql/data/正常会看到ibdata1、ib_logfile0、ib_logfile1以及mysql目录。如果这几个文件都在,说明初始化没白做。顺手再看一眼目录属主:
ls -ld /data/mysql/data/确保属主是mysql:mysql。权限不对的话,启动时mysqld会报Permission denied,这种问题经常出现在你看似"照做"的步骤里——某个mkdir或chown被跳过,后续所有操作全卡住。
5. my.cnf配置清单:先跑起来,再谈调优
很多教程喜欢一上来就堆一大堆优化参数,其实对5.6.51来说,最重要的是先有一个最小可用配置,确保能启动、能连接、能写数据,等业务稳定后再根据监控逐步调整。我下面给的配置可以直接用于生产环境起步,每项参数都会说明理由。
5.1 最小可用配置与关键参数解释
创建/etc/my.cnf:
[mysqld] basedir=/usr/local/mysql datadir=/data/mysql/data socket=/tmp/mysql.sock pid-file=/data/mysql/tmp/mysqld.pid log-error=/data/mysql/logs/mysql.err port=3306 user=mysql skip-external-locking character-set-server=utf8mb4 collation-server=utf8mb4_general_ci default-storage-engine=InnoDB innodb_buffer_pool_size=1G max_connections=500逐条说下关键点。basedir和datadir必须和实际目录完全一致,否则检查路径的时间比安装时间还长。pid-file指定到/data/mysql/tmp/下面,确保该目录属主是mysql,否则mysqld启动时无法创建pid文件。user=mysql表示启动时不切换账号,直接以mysql用户运行,避免后续因su权限导致的日志混乱。
skip-external-locking是5.6时代的经典参数,它的作用是跳过外部锁系统,避免多实例环境下的锁冲突。单机单实例场景下加上它没有坏处。innodb_buffer_pool_size不要照抄我的1G值,需要按实际内存来定,后面我会专门说计算方法。
5.2 字符集、时区与默认引擎
character-set-server=utf8mb4是必选项。老项目如果历史数据用的是utf8,在5.6.51里虽然也能存中文,但遇到生僻字、emoji这种四字节字符就会报错。utf8mb4是utf8的超集,兼容性最好,新库统一用它没问题。注意,这里有个隐藏坑:5.6.51的连接层字符集默认是utf8,即使服务器配了utf8mb4,如果程序连接串里没指定characterEncoding=utf8mb4,写入中文也可能乱码。建议在my.cnf里加一行:
[client] default-character-set=utf8mb4这能让命令行客户端默认使用同样字符集,减少排查"数据库里存了乱码"这种问题的时间。
时区方面,可以在[mysqld]段加一行:
default-time-zone='+08:00'注意,如果你所在时区不是东八区,把这个值改成对应的时区偏移。这个参数直接影响NOW()函数的结果,老代码尤其是报表逻辑,对时间计算很敏感,启动前就定好,避免后续靠SET GLOBAL time_zone临时救急。
5.3 日志设置:错误日志、慢查询日志
错误日志用log-error指定路径,我之前遇到启动失败,第一件事就是打开/data/mysql/logs/mysql.err看最后二十行。日志路径配错或没配,启动期的问题排查会变成大海捞针。慢查询日志在5.6.51里默认关闭,需要手动开启:
slow_query_log=1 slow_query_log_file=/data/mysql/logs/slow.log long_query_time=2long_query_time=2表示超过2秒的查询会记录日志。老业务上线跑了一两周后,慢日志能直观告诉你哪些SQL需要优化,这是从"能用"迈向"好用"的重要观察点。
6. 启动、安全初始化与连接验证
配置写完了,终于到了启动环节。这一步会有两个分支选择,不同方式对systemd的管理方式影响很大,我建议一步到位用mysqld直接启动,把进程交给systemd来管。
6.1 两种启动方式:mysqld_safe与mysqld直接启动
手工测试阶段,很多人习惯先跑一次:
/usr/local/mysql/bin/mysqld_safe --defaults-file=/etc/my.cnf &用mysqld_safe启动的好处是,它会自动重启意外退出的mysqld子进程,还能把错误日志重定向到指定文件。但它是一个包装脚本,进程关系比较绕,后续如果配systemd服务,常常出现systemd认为服务已停止、实际mysqld还在跑的状况。
我更推荐在测试时直接用:
/usr/local/mysql/bin/mysqld --defaults-file=/etc/my.cnf --user=mysql &然后用端口或进程检查是否起来:
netstat -tlnp | grep 3306看到3306端口LISTEN,说明启动成功。如果没起来,立即看/data/mysql/logs/mysql.err。这个文件记录了mysqld启动过程中几乎所有的有效线索,比你去猜配置要直接得多。
6.2 root密码设置与清理匿名账户
5.6.51刚初始化完,root默认无密码,只能本机连接。首先用Socket方式登进去:
/usr/local/mysql/bin/mysql -uroot -S /tmp/mysql.sock登上之后第一件事就是设置root密码。我不建议直接跑一条ALTER USER,而是用官方提供的安全初始化脚本:
/usr/local/mysql/bin/mysql_secure_installation这个脚本会以问答方式引导你:设置root密码、删除匿名用户、禁止root远程登录、删除test数据库。每一步都按推荐选项执行即可。尤其注意"Remove anonymous users"和"Disallow root login remotely"这两项,生产环境必须选择。
手动执行等价SQL也可以,但脚本更省事且不容易漏掉某一项。如果你所在环境不允许交互式终端,可以提前写好SQL文件批量执行。核心就是两条:
DELETE FROM mysql.user WHERE User=''; UPDATE mysql.user SET Password=PASSWORD('你的强密码') WHERE User='root'; FLUSH PRIVILEGES;6.3 通过客户端连通性验证
安全初始化完成后,重新登录一次验证:
/usr/local/mysql/bin/mysql -uroot -p -e "SELECT VERSION();"输入密码,出现5.6.51-log(或类似字样)说明连接正常。顺手建一个测试库试试写权限:
CREATE DATABASE testdb DEFAULT CHARACTER SET utf8mb4; USE testdb; CREATE TABLE t (id INT PRIMARY KEY, name VARCHAR(50)); INSERT INTO t VALUES (1, '测试'); SELECT * FROM t;能执行完一轮增删改查,基本可以确认服务健康。
7. 注册为systemd服务,解决开机自启
手动启动只能解决眼前问题,服务器一重启,MySQL不会自动起来,还得人工去敲命令,这在生产环境是不可接受的。把MySQL注册为systemd服务,是我每次安装完必须做的一件事。
7.1 自定义Unit文件
在/etc/systemd/system/mysql-5.6.service新建一个unit文件:
[Unit] Description=MySQL 5.6.51 Community Server After=network.target [Service] Type=simple User=mysql Group=mysql ExecStart=/usr/local/mysql/bin/mysqld --defaults-file=/etc/my.cnf TimeoutSec=300 Restart=on-failure [Install] WantedBy=multi-user.target然后逐行解释几个关键点。Type=simple表示ExecStart直接启动mysqld进程,systemd会把这个进程当作服务主进程来管理,停止服务时直接向它发送SIGTERM,MySQL会自己处理优雅关闭。最忌讳的是在服务里又套一层mysqld_safe,因为mysqld_safe自己会拉起子进程并驻留前台,systemd很难准确掌握服务状态,Stop时经常出现"服务已停但端口还开着"的怪事。
启用服务并设置开机自启:
systemctl daemon-reload systemctl enable mysql-5.6 systemctl start mysql-5.6 systemctl status mysql-5.6看到active (running)就说明服务状态正常。以后开机自动启动,重启服务器也不用担心。
7.2 启动失败的常见排查路径
如果systemctl start没有起来,我的排查顺序是固定的:
第一步看unit状态:
systemctl status mysql-5.6第二步看错误日志:
tail -n 50 /data/mysql/logs/mysql.err第三步确认数据目录和日志目录权限:
ls -ld /data/mysql /data/mysql/data /data/mysql/logs90%的问题最后都落在"路径写错"和"目录权限不对"两个原因上。比如datadir配置成/data/mysql/data,但实际路径是/data/mysql/data/——这种末尾斜杠差异在大多数情况下没事,但某些5.6版本的路径拼接逻辑会很敏感,建议统一不加斜杠。
8. 5.6.51特有的坑位清单(新手最容易翻车)
写到这,核心安装流程已经全部跑通。如果你一次成功,恭喜;如果卡在哪一步,大概率是下面这些5.6.51特有细节没注意到。我专门把它拎出来再啰嗦几句,避免你在网上搜半天不知所措。
8.1 认证方式与老客户端兼容
5.6.51默认使用mysql_native_password认证,这种认证方式在5.7到8.0时代逐渐被替换,但5.6和5.7的默认行为一样,老版本PHP、Python连接库都能顺利连通。这反而是5.6.51的一个"优势"——在兼容老项目时,它的认证协议阻力最小。如果你后面自己手动改过用户认证插件,比如为了老客户端用了mysql_old_password,要注意5.6.51里这种插件默认不启用,需要运行时加载,改完后务必备份mysql.user表再操作。
8.2 区分初始化和启动的日志位置
我在实际排查中反复强调,初始化阶段的报错不一定出现在mysql.err里,因为此时mysqld还没完全起来。mysql_install_db的报错会直接输出到终端,一般关键字有FATAL ERROR、Permission denied、Can't find file。但启动阶段的问题就要看/data/mysql/logs/mysql.err了。养成"初始化看终端、启动看日志"的习惯,能节省大量排查时间。
8.3 从5.6.51升级之前要想清楚三件事
5.6.51既然是老版本,迟早要面对升级。基于我的经验,升级前至少要确认三件事:一是mysql_upgrade的版本匹配,5.6的数据目录结构到了5.7需要额外步骤迁移,不能直接换二进制包就完事;二是字符集编码,老库如果一直是utf8,升级前要把数据统一验证一遍,避免四字节字符在升级过程中报错;三是备份策略要提前演练,mysqldump全量导出导入是5.6升级最稳妥的路线,别到了上线当天才第一次测试备份恢复。
备份这条多说一句,5.6.51的mysqldump默认只做逻辑备份,数据量大时会很慢,但对绝大多数中小业务足够。有条件的话,可以加物理备份工具做全量+增量配合,恢复速度会快很多。不过不管哪种方案,第一次用之前必须做一次完整的恢复演练,我见过太多"备份能生产但恢复时才发现少了个参数"的情况。
用mysqldump做例行备份的参考命令:
/usr/local/mysql/bin/mysqldump \ -uroot -p \ --single-transaction \ --routines \ --triggers \ --databases mydb \ > /backup/mydb_$(date +%F).sql--single-transaction参数对InnoDB表非常关键,它能在不锁表的情况下拿到一致性快照,适合5.6.51这种以InnoDB为主的实例。
在我实际经手过的几套老系统迁移中,装5.6.51的服务器到最后都不是"装不上"的问题,而是"装完不好好收尾"的问题。数据目录权限没调对、systemd服务没注册、日志路径没规划,这些才是让一台MySQL慢慢变脆弱的真正原因。如果你现在正处于安装后的调试期,我的建议是先别看任何性能优化文章,把本文第七章的systemd服务配好,再把备份命令加进crontab,然后才去考虑buffer pool调多大、慢查询阈值设多少。数据库这东西,跑起来容易,跑得稳才见功夫。