自己折腾服务器和开发环境这些年,Ubuntu和MySQL这对组合算是绕不开的老搭档了。无论你是刚接触Linux的学生,还是要在生产环境部署JavaWeb项目的开发者,大概率都要在Ubuntu上跟MySQL打交道。网上关于MySQL安装的教程不少,但要么写得云山雾罩,要么直接照搬CentOS的rpm思路,在Ubuntu上踩得头破血流。
我最早在Ubuntu 16.04上装MySQL 5.7,后来一路升级到20.04、22.04,中间踩过SSL连接报错、root密码忘记、环境变量搞乱导致命令找不到这些坑。这篇文章就把我在Ubuntu下安装、配置、排查MySQL的完整经验整理出来,从装前准备、核心安装步骤、日常运维操作,到高频问题排查,一条龙讲透。适合刚接触Linux的初学者,也适合被MySQL折磨过想彻底搞明白的老手。
1. 内容整体设计与思路拆解
1.1 为什么选Ubuntu而不是其他发行版
Linux发行版几十上百个,但Ubuntu在开发者群体里的占比一直很稳。原因不复杂:社区活跃、资料多、软件源覆盖全。遇到任何问题,基本Google一搜就有前人踩坑的答案。
对比一下几个主流发行版,你就能明白为什么大家默认选Ubuntu:
| 发行版 | 包管理 | MySQL安装方式 | 上手难度 |
|---|---|---|---|
| Ubuntu/Debian | apt/dpkg | 官方源直接装,依赖自动解决 | 低 |
| CentOS/RHEL | yum/dnf | 默认源是老版本,需额外配源或用rpm包 | 中偏高 |
| Arch Linux | pacman | 滚动更新,版本最激进 | 偏高 |
CentOS系装MySQL最麻烦的一点是源里只有老版本MariaDB,要装真正的MySQL还得去下载rpm包或者用官方仓库,而rpm安装时如果依赖没准备好,那才是真正的噩梦。Ubuntu这边就简单很多,apt直接搞定依赖,一条命令装完,这也是我在Ubuntu上装MySQL最省心的地方。
1.2 用apt装还是用源码编译装
在Ubuntu下装MySQL,主流的路径有三条:
- apt install直接装:最简单粗暴,官网源或系统源里的预编译包,安装、升级、卸载都交给包管理器,对大多数人是首选。
- 下载官网tar包手动部署:适合需要特定版本(比如老项目指定MySQL 5.7)、或者想自定义安装路径的场景。但依赖问题全得自己解决,配置环境变量、初始化数据目录、配systemd服务,一套流程走完挺折腾。
- 源码编译安装:基本只有二次开发或者极其特殊的需求才会这么干,编译一次大几十分钟,对普通业务开发没多大意义。
我最推荐的是第一种。MySQL 8.0官方早已在Ubuntu源里准备好了,除非你项目里明确锁死了某个小版本,否则没必要自己从官网下tar包。二进制版本和apt版本在性能上没有任何差别,但apt版本能帮你自动管理依赖和服务脚本,省下大把时间。
有人可能担心apt源里的版本太老。这个顾虑在MySQL 8.0时代基本上不存在了,Ubuntu 20.04及之后的源里MySQL 8.0版本会跟着安全更新补丁走。真到了哪天你需要某个特定小版本,再考虑下载官方tar包也不迟。
1.3 到底该装MySQL还是MariaDB
刚接触的人可能被搞懵:为什么Ubuntu上装MySQL,有时候装出来却是MariaDB?
这里面的历史原因是2010年后MySQL被Oracle收购,MySQL的创始人Monty创建了MariaDB分支,并且Debian/Ubuntu的某些版本里默认的mysql-server包被替换为MariaDB的兼容包。如果你在Ubuntu 18.04上直接执行apt install mysql-server,装出来的确实是MariaDB,容易让人摸不着头脑。
但在Ubuntu 20.04及以后,mysql-server包恢复为真正的MySQL 8.0。所以版本不同,行为差别很大。如果你在旧版Ubuntu上,或者对装出来的版本心存疑虑,最快的确认方式就是登进去看:
mysql --version我见过不少人在老教程引导下,在Ubuntu上装完MySQL拿root登录,密码死活不对,最后才发现自己其实是装了个MariaDB,很多命令和参数都不一样。所以动手之前先搞清楚版本,免得白忙活。
2. 核心细节解析与实操要点
2.1 在Ubuntu 22.04上安装MySQL 8.0的完整步骤
先交代一下环境,我以下操作基于Ubuntu 22.04 LTS(虽然20.04和24.04操作几乎一致),MySQL 8.0。如果是全新系统,第一步永远是更新软件源:
sudo apt update && sudo apt upgrade -y这个步骤很多人喜欢跳过,觉得反正装软件时apt会自动处理依赖。但我的建议是从一开始就做,原因有两个:一是系统里如果残留有老版本MySQL相关组件,不更新索引直接装容易撞上依赖冲突;二是新系统里有些基础依赖(如libaio1)可能没装全,更新一遍能省去后面的麻烦。
接下来安装MySQL服务端,一条命令搞定:
sudo apt install -y mysql-server注意,这里装的是服务端,包含了mysqld进程、数据目录初始化、systemd服务脚本。如果你只需要客户端(比如只连远程数据库),装mysql-client就够了,但大多数情况下我们两个都要,直接装server会连带把client也装上。
安装过程在Ubuntu 22.04上会自动完成数据目录初始化。这里有个和旧版本很大的不同:MySQL 8.0初始安装后,root账号的认证方式默认是auth_socket,也就是说只要你用系统的root用户或者sudo权限,就能直接登进MySQL,不需要密码。
验证一下是否安装成功:
systemctl status mysql如果看到active (running),说明服务已经起来了。然后用下面的命令登录:
sudo mysql能进入mysql>提示符,就代表安装成功了。
2.2 初始安全配置与root密码设置
很多新手卡在这一步:明明装好了,但不知道root密码是啥,用密码登录总是失败。
前面说了,MySQL 8.0默认root走的是auth_socket插件,所以你需要先用sudo mysql进去,自己设置密码:
ALTER USER 'root'@'localhost' IDENTIFIED WITH caching_sha2_password BY '你的密码'; FLUSH PRIVILEGES;执行完这步,root密码就生效了。把caching_sha2_password改成mysql_native_password也是常见的操作,因为一些老版本客户端(比如老Navicat)不支持caching_sha2_password。不过MySQL 8.0官方推荐用caching_sha2_password,在安全性和性能上都更好。如果你用的客户端足够新,建议保持默认,不需要改。
设置好密码后,跑一下官方自带的安全加固脚本:
sudo mysql_secure_installation这个脚本会问你几个问题:是否设置密码强度、是否删除匿名用户、是否禁止root远程登录、是否删除test数据库。除非你明确知道自己在干什么,否则一律Y。特别是“禁止root远程登录”这一项,很多人为了方便想选N,但安全角度强烈建议Y。远程连接请单独创建业务账号,不要让root暴露在网络上。
操作完以后,可以顺手验证一下密码登录是否正常:
mysql -u root -p输入刚才设置的密码,能进就说明一切OK。
2.3 字符集配置:为什么你总是看到乱码
中文乱码估计是MySQL使用中最高频的痛点之一。在MySQL 8.0里,默认字符集是utf8mb4,这对中文用户已经很友好了。但如果你是从老项目数据库迁移过来的,或者建表时没指定字符集,还是会遇到乱码问题。
先查看当前的字符集配置:
SHOW VARIABLES LIKE 'character_set%';最理想的情况是这样:
+--------------------------+-------------------------------------+ | Variable_name | Value | +--------------------------+-------------------------------------+ | character_set_client | utf8mb4 | | character_set_connection | utf8mb4 | | character_set_database | utf8mb4 | | character_set_results | utf8mb4 | | character_set_server | utf8mb4 | +--------------------------+-------------------------------------+如果不是这样,可以修改配置文件。编辑MySQL配置文件:
sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf在[mysqld]段下添加:
[mysqld] character-set-server = utf8mb4 collation-server = utf8mb4_unicode_ci然后重启服务:
sudo systemctl restart mysql重新登录查看,应该就是utf8mb4全家桶了。
这里我要多说两句。老教程里经常会让人改成utf8,但utf8在MySQL里是utf8mb3的别名,只能存基本平面字符,像emoji、生僻汉字这些根本存不进去。utf8mb4才是真正的四字节UTF-8,能覆盖所有Unicode字符。从2010年的MySQL 5.5.3开始就有这个选项了,但直到8.0它才成为默认值。新库一律用utf8mb4,别犹豫。
2.4 防火墙与远程连接授权:Navicat为什么连不上
装好MySQL后大部分人都会遇到一个问题:本地登录没问题,用Navicat或者别的客户端从别的主机连,怎么都连不上。原因就两个:防火墙没放行3306端口,或者MySQL的用户权限只允许localhost访问。
先说防火墙。Ubuntu默认用的是ufw,查看3306端口是否放行:
sudo ufw status如果状态是inactive,说明防火墙没开,那问题就不在这。如果开着,需要放行MySQL端口:
sudo ufw allow 3306/tcp再说MySQL授权。MySQL用户是按“用户名+主机”来区分的,'root'@'localhost'只允许本机连,远程主机过来会被拒绝。正确的做法是创建一个专门用于远程连接的用户:
CREATE USER 'app_user'@'%' IDENTIFIED BY '强密码'; GRANT ALL PRIVILEGES ON *.* TO 'app_user'@'%'; FLUSH PRIVILEGES;这里的%表示任意主机,也可以指定具体IP,比如'app_user'@'192.168.1.100',更安全。
创建用户时还有个小细节。MySQL 8.0默认的密码加密方式是caching_sha2_password,如果你的Navicat版本比较老(8.0以下),可能不认识这个加密方式,连接时报Authentication plugin 'caching_sha2_password' cannot be loaded。解决办法有两个:一是升级Navicat到16以上,二是把用户的认证方式改成老式的:
ALTER USER 'app_user'@'%' IDENTIFIED WITH mysql_native_password BY '强密码';不过还是要强调一下,mysql_native_password属于历史遗留方案,新项目尽量用新客户端+caching_sha2_password。安全性和性能上,新的加密插件都要好很多。
3. 实操过程与核心环节实现
3.1 忘了root密码怎么重置(常见场景复盘)
这个场景太经典了。我接手过几次同事的开发机,MySQL的root密码被前一个人改过,谁都不知道是什么,项目又急着要跑起来。网上给的通用方案就是skip-grant-tables,但在MySQL 8.0下操作细节跟老版本有出入。
先停掉MySQL服务:
sudo systemctl stop mysql然后以跳过权限表的方式启动:
sudo mysqld_safe --skip-grant-tables &这里有个要注意的点:mysqld_safe启动时会以后台方式运行,但如果你的系统里mysqld没能正常进入skip-grant-tables模式,后面的操作会白做。所以启动后稍等两秒,确认进程真的存活了再继续:
ps -ef | grep mysqld看到mysqld_safe和mysqld进程都在,再登录进MySQL:
mysql -u root注意,这种模式下不需要密码就能登录。但坑点来了:在skip-grant-tables状态下,你直接执行ALTER USER改密码,可能会报错,因为权限系统压根没加载。更稳妥的做法是先刷新权限表,让当前会话获得正常权限:
FLUSH PRIVILEGES;然后再改密码:
ALTER USER 'root'@'localhost' IDENTIFIED BY '新密码';改完退出,杀掉mysqld进程,再正常启动:
sudo pkill mysqld sudo systemctl start mysql用新密码登录验证:
mysql -u root -p这个流程我在MySQL 8.0.28和8.0.32上都验证过,没问题。核心就是在改密码前一定要执行FLUSH PRIVILEGES,不然会撞上权限表未加载的各种诡异报错。
3.2 环境变量配置错误导致的mysql命令找不到
当你用源码包方式安装MySQL时,会遇到一个很典型的问题:明明装好了,mysql这个命令却提示command not found。这是因为MySQL的可执行文件目录(比如/usr/local/mysql/bin)没有被加进PATH环境变量。
我见过有人去修改/etc/environment文件,结果格式写错,导致整个系统登录后所有命令都找不到,网卡、蓝牙全出问题。这里提供一个安全且永久的配置方法。
先确认MySQL的bin目录在哪里。如果是apt安装的,默认在/usr/bin,一般不需要配。如果是源码安装或tar包部署,路径可能在/usr/local/mysql/bin。确认路径后,编辑~/.bashrc:
echo 'export PATH=$PATH:/usr/local/mysql/bin' >> ~/.bashrc source ~/.bashrc这种配法只对当前用户生效,不会影响系统其他用户或服务,改坏了也只会让当前用户的shell出问题,重启终端就好。为什么我不推荐直接改/etc/environment?因为那个文件是系统级的,里面格式要求非常严格,比如不能带export关键字、每行不要有多余空格。一旦写错,图形界面都没法正常登录,排查起来极其痛苦。
配置完成后,还需要让MySQL的库文件能被动态链接器找到,否则运行mysql时报错libmysqlclient.so: cannot open shared object file。编辑/etc/ld.so.conf.d/mysql.conf:
echo '/usr/local/mysql/lib' | sudo tee /etc/ld.so.conf.d/mysql.conf sudo ldconfig这步很多人会漏掉,等报错了才一头雾水。提前做好,后面少绕弯。
3.3 常用运维命令与SQL实战
装好MySQL只是开始,日常用得最多的操作还得熟练。我整理一下自己在生产环境天天用、新手却容易搞混的几个命令。
服务管理:
systemctl status mysql # 查看状态 systemctl restart mysql # 重启 systemctl enable mysql # 开机自启查看数据库和表:
SHOW DATABASES; USE 数据库名; SHOW TABLES; DESC 表名;这三个命令是入门必会的,SHOW系列在排查问题时候特别有用,比如:
SHOW PROCESSLIST;能看当前所有连接在干什么,数据库卡住时第一反应就是执行它,看看有没有长时间Sleep或Locked的会话。
字符串转日期:这个是高频率操作,强烈建议记牢。业务表里经常有用户传过来的"2024-08-15 14:30:00"这种字符串,需要转成DATE或DATETIME类型再做比较。MySQL提供了STR_TO_DATE函数:
SELECT STR_TO_DATE('2024-08-15 14:30:00', '%Y-%m-%d %H:%i:%s');反过来,把日期格式化输出用DATE_FORMAT:
SELECT DATE_FORMAT(NOW(), '%Y年%m月%d日');设置默认值为0:这个也是高频需求。MySQL 8.0里如果某字段需要默认值0,建表时可以直接写:
CREATE TABLE example ( id INT PRIMARY KEY AUTO_INCREMENT, status TINYINT NOT NULL DEFAULT 0 );如果你用的是老版本MySQL(5.7之前),某些字段类型(比如TEXT、BLOB)不允许设置默认值,这是一个历史限制,8.0时代已经放宽了,但建表时养成指定DEFAULT的习惯依然是好习惯。
存储过程:JavaWeb项目里偶尔会用到存储过程来封装复杂查询逻辑。一个最简单的示例:
DELIMITER // CREATE PROCEDURE get_user_count() BEGIN SELECT COUNT(*) FROM users; END // DELIMITER ; CALL get_user_count();注意DELIMITER的使用,因为默认分号会让MySQL在遇到分号时就结束输入,用DELIMITER //先换掉结束符才能完整输入整个存储过程。这个细节写SQL脚本时特别容易踩坑。
4. 常见问题与排查技巧实录
4.1 SSL连接错误:报错信息看不懂怎么办
MySQL 8.0默认开启了SSL连接,这本身是好事,但有时候会带来奇奇怪怪的问题。最常见的一个报错是:
ERROR 2026 (HY000): SSL connection error: protocol version mismatch或者客户端连接时报SSL connection error: error:1425F102:SSL routines:ssl_choose_client_version:unsupported protocol。
出现这个问题的原因通常是客户端支持的SSL/TLS协议版本太旧,而MySQL 8.0要求的最低版本是TLS 1.2。老客户端(尤其是系统自带的旧版libmysqlclient,或者老Navicat)只支持TLS 1.0/1.1,两边匹配不上就报错。
解决办法有三种,按推荐程度排序:
第一种,升级客户端:把Navicat、mysql-connector-java这些更新到支持TLS 1.2的版本。这是最一劳永逸的方案。
第二种,临时指定--skip-ssl:只是紧急排查用,不推荐生产环境这么干:
mysql -u root -p --skip-ssl第三种,调整MySQL服务端的ssl配置:如果确实有老客户端必须连,可以在配置里放宽TLS版本要求:
[mysqld] tls_version = TLSv1.2,TLSv1.3注意MySQL 8.0.16之后的版本,tls_version参数只接受TLSv1.2和TLSv1.3,老版本参数会自动忽略。别想着把TLSv1和TLSv1.1加回去,8.0已经不支持了。如果只是测试环境,也可以直接禁用SSL:
[mysqld] skip_ssl但强烈不建议在生产环境这样干,数据在传输过程中就是裸奔的。安全性和便利性的权衡,最终还是要自己拿捏。
4.2 安装过程中出现错误代码0x80070424的含义
这个报错很有意思,我一开始是在Windows上装Ubuntu子系统时遇到的,但接着在Linux环境配置MySQL时,也有不少朋友遇到类似的报错困扰。
错误代码: 0x80070424是Windows系统服务的错误,意思是“指定的服务未安装或已禁用”。场景通常是:你在Windows上通过WSL或者虚拟机操作Ubuntu,想在Windows服务管理器里启动某个依赖服务,结果服务本身不存在。要注意的是,这不属于Linux环境的问题,纯粹是Windows层的服务状态不对。
在Ubuntu虚拟机里跑MySQL时,我更常遇到的是另一个类似的坑:启动虚拟机后MySQL服务没有自动起来,连接时报Can't connect to local MySQL server through socket。排查步骤:
systemctl status mysql如果不是active状态,直接启动:
systemctl start mysql如果启动失败,看错误日志:
sudo tail -100 /var/log/mysql/error.log日志里最关键的信息是最后几行。常见的启动失败原因包括:数据目录权限不对、磁盘空间满、配置文件的某个参数写错。有一次我在配置里手滑加了一个不存在的变量,MySQL直接拒绝启动,日志里报unknown variable,改掉就好了。这些细节,光看报错信息可能一头雾水,日志会直接告诉你答案。
4.3 忘记Ubuntu系统登录密码和MySQL密码的组合排查
作为开发机,常常是整个系统密码和MySQL密码一起忘掉。如果你遇到的是这种情况,处理顺序要理清:先搞定系统登录密码,再处理MySQL密码。
Ubuntu系统密码重置有一个固定的方法:开机时在GRUB菜单选择Advanced options for Ubuntu,选recovery mode,然后在Recovery Menu里选择root。进入root shell后,用passwd 用户名重置密码。
这套操作本质上就是通过单用户模式绕过登录认证。平时用得少,真到用的时候救命的,建议收藏一下。
MySQL密码的忘记处理我在前面3.1已经写过了,这里就不再重复。需要强调的是,以上所有重置操作完成后,务必确认一件事:检查有没有开启自动更新,以及MySQL的binlog是否正常记录。因为密码遗忘往往发生在项目濒临上线或者赶工期的节点,数据安全反而比密码本身更重要。
4.4 高频问题速查表
有些问题遇到太多次了,我直接整理成一个速查表,按图索骥省得翻来翻去:
| 现象 | 可能原因 | 解决办法 |
|---|---|---|
| 安装后无法用密码登录root | 8.0默认auth_socket认证 | sudo mysql进入后ALTER USER设置密码 |
| 远程连接超时 | ufw或iptables未放行3306 | sudo ufw allow 3306/tcp |
| Navicat连接报plugin错误 | 客户端不支持caching_sha2_password | 升级客户端或改mysql_native_password |
| SSL connection error | TLS版本不匹配 | 升级客户端,或服务端配置tls_version |
| mysql: command not found | bin目录不在PATH路径 | 添加export PATH=$PATH:/usr/local/mysql/bin |
| 中文乱码 | 字符集不是utf8mb4 | 修改mysqld配置文件并重启 |
我把排查思路提炼成这样:先看服务状态,再看错误日志,最后才动配置。很多人一遇到问题,上来就改配置,越改越乱。记住一个字,稳。
4.5 从虚拟机到云服务器的路径差异
最后说一个话题,很多人在自己虚拟机上把MySQL装好了、一切都正常,但一到云服务器上就到处碰壁。这里面有环境差异的问题,也有安全策略的问题。
虚拟机的网络一般是NAT模式或者桥接模式,默认情况下防火墙配置也比较宽松,所以MySQL装完就能连。云服务器则不然,除了操作系统层面的防火墙,还有一个安全组的概念。安全组规则的优先级比系统防火墙还高,必须先去云控制台把3306端口加入入站规则,否则你在操作系统里把ufw关了也白搭。
另一个差异是配置。云服务器的机器配置一般不高,内存可能就2G或者4G,这时候MySQL 8.0默认的缓冲池大小可能直接把内存吃满,导致系统OOM。建议在配置里显式调小一点:
[mysqld] innodb_buffer_pool_size = 256M256M对于2G内存的机器来说是一个比较稳的值,既保证查询性能,又留出系统和其他服务的余量。
我自己实际在云服务器部署时踩过这样一个坑:执行apt install mysql-server后,系统占用直接飙升到90%。排查下来就是默认配置把缓冲池设置得太大了。改成256M后,内存降到40%以下,问题解决。配置完成后记得:
sudo systemctl restart mysql才能让参数生效。
这篇内容从头到尾都是我在各种场景里实际折腾MySQL的积累,希望能帮你少走点弯路。安装只是第一步,后面运维和排查才是真正花时间的地方。如果你按照这篇文章的步骤走下来还是遇到问题,优先去看MySQL的错误日志,日志里不会说谎。