搞过 Linux 服务器的人基本都躲不开 MySQL尤其是 Ubuntu 上安装配置这块。我最早是在一台配置很一般的云服务器上手搓当时照着网上的文章一路apt install mysql-server装完发现字符集乱码、root 密码没法远程登、端口被防火墙拦搞到差点想砸键盘。后来把官方文档和实际调参都捋了一遍才算把整个流程吃透。这篇就把我在 Ubuntu 上安装和配置 MySQL 的完整过程写出来包括版本选型、仓库配置、安全初始化、性能参数、权限管理、备份恢复和常见坑适合刚接触 Linux 的开发者也适合那些装完以后不知道怎么调优的老手参考。很多人以为 Ubuntu 上装 MySQL 就是跑一条命令的事其实后面藏着一堆细节。比如默认源里的版本可能不是最新而 MySQL 官方仓库的版本更新更及时再比如mysql_secure_installation这个步骤看似多余实际能帮你堵掉匿名账号和测试库的隐患。下面我从头到尾拆开来说。1. 装 MySQL 前先想清楚的事1.1 你自己的 Ubuntu 版本是什么先确认系统版本因为不同版本的 Ubuntu 使用的包管理器和默认软件源策略不太一样。虽然都叫apt但 20.04、22.04、24.04 这些 LTS 版本对应的 MySQL 默认版本可能不同。看版本命令很简单lsb_release -a运行完可以看到Distributor ID: Ubuntu和Release: xx.04。我测试过 20.04 默认源里是 MySQL 8.0.x22.04 也是 8.0.x但小版本会有区别24.04 则直接是 8.0 系列较新的维护版。如果你的应用对 MySQL 小版本有特殊依赖比如某些驱动对 8.0.28 以下的认证插件有兼容问题那就要在安装前决定是直接用默认源还是换成官方源。1.2 选系统自带源还是 MySQL 官方源这是一个容易被忽略的决策点。Ubuntu 自带的mysql-server包是经过发行版维护者测试的稳定性和系统兼容性都更好但版本更新滞后。MySQL 官方源则会提供最新的 GA 版本还能拿到mysql-apt-config这样的配置工具方便你指定安装 8.0、8.4 或更晚的版本。我的建议是如果不是为了尝鲜新功能优先用系统自带的默认源因为它省事且足够稳定。但如果你有明确的需求比如要安装某个特定小版本或者希望后续能方便地用apt upgrade升级到官方源里的新版本那就走官方源。走官方源需要先下载一个.deb包来配置源你可以在 MySQL 官网上找到对应 Ubuntu 平台的包注意选对架构x86_64 的选amd64。1.3 预先想好你的使用场景安装前应该问自己一个问题这台 MySQL 是给本机上的 Web 应用用的还是要对外提供数据库服务如果只是搭配 PHP、Python 之类的本地应用那完全不需要监听所有网络接口只用localhost就够了这样还能减少暴露风险。如果需要远程连接则要规划好账号权限和防火墙规则这些我会在后面的配置部分专门讲。2. 安装前的系统准备2.1 更新软件包索引在任何安装之前先把系统索引和现有软件包更新到最新避免依赖冲突。这一步虽然基础但很多人跳过之后遇到莫名其妙的依赖问题。sudo apt update sudo apt upgrade -y升级的时候如果提示重启服务可以选Ok但要注意如果内核有更新建议之后找时间重启机器不然 MySQL 装上后可能运行在旧内核上这倒不至于出大问题但总让人心里不踏实。2.2 用默认源安装 MySQL最简单的做法sudo apt install mysql-server -y安装完成后MySQL 服务会自动启动并设置开机自启。你可以验证一下sudo systemctl status mysql如果看到active (running)说明服务正常。这一步装出来的版本可能是mysql Ver 8.0.x for Linux on x86_64这样的。如果你嫌版本旧可以再按 2.3 的步骤换成官方源。2.3 添加 MySQL 官方源的完整过程我到这一步建议你直接使用官方源虽然多几步但能解决后面可能遇到的版本升级问题。先把官方源配置文件下载下来wget https://dev.mysql.com/get/mysql-apt-config_0.8.30-1_all.deb sudo dpkg -i mysql-apt-config_0.8.30-1_all.deb中间会弹出配置界面你选Server那个选项然后选你想要的 MySQL 版本比如mysql-8.0。如果你不清楚该选什么保持默认也行。之后执行sudo apt update这时候源里就有了 MySQL 官方提供的版本。接着安装sudo apt install mysql-server -y安装过程中会提示你为 root 用户设置密码。注意这里的 root 是 MySQL 内部的 root和 Linux 的 root 不是一回事。如果你在那一步直接回车默认密码为空之后用mysql_secure_installation也可以补上。2.4 安装时容易翻车的网络问题国内服务器访问官方源经常会出现下载速度慢或者超时的情况。解决办法是换镜像或使用代理但这不是本文重点。如果直接安装系统自带源没问题就不需要折腾官方源。另一种做法是下载.deb包后用dpkg安装但依赖关系处理比较麻烦。不管走哪条路安装前都可以先跑一遍sudo apt update看看源是否正常工作如果报错先修源再安装。3. 初始化配置与安全加固3.1 运行安全安装脚本装完 MySQL 后第一件事不是急着建库而是运行官方提供的安全加固脚本sudo mysql_secure_installation它会依次询问你几个问题是否配置 Validate Password 组件我建议选1或2也就是设置密码强度检查。输入 root 密码并确认。是否移除匿名用户选择Y。是否禁止 root 远程登录选择Y除非你有特殊理由开放 root 远程。是否删除测试数据库选择Y。是否重新加载权限表选择Y。这里有个容易踩的坑如果你在安装时没有设置 root 密码运行这个脚本时第一次会要求你设置新密码。如果已经有密码就先用旧密码登进去再改。如果你忘记了 root 密码后面的常见问题部分会讲重置方法。3.2 理解 root 用户的两种登入方式在 Ubuntu 的 MySQL 8.0 中root 用户默认使用auth_socket插件认证意味着你只能通过系统 root 用户或者 sudo 用户直接进入 MySQL不需要密码。这样做提高了本地安全性但也导致很多新手用mysql -u root -p登录时明明输入正确密码却报错。你可以查看当前 root 用户的认证方式SELECT user, host, plugin FROM mysql.user WHERE user root;如果看到auth_socket而你希望用密码登录可以切换为caching_sha2_passwordALTER USER rootlocalhost IDENTIFIED WITH caching_sha2_password BY 你的密码;这里要提醒你改了认证插件后记得执行FLUSH PRIVILEGES;。另外caching_sha2_password是 MySQL 8.0 的默认认证插件一些旧版本的客户端可能不兼容如果你的应用连接报错再改成mysql_native_password也来得及但 8.0 里官方推荐尽量用新的。3.3 验证安装与基本信息登录测试sudo mysql -u root -p输入密码后进入 MySQL 命令行然后查看版本和当前连接的变量SELECT VERSION(); SHOW VARIABLES LIKE version_comment;还可以看看 MySQL 启动时间SHOW GLOBAL STATUS LIKE Uptime;如果都能正常显示基本就说明安装成功了。4. 核心配置文件解析与调优4.1 认识 MySQL 的配置目录Ubuntu 上 MySQL 8.0 的配置文件主要路径是/etc/mysql/my.cnf它只是个总入口真正的配置分散在/etc/mysql/mysql.conf.d/和/etc/mysql/conf.d/里。你可以在这些目录里新建.cnf文件来覆盖或追加配置。这个机制很灵活但同时也容易让人困惑要动配置之前最好先看一遍ls -l /etc/mysql/ ls -l /etc/mysql/mysql.conf.d/常见的做法是编辑/etc/mysql/mysql.conf.d/mysqld.cnf这是服务端主配置文件。修改任何配置前先备份sudo cp /etc/mysql/mysql.conf.d/mysqld.cnf /etc/mysql/mysql.conf.d/mysqld.cnf.bak改完之后重启服务sudo systemctl restart mysql4.2 字符集与排序规则老生常谈但必须搞对字符集是我在安装 MySQL 后第一个要调的地方。默认的latin1不支持中文必须改成 UTF-8 或更完整的 UTF-8MB4。在 MySQL 8.0 中默认字符集已经是utf8mb4但老版本或某些安装方式下可能还是latin1。你可以在配置文件的[mysqld]段添加[mysqld] character_set_server utf8mb4 collation_server utf8mb4_0900_ai_ci然后重启 MySQL。重启后验证SHOW VARIABLES LIKE character_set_server; SHOW VARIABLES LIKE collation_server;注意排序规则要匹配字符集。utf8mb4_0900_ai_ci是 MySQL 8.0 常用的如果你还在用 5.7可能要用utf8mb4_unicode_ci或utf8mb4_general_ci。这里还有个细节数据库和表的字符集可以在建库建表时单独指定但服务端默认值决定了那些没显式指定的对象。4.3 时区设置MySQL 的时区默认跟随系统如果你服务器时区是 UTC那数据库时间会比北京时间慢 8 小时。最好在配置里显式指定[mysqld] default-time-zone 08:00这里08:00是东八区。如果你不确定就运行SELECT NOW();看看当前时间如果差了几个小时就按这种方式调整。要注意default-time-zone这个变量可能需要一定的权限才能修改用 root 直接改配置文件是最省事的。4.4 连接数与会话超时默认的连接数上限是 151对于小型应用够用但如果你的应用有大量连接池可能不够。可以在[mysqld]下设置max_connections 500 wait_timeout 600 interactive_timeout 600wait_timeout是普通连接的空闲超时时间单位秒600 表示 10 分钟。interactive_timeout是交互式连接的。这些参数要根据机器内存合理设置连接数开太高会消耗大量内存每一条连接都会有一些缓存。你的配置得考虑内存上限比如一台 2GB 内存的机器开 500 连接可能就不太健康了。建议先跑free -h看看内存再决定。4.5 缓存与性能参数初调MySQL 8.0 中缓冲池大小innodb_buffer_pool_size是最关键的参数之一默认值通常是 128MB。对于数据量大的业务建议把它设为物理内存的 50%~70%。例如 4GB 内存的服务器可以设置为 2G 到 3Ginnodb_buffer_pool_size 2G修改之前要确认数据文件大小和系统内存余量。另外innodb_log_file_size默认 48MB对于频繁写入的场景可以调到 256MB 甚至更大但这会影响崩溃恢复时间。日志文件太大恢复时扫描的时间也会变长。我建议先保持默认用监控工具观察一段时间再动这些参数。4.6 日志与慢查询日常诊断最好开启慢查询日志把超过 2 秒的查询记录下来。配置文件里加上slow_query_log 1 slow_query_log_file /var/log/mysql/slow.log long_query_time 2这样能帮你快速定位那些拖着数据库后腿的 SQL。另外错误日志默认路径一般是/var/log/mysql/error.log如果哪天服务启动失败第一件事就是看这个文件很多问题在最后几行就能找到答案。还可以开启通用日志general_log来记录所有查询但它会快速膨胀调试完务必关掉。5. 用户、权限与远程访问5.1 创建业务专用账号我强烈建议不要用 root 去跑业务应用。创建一个按业务命名的账号只给它需要的权限能大幅降低风险。创建用户假设密码为Str0ngPass!CREATE USER app_userlocalhost IDENTIFIED BY Str0ngPass!;如果应用和数据库不在同一台机器还需要允许从某个 IP 或网段登录。比如只允许应用服务器的 IP192.168.1.100连接CREATE USER app_user192.168.1.100 IDENTIFIED BY Str0ngPass!;如果主机部分填%表示任意 IP 都能连但这非常危险除非你很清楚自己在做什么否则不要这么用。5.2 授权与撤销给用户授予某个数据库的所有权限GRANT ALL PRIVILEGES ON mydb.* TO app_userlocalhost; FLUSH PRIVILEGES;这里mydb.*表示 mydb 库下的所有表。更细的权限包括SELECT、INSERT、UPDATE、DELETE等。如果只给查询权限GRANT SELECT ON mydb.* TO readonly_userlocalhost;需要撤销权限时REVOKE ALL PRIVILEGES ON mydb.* FROM app_userlocalhost;删除用户DROP USER app_userlocalhost;注意修改权限后一般要执行FLUSH PRIVILEGES;让权限表重新加载。MySQL 8.0 会隐式地处理部分情况但养成习惯总没错。5.3 开启远程访问的完整设置MySQL 默认只监听127.0.0.1也就是不开放远程。如果你需要远程连接先修改配置文件/etc/mysql/mysql.conf.d/mysqld.cnf找到bind-address这行bind-address 0.0.0.0改成0.0.0.0表示监听所有网卡然后重启。只监听某个具体 IP 也可以填服务器的内网 IP。还要确认防火墙允许 3306 端口比如使用 ufwsudo ufw allow 3306/tcp如果你用的是云服务商的安全组记得在控制台放行相应端口。远程连接测试mysql -h 服务器IP -u app_user -p -P 3306我要特别提醒的是不要只改 bind-address 而忘了防火墙否则你会一直卡在connect to server: Connection refused。如果测试连接不上先在本机登录看是否正常然后检查端口监听状态ss -tlnp | grep 3306如果显示0.0.0.0:3306说明服务器在监听问题可能出在防火墙或账号主机限制。6. 数据备份与恢复6.1 使用 mysqldump 备份备份是数据库管理里最不能省的一环。mysqldump 是 MySQL 自带的逻辑备份工具。简单的备份命令mysqldump -u root -p --databases mydb /backup/mydb_$(date %F).sql加上--single-transaction可以在备份时减少对表锁定影响针对 InnoDBmysqldump -u root -p --single-transaction --routines --triggers --databases mydb /backup/mydb_$(date %F).sql--routines备份存储过程--triggers备份触发器。如果备份所有库mysqldump -u root -p --all-databases /backup/all_$(date %F).sql备份文件最好压缩mysqldump -u root -p --all-databases | gzip /backup/all_$(date %F).sql.gz恢复时再解压导入。备份文件不要和数据库放在同一块硬盘上至少放到另一目录或远程存储否则硬盘故障时备份也一起没了。6.2 恢复备份恢复很简单把备份文件导入 MySQL 即可mysql -u root -p /backup/mydb_2025-01-01.sql如果是压缩包gunzip /backup/all_2025-01-01.sql.gz | mysql -u root -p这里有一点要留意备份 SQL 开头可能包含DROP TABLE或CREATE TABLE恢复时如果目标库已存在同名表会覆盖。所以在恢复前最好先确认你要在哪个环境恢复避免把生产环境覆盖了。我建议在恢复前把目标库导出一个当前快照再执行恢复万一搞错还能补救。7. 常见问题与排查技巧7.1 服务无法启动怎么定位如果systemctl status mysql显示失败可以查看错误日志sudo tail -100 /var/log/mysql/error.log常见错误包括磁盘空间不足、配置文件权限错误、InnoDB 数据目录损坏、端口被占用。先看日志里有没有Cant create/write to file、Permission denied、Address already in use这类关键词。如果是端口被占用用ss -tlnp | grep 3306找到占用进程。如果是权限错误检查/var/lib/mysql目录属主是否为mysqlsudo chown -R mysql:mysql /var/lib/mysql这种情况多见于你手动移动过数据目录后忘记改属主。7.2 忘记 root 密码怎么办忘记 root 密码是所有人迟早会遇到的问题。MySQL 8.0 的处理方式和 5.7 略有不同但基本思路是一样的跳过授权表登录然后改密码。首先停掉服务sudo systemctl stop mysql然后以跳过授权表的方式启动sudo mysqld_safe --skip-grant-tables 或者编辑配置加一行skip-grant-tables再启动。此时可以无密码登录mysql -u root登录后先刷新权限FLUSH PRIVILEGES;然后更改 root 密码ALTER USER rootlocalhost IDENTIFIED BY NewStrongPass!;退出后重启服务sudo systemctl restart mysql这里有个非常关键的点skip-grant-tables状态下要先把权限表刷新了才能执行ALTER USER否则可能报错。改完密码后一定要记得移除skip-grant-tables配置项并且重启服务不然任何人都能在不认证的情况下登进数据库等于裸奔。7.3 连接数耗尽应用报Too many connections时是因为连接数达到了max_connections上限。先用管理员账号连进去看状态SHOW STATUS LIKE Threads_connected; SHOW VARIABLES LIKE max_connections;如果连接数确实经常接近上限可以临时提高max_connections但要结合内存。同时检查应用端的连接池配置看是否没有正确释放连接。有时候不是数量不够而是程序里有连接泄漏每次数据库操作都新建连接又没关闭时间一长就满了。这种问题靠调参数只能缓解根治要改代码。7.4 字符集乱码插入中文后显示???几乎都是客户端连接字符集和服务端不匹配。检查服务端和客户端的字符集SHOW VARIABLES LIKE character_set_%;确保character_set_client和character_set_server都是utf8mb4。还可以在连接串里指定字符集比如 PHP 的 PDO DSN 里加charsetutf8mb4JDBC 连接串加characterEncodingutf8mb4。改完配置后旧表如果已经是latin1需要转成utf8mb4转之前备份好。转换命令可以针对单表ALTER TABLE my_table CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;但要先做好数据备份转换过程会重写表数据量大时耗时较长。8. 安装配置过程中的几条个人经验最后分享几个我在实际部署中积累的点。首先装完 MySQL 后我习惯第一时间用mysql_secure_installation把匿名用户和测试库清掉别等上线前才做那时候业务数据一来就下不去手了。其次任何配置修改都走mysqld.cnf的追加文件不要随便改系统级my.cnf的核心部分维护起来清爽。再次备份要不仅做正常备份还要定期在另一台环境恢复测试确认备份文件不是一包垃圾我曾经遇到过备份文件损坏但没检查直到真正要恢复时才发现的尴尬事。还有一个容易忽略的点MySQL 升级后认证插件可能变化尤其是 8.0 的默认认证插件和旧客户端不兼容升级前先看应用连接测试是否正常。如果你在生产环境跑旧应用建议先在测试环境用同样的客户端版本连一下新 MySQL 实例确认兼容性再升级。关于远程访问我一般不会开 root 远程而是创建专用账号并限制来源 IP这样即使密码泄露影响面也有限。如果你是从零开始搭服务器希望这篇能帮你少踩几个坑。装数据库只是起点后续还有性能监控、日志轮转、密码策略这些事要做但先把安装和基础配置弄扎实后面的路就顺了。