多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

Ubuntu 22.04 安装 MySQL 8.0:从 apt 部署到远程连接与踩坑实战

Ubuntu 22.04 安装 MySQL 8.0:从 apt 部署到远程连接与踩坑实战 最近帮同事把几台测试服务器上的MySQL重新收拾了一遍清一色都是Ubuntu 22.04。说起来“安装MySQL”这件事在很多教程里就是两三条命令的事自己上手才知道坑一个接一个装完root登不进去、字符集乱码、外面连不上甚至卸载重装都能把自己绕晕。这篇就把我在这套环境上实测走通的完整流程写下来从环境准备、包安装、安全初始化、核心配置到远程访问和卸载重装每一步我都会说明为什么这么做顺便把我踩过的坑一并交代清楚。内容主要适合两类人一类是刚接触Linux服务器、想在自己的Ubuntu 22.04上把MySQL跑起来的同学另一类是之前装过但又搞坏了、想彻底重来一遍的朋友。我尽量把命令写到可以直接复制执行的程度但也会把背后的原理讲透这样你后面遇到变体情况也能自己判断。1. 写在前面的几个关键认知1.1 为什么我推荐直接用apt装MySQL而不是折腾源码编译说句实话在Ubuntu 22.04上装MySQL绝大多数场景直接sudo apt install mysql-server就够了不需要从源码编译也不用去官网下tar包手动解压。很多人一搜“MySQL安装教程”就看到源码编译的帖子其实那是给对版本有特殊要求或者追求自定义编译参数的人准备的。你用apt装的是Ubuntu官方源里预编译好的二进制包依赖关系自动处理服务注册、开机自启、日志轮转这些通通不用自己操心。对于日常开发、个人博客、中小型项目的数据库服务器来说apt装出来的性能和稳定性完全够用。值得多说一句的是网上偶尔有人提到用snap装MySQL我试过一次体验并不好。snap版本的目录结构、服务名和deb包不完全一样出了问题很难找到对应的排查经验而且系统资源占用也相对高。所以我的原则很简单除非有特殊理由否则一律apt装。1.2 先搞清楚要装MySQL 8还是5.7Ubuntu 22.04的官方源里默认带的是MySQL 8.0系列不是5.7。这一点非常关键因为很多人拿着老教程去装5.7折腾半天发现源里根本没有这个版本。MySQL 8.0和5.7有几个明显区别我实际用下来的体会有几点身份认证插件不同。8.0默认用caching_sha2_password而5.7及更早版本用的是mysql_native_password。这个问题会导致老版本客户端、某些老项目连接报错后面我会专门写解决办法。8.0的性能和安全性更好窗口函数等SQL功能也更完善新项目完全没必要回头用5.7。官方源里没有5.7如果你因为老项目原因必须用5.7我的建议是直接用Docker跑一个mysql:5.7容器比在系统里硬装省心太多。还有一个很多人搜过的问题“mysql安装没有develop选项”。这个说法其实来自Windows平台的MySQL Installer图形安装器里面有Developer Default、Server only之类的组件选择。在Ubuntu上用apt安装时是没有这种交互选项的你只需要装mysql-server一个包服务端、客户端、基础工具都会一起装好。如果你被这个说法困惑过可以放心了。2. 准备工作环境检查与系统更新2.1 确认系统版本和网络环境不管你是新买的云服务器还是本地虚拟机第一步都建议先确认系统版本避免拿着CentOS的教程在Ubuntu上硬套。打开终端执行lsb_release -a如果输出Description: Ubuntu 22.04.x LTS那就没问题。顺便看下架构uname -m绝大多数服务器是x86_64如果是ARM架构的机器下面的安装命令同样适用因为Ubuntu源里也有ARM版MySQL包只是部分性能调优参数需要留意。接着检查网络和软件源。执行sudo apt update这一步会拉取软件包索引。如果你的网络情况比较特殊导致apt update速度很慢可以考虑把软件源换成访问更快的镜像源替换之前记得先备份原来的/etc/apt/sources.list文件。不过一般情况下官方源或者地区性镜像源就够用不需要在这个环节卡太久。更新完软件源之后我习惯顺手看下源里MySQL包的版本信息apt-cache policy mysql-server输出里会显示候选版本如果是8.0.x说明源没问题接下来直接装就行。2.2 把旧的MySQL残留清理干净这一步太重要了。我之前遇到过好几台机器用户说“我明明没装过MySQL怎么一装就报端口占用”结果一查机器上有旧版本或者没卸载干净的残留。先检查有没有装过MySQL相关的东西dpkg -l | grep mysql没有任何输出说明是干净的。如果出现了类似mysql-server-8.0这样的记录说明之前装过建议先把老版本卸载再继续后面的步骤。卸载命令我放在最后一部分“卸载重装”里那里有完整的操作你也可以直接跳到那节看完再回来。再检查一下3306端口是否被占用ss -lntp | grep 3306有输出说明端口已经被占用了可能是别的数据库实例也有可能是残留进程。这时候要搞清楚是谁在占用别盲目装新的。最后把系统自带的包索引更新一遍同时升级一下已有的软件包sudo apt update sudo apt upgrade -y这一步会花点时间但很有必要。老的内核或者依赖库可能会导致MySQL安装时出现莫名奇妙的依赖问题更新完再装会顺畅很多。3. 用apt安装MySQL并验证服务3.1 一条命令装完mysql-server环境准备好之后安装过程其实非常简单sudo apt install mysql-server -y安装过程中系统会把mysql-server-8.0、mysql-client-8.0、mysql-common这些包一起拉下来不需要单独装客户端。等待进度条跑完MySQL就算装好了。验证版本mysql --version正常会输出类似mysql Ver 8.0.39-0ubuntu0.22.04.1 for Linux on x86_64这样的文字。看到这个说明核心组件已经就位。接着看服务状态systemctl status mysql如果是active (running)说明mysqld已经正常启动。如果没有运行可以手动启动sudo systemctl start mysql我建议顺手做一件事把开机自启打开省得服务器重启之后数据库没起来sudo systemctl enable mysql3.2 服务启停和连接测试服务管理的常用命令我直接列出来后面排查问题会频繁用到# 重启服务改配置之后经常用 sudo systemctl restart mysql # 停止服务卸载或维护时用 sudo systemctl stop mysql # 启动服务 sudo systemctl start mysql # 查看详细状态 systemctl status mysql重点来了装完之后你怎么连进去Ubuntu上MySQL默认的root用户认证方式比较特殊我第一步先试一下免密登录sudo mysql这里不需要输入密码直接回车就能进入mysql命令行界面。这是Ubuntu默认的安全策略root用户通过系统socket认证当前系统用户是root或具有sudo权限时可以直接进。见识一下然后退出SHOW DATABASES; EXIT;如果你直接执行mysql -u root -p然后随便输个密码大概率会报Access denied。这个现象几乎每个新手都会遇到原因我在下一节仔细讲。4. 安全初始化与root账号的正确打开方式4.1 mysql_secure_installation到底做了什么安装完成后的第一件事我建议跑一下安全初始化脚本sudo mysql_secure_installation这个脚本会问你一系列问题很多人不知道该怎么选我按顺序说第一个问题问是否安装密码强度校验组件Validate Password Component输入Y并按提示选择强度。一般选1MEDIUM就够要求密码至少8位包含大小写字母、数字和特殊字符。接下来输入新的root密码注意要满足刚才选的强度要求。是否删除匿名用户选Y。匿名用户意味着任何人都能无账号登录必须删。是否禁止root远程登录选Y。root账号只在本地用远程访问用单独创建的应用账号。是否删除test测试库选Y。test库是默认空库不删留着没意义。是否现在刷新权限表选Y。这套流程跑完MySQL的基本安全加固就算完成了。有一点要说明这个脚本只是“基本”安全措施生产环境还需要考虑账号体系设计、网络隔离、备份策略等不要以为跑完这一步就高枕无忧了。4.2 root账号登录失败先搞清auth_socket机制这一节内容几乎可以解决90%的“MySQL装完登不进去”问题。Ubuntu直接用apt安装MySQL时root账号默认走的认证插件是auth_socket不是密码认证。这意味着只要你是系统root用户或者有sudo权限执行sudo mysql就能直接进不需要密码。但如果你尝试mysql -u root -p然后输入密码反而会被拒绝因为auth_socket根本不校验密码。我在一台机器上试过走的流程是先sudo mysql进去然后执行下面的SQL把root改成密码登录ALTER USER rootlocalhost IDENTIFIED WITH mysql_native_password BY 你的新密码; FLUSH PRIVILEGES;跑完之后root的认证方式就从socket变成了密码以后可以用mysql -u root -p登录了。但这里我反而建议你考虑清楚你真的需要把root改成密码登录吗我的习惯是保留root的auth_socket认证不改它另外创建一个日常使用的管理账号。理由很简单root的socket认证只允许本机管理员访问攻击面更小日常开发想连接数据库就用普通账号就算账号密码泄露也不至于直接丢掉最高权限。尤其是服务器上还跑着网站和业务接口的时候少给外部应用开放root权限是必须养成的习惯。如果你确实需要远程用root至少把host限制在一个可信的网段内不要放给所有IP。5. 核心配置字符集、时区、连接数与日志5.1 字符集、时区和连接数的配置写法MySQL装好之后默认配置可以用但有几个参数我建议第一时间调一下否则项目跑起来再改就会发现很多表结构、连接串都受影响。配置文件的位置在/etc/mysql/mysql.conf.d/mysqld.cnf这是Ubuntu上mysqld的主配置入口。用vim打开sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf在文件末尾的[mysqld]段里追加以下内容# 字符集 character-set-server utf8mb4 collation-server utf8mb4_unicode_ci # 时区 default-time-zone 08:00 # 连接数 max_connections 300为什么字符集用utf8mb4因为MySQL的utf8实际上是utf8mb3最多只能存3字节字符遇到表情符号或者生僻字直接报错。utf8mb4才是完整的Unicode实现兼容性最好。排序规则选utf8mb4_unicode_ci是经典选择按Unicode标准排序足够绝大多数中文项目使用。MySQL 8.0默认的utf8mb4_0900_ai_ci也可以只是如果你要做数据迁移、跨版本复制用unicode_ci会省掉一些排序差异的麻烦。时区这里也要说明一下。如果你的服务器部署在国内业务场景一般希望MySQL时间区域也是东八区。配置里写08:00比写Asia/Shanghai更直接因为Asia/Shanghai这种命名时区需要系统加载时区表不是所有环境都预置。连接数默认是151对于一些稍微有点并发的小应用足够如果项目是Java Web、Spring Boot这类常驻连接比较多的可以调到两三百。但别无脑调大MySQL每个连接都会占用内存粗算150个连接大概消耗1~2G内存云服务器只有2G内存的话把max_connections调到500反而是帮倒忙。改配置前先看一眼机器内存free -h。改完配置文件重启服务让配置生效sudo systemctl restart mysql然后进入MySQL验证SHOW VARIABLES LIKE character_set_server; SHOW VARIABLES LIKE collation_server; SHOW VARIABLES LIKE time_zone;看到utf8mb4、utf8mb4_unicode_ci、08:00说明配置已经生效了。5.2 查看错误日志和日志轮转MySQL的日志目录默认在/var/log/mysql主错误日志是error.log。服务启动失败、权限出错、连接异常第一反应就是看这个文件sudo tail -n 100 /var/log/mysql/error.log这个习惯在Linux服务器维护中非常有用。很多“我MySQL怎么起不来了”的问题答案就在日志最后几行里。比如常见的socket路径错误、目录权限不对、配置项写错了日志都会给出具体提示。日志轮转这块Ubuntu已经自动配好了不需要你手动清日志。我个人只是建议如果某个库业务量大导致日志膨胀明显可以关注一下/etc/logrotate.d/mysql-server里的配置一般默认按周轮转并保留几份足够了。另外我习惯在改完配置之后多看一遍服务状态sudo systemctl status mysql systemctl is-enabled mysql确认服务是active (running)并且enabled状态心里踏实。6. 远程连接创建用户、授权、防火墙一次讲清6.1 创建用户并授权的完整SQL本地连上MySQL之后接下来很多人要干的事就是让应用服务器或自己电脑能远程连数据库。这里的第一步不是改配置文件而是先创建远程用户。进入MySQLsudo mysql创建用户并指定允许的连接来源-- 只允许本机访问 CREATE USER appuserlocalhost IDENTIFIED BY AppPass2026; -- 允许192.168.1.x网段访问 CREATE USER appuser192.168.1.% IDENTIFIED BY AppPass2026; -- 允许所有来源访问不推荐 CREATE USER appuser% IDENTIFIED BY AppPass2026;然后授权。这里强烈建议按最小权限原则来别动不动就ALL PRIVILEGES ON *.*-- 只给某个库的增删改查权限 GRANT SELECT, INSERT, UPDATE, DELETE ON mydb.* TO appuser192.168.1.%; -- 临时开发环境可以给全部权限但限定库名 GRANT ALL PRIVILEGES ON mydb.* TO appuser192.168.1.%;最后刷新权限FLUSH PRIVILEGES;退出后用客户端验证一下mysql -u appuser -p -h 服务器IP -P 3306我踩过的一个坑是创建用户时用localhost然后远程去连怎么都连不上因为localhost只匹配本机连接。如果你想远程访问用户的host部分一定要写能匹配你来源IP的值要么具体网段要么%。6.2 防火墙与云安全组双重检查3306端口怎么放行到了这一步很多人的配置看着都对用户也建好了密码也没错但远程工具还是报Cant connect to MySQL server on ... (10060)。原因多半是端口没放行。先看看MySQL有没有监听非本机地址。默认配置下MySQL只监听127.0.0.1你改完远程用户也没用它根本没对外开放。修改方法sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf找到这一行bind-address 127.0.0.1改成bind-address 0.0.0.0然后重启sudo systemctl restart mysql用ss验证监听地址sudo ss -lntp | grep 3306输出里如果绑定的IP是0.0.0.0:3306说明监听已经对外开放了。接着处理防火墙。Ubuntu默认用ufw先看状态sudo ufw status如果是active放行3306端口并限定来源推荐这样做sudo ufw allow from 192.168.1.0/24 to any port 3306如果你只是想临时测试直接sudo ufw allow 3306/tcp也行但生产环境最好还是限定具体来源网段。还有最后一个隐蔽关卡如果你用的是云服务器厂商控制台里的安全组也要放行3306端口。很多人在服务器上把ufw关了结果还是连不上就是栽在安全组这里。这个步骤太容易漏掉了我特意再强调一次云控制台安全组入方向规则加一条来源填你的办公IP或VPC网段协议TCP端口3306然后保存生效。到这里远程连接基本就通了。7. 踩坑记录登录失败、密码策略、依赖损坏和卸载重装7.1 常见问题排查速查表我整理了一份高频问题速查表按照“现象 → 解决办法”来写这个表我每次部署都会看一遍实用性很高问题现象可能原因解决办法Access denied for user rootlocalhostroot走auth_socket认证密码不对用sudo mysql进入或用ALTER USER改成密码认证Cant connect to local MySQL server through socket /var/run/mysqld/mysqld.sockmysqld没启动或socket路径不对systemctl status mysql看日志手动start服务远程连接超时或10060bind-address或防火墙/安全组没放行改bind-address0.0.0.0放行3306双重检查ERROR 1819 (HY000): Your password does not satisfy the current policy requirements密码强度不够提高密码复杂度或者调整validate_password组件策略Authentication plugin caching_sha2_password cannot be loaded客户端版本太旧不支持8.0新插件升级客户端或者把用户改成mysql_native_passwordUnknown system variable validate_password8.0里组件名变了INSTALL COMPONENT file://component_validate_password;依赖损坏apt安装失败之前有包没装完sudo apt --fix-broken install -y这里面有两个问题特别值得展开。第一个是老客户端连接MySQL 8.0报认证插件错误。MySQL 8.0默认caching_sha2_password如果项目里用的数据库驱动太老比如老版本PHP、Python、Navicat旧版连接时就会报错。临时解决办法是把该用户的认证方式改回老的ALTER USER appuser% IDENTIFIED WITH mysql_native_password BY 你的密码; FLUSH PRIVILEGES;但从长远来说建议升级客户端和驱动到支持caching_sha2_password的版本毕竟mysql_native_password在8.0版本系列里已经标记为废弃后续版本可能彻底移除。第二个是忘记root密码。遇到这种情况先别急着重装系统用跳过权限表的方式恢复sudo systemctl stop mysql sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf在[mysqld]下加一行skip-grant-tables保存后启动MySQL此时任何用户都能无密码进入。进去后执行FLUSH PRIVILEGES; ALTER USER rootlocalhost IDENTIFIED BY 新密码; FLUSH PRIVILEGES;然后务必把配置文件里的skip-grant-tables删除再重启服务。强调一遍这个参数绝不能留在生产配置里否则等于数据库大门敞开。用完之后必须删这一点我每次都会反复确认。7.2 卸载重装的完整命令最后说一个很多人都会干的事装坏了想彻底卸载重来。最简单的办法不是直接apt remove因为不处理数据目录的话重装后还是老配置问题依旧。完整卸载命令如下sudo systemctl stop mysql sudo apt purge mysql-server mysql-client mysql-common mysql-server-core-8.0 mysql-client-core-8.0 sudo rm -rf /var/lib/mysql /etc/mysql /var/log/mysql sudo apt autoremove -y解释一下每一步的用意。purge会连配置文件一起删除如果你想保留数据目录/var/lib/mysql不要执行rm -rf那一步这样数据库文件还在重装之后可以尝试直接复用。但如果你的目标是彻底回归干净环境那数据目录和配置目录都要删干净否则重新安装时会因为旧的备份文件夹、权限问题报错。全部清理完之后再装一次sudo apt update sudo apt install mysql-server -y sudo mysql_secure_installation注意重装之后之前的用户、权限、配置全部没了需要重新创建用户和授权。如果你是因为必须要用5.7版本才来折腾卸载我再给一个建议直接上Docker跑一个5.7容器比自己跟源里的版本死磕省事太多了。参考命令docker run -d \ --name mysql57 \ -p 3306:3306 \ -e MYSQL_ROOT_PASSWORDrootpass \ -v /opt/mysql57:/var/lib/mysql \ mysql:5.7这样既拿到了5.7的完整环境又不会污染宿主机后续要删要换都方便。特别是老项目迁移测试阶段这种“环境隔离”的思路能少踩很多坑。我个人在实际操作中的体会是装MySQL这件事90%的问题都出在“版本认知”和“权限体系”上。版本认清了用对方法一条命令就能装好权限体系理清了后面登录、远程、授权所有环节都会顺畅很多。服务器上任何一步操作都值得多留个心眼尤其是涉及root和端口放行的地方。按这个流程走一遍应该能把你从各种坑里捞出来。
返回列表