资讯动态

Ubuntu 22.04 部署 MySQL 8.0 实战:从安装到主从同步全指南

发布时间:2026/10/6 13:26:40 来源:尧图企业网站定制
前阵子帮朋友在一台全新的Ubuntu 22.04服务器上部署MySQL顺手翻了不少教程结果发现一个很普遍的问题网上的教程大量停留在MySQL 5.7时代很多命令和配置在8.0上要么失效要么有隐藏的坑。最典型的就是root账号的默认认证方式Ubuntu的apt源安装的MySQL 8.0默认用的是auth_socket而不是caching_sha2_password导致很多人“设了密码”之后依然无法远程登录、甚至本地登录都报错。这篇文章我就把这套流程完整走一遍从零开始覆盖安装、安全初始化、root认证修复、远程访问、防火墙、基础调优一直到xtrabackup备份和GTID主从同步的思路最后再补一个Docker Compose部署的对比希望能帮你少踩几个坑。文章适用于两类读者一类是第一次在Ubuntu 22.04上装MySQL、需要一份能直接照着敲的新手另一类是想在测试环境快速验证备份恢复、主从复制方案的运维虽然不会深入到生产级参数调优但关键节点的思路和坑都会讲到。1. 安装前的环境准备为什么我推荐apt源安装而不是二进制包1.1 Ubuntu 22.04自带的MySQL版本与选型Ubuntu 22.04Jammy的官方软件源里默认带的是MySQL 8.0.x版本。国内很多云厂商的镜像源也都同步了这个版本。我查了一下当前源里的具体版本号一般在8.0.3x左右具体以apt-cache policy mysql-server显示为准。选型上我强烈建议直接用apt源安装理由很简单依赖自动处理MySQL Server在Ubuntu上有大量依赖包libaio、libmecab、libjson-c等用apt安装会自动把这些依赖一并装上二进制包方式还得手动处理一堆运行时库。服务管理集成apt安装后会自动注册为systemd服务systemctl start/stop/restart mysql就能管理省去自己写启动脚本的麻烦。升级路径清晰后续MySQL发布小版本更新apt upgrade就能平滑升级二进制包方式升级要重新解压覆盖容易出权限错乱。你可能想问那为什么不直接用Docker这个我放在文章最后专门对比先按原生安装走。1.2 先更新软件源并检查系统基础组件在开始安装之前先把系统更新到最新状态这一步不是可有可无的。我遇到过几次因为libaio版本过旧导致后续MySQL启动失败的情况根源就是系统没有先整体更新。sudo apt update sudo apt upgrade -y中间如果有内核更新建议重启一下服务器让新内核生效。不重启的话后续MySQL装好后虽然能跑但某些系统调优参数可能受旧内核限制影响性能表现尤其是vm.swappiness这类参数。顺手把必要的基础工具装上MySQL安装过程会用到sudo apt install -y net-tools curl wget gnupg lsb-release其中gnupg和lsb-release在后面添加Percona仓库用于安装xtrabackup时会用到先装好不亏。1.3 检查端口占用3306被占用的处理在正式安装之前先确认一下3306端口是否被占用。有些云服务器镜像会预装别的数据库比如MariaDB而MariaDB和MySQL的包在Ubuntu里是冲突的直接apt install mysql-server可能会报错。sudo ss -lntp | grep 3306如果已经占了先确认是什么进程sudo lsof -i:3306如果是MariaDB先停掉并卸载sudo systemctl stop mariadb sudo apt remove --purge mariadb-server mariadb-client -y sudo apt autoremove -y这一步一定要做干净否则后面装MySQL时mysql_install_db会因为数据目录里残留的旧库文件直接报错。2. 核心安装流程从apt install到安全初始化脚本2.1 安装mysql-server在确保环境干净之后执行安装命令sudo apt install mysql-server -y安装过程Ubuntu会自动启动MySQL服务。安装完成后检查状态sudo systemctl status mysql sudo systemctl enable mysqlenable这一步是把MySQL设为开机自启默认情况下apt安装后其实会自动启用但手动执行一次更保险尤其是你装过其他数据库、可能改过systemd配置的情况下。验证MySQL是否真的能正常工作sudo mysqladmin ping如果返回mysqld is alive说明服务正常。2.2 安全初始化脚本mysql_secure_installation逐项讲解装好后MySQL默认的安全配置很松这就是为什么要跑一遍安全初始化脚本。执行sudo mysql_secure_installation这里有一个跟5.7不一样的地方8.0版本安装完成后root账号默认是auth_socket认证后面详细讲所以这个脚本会以sudo身份让你直接进入MySQL来配置而不是要你先输入root密码。脚本会依次问你以下几个问题是否设置密码验证组件VALIDATE PASSWORD COMPONENT建议选Y但密码策略先选LOW只校验长度避免后续开发调试时因密码规则太严格而烦躁。生产环境再按需调成MEDIUM或STRONG。设置root密码注意这里的root是MySQL的root不是操作系统的root。删除匿名用户Remove anonymous users选Y。匿名用户是安全大忌尤其是MySQL默认监听将通过后续配置开放到局域网时。禁止root远程登录Disallow root login remotely选Y。这个建议选Y后续我们会单独创建一个管理账号用于远程连接root只保留本机登录权限。删除test数据库并访问Remove test database and access to it选Y。test库有权限漏洞留着没用。重新加载权限表Reload privilege tables now选Y让所有改动立即生效。每一步的含义我简单解释一下MySQL的权限系统是分层的mysql.user表存储全局权限mysql.db存储数据库级权限匿名用户如果存在会在连接时被MySQL优先匹配导致你新建的普通用户反而拿不到预期权限所以必须清理干净。2.3 安装后的目录结构速览这一步是为了让你后续排查问题时能快速找到对应文件数据目录/var/lib/mysql所有数据库文件、binlog文件都在这里配置文件/etc/mysql/mysql.conf.d/mysqld.cnf这是最主要的配置入口错误日志/var/log/mysql/error.logsystemd服务文件/lib/systemd/system/mysql.service有个脚本化安装的细节如果你需要批量部署多台机器mysql_secure_installation没法直接传参数但可以通过debconf预置回答。不过8.0版本这个脚本内部用的是mysqladmin和SQL语句执行预置比较麻烦我的做法是安装后用一段SQL在多台机器上统一执行后面统一修改root认证部分会讲到。3. root账号认证方式的坑8.0的auth_socket改成密码登录3.1 为什么默认root登录不需要密码这里必须花点篇幅说清楚。Ubuntu源安装的MySQL 8.0root账号默认使用auth_socket插件认证。这个插件的认证逻辑是这样的只要当前操作系统用户是root或者sudo切换成root就能直接通过socket连接MySQL不需要输密码。设计初衷是安全——root账号只在系统本机使用避免暴力破解和远程探测。但实际使用中很多人不适应明明设置了密码却始终无法用密码登录改配置想远程连发现root根本连不上甚至用Navicat等客户端本地连接也失败。查看当前root的认证方式SELECT user, host, plugin FROM mysql.user WHERE user root;正常情况下会看到root的plugin是auth_socket。3.2 修改认证方式的具体SQL将root改为caching_sha2_password密码认证执行以下SQL即可ALTER USER rootlocalhost IDENTIFIED WITH caching_sha2_password BY 你的强密码; FLUSH PRIVILEGES;需要注意8.0默认情况下mysql_native_password插件虽然还存在但官方已经标记为废弃新客户端包括MySQL Shell、最新版本的Navicat都能正常支持caching_sha2_password没必要继续用旧的。改完后退出再重新登录验证mysql -u root -p如果密码能正常登录说明修改成功。3.3 我这边的踩坑记录一次权限表误操作网上不少人教“直接UPDATE mysql.user SET pluginmysql_native_password”这种方法不是说完全不行但风险很大。我曾经在一次操作中直接UPDATE整个user表把user和host字段也顺带改了导致MySQL重启后拒绝所有连接最后只能通过--skip-grant-tables方式进入数据库修复权限表。那次之后我养成了一个习惯修改认证方式一律用ALTER USER不动user表本身。还有一个隐藏问题如果你之前执行过ALTER USER把root改成了密码认证然后又用mysql_secure_installation重新跑了一遍脚本会要求先输root密码才能继续。所以顺序上我的建议是先跑安全初始化脚本再修改认证方式。4. 配置远程连接bind-address、用户授权与防火墙4.1 修改监听地址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重启MySQL使配置生效sudo systemctl restart mysql改完后检查监听状态sudo ss -lntp | grep mysql如果显示0.0.0.0:3306或具体网卡IP说明监听已经开放。这里有一个值得注意的点如果你的服务器有多个网卡比如内网A、公网B不要直接设0.0.0.0最好指定具体的内网IP避免公网端口暴露。比如bind-address 192.168.1.1004.2 创建专用账号并授权远程连接不推荐用root原因不言自明——root权限太大一旦被爆破整个数据库就完了。正确的做法是创建专用业务账号CREATE USER devops192.168.1.% IDENTIFIED BY StrongPassw0rd!; GRANT ALL PRIVILEGES ON *.* TO devops192.168.1.%; FLUSH PRIVILEGES;devops192.168.1.%表示仅允许192.168.1网段的机器连接比%允许所有IP安全得多。如果确实需要允许所有IP访问开发环境常见可以使用devops%但生产环境强烈不建议。单独给业务应用建账号时最好遵循最小权限原则CREATE USER app_user% IDENTIFIED BY AppPassw0rd!; GRANT SELECT, INSERT, UPDATE, DELETE ON mydb.* TO app_user%; FLUSH PRIVILEGES;能看到区别吗业务账号只给了某个数据库的增删改查权限连DROP、CREATE都没给这样即使账号被拖库影响面也有限。4.3 防火墙配置ufw和云安全组Ubuntu 22.04默认使用ufw防火墙。如果你启用过ufw检查sudo ufw status需要放行3306端口sudo ufw allow from 192.168.1.0/24 to any port 3306 proto tcp sudo ufw reload只放行指定网段访问而不是sudo ufw allow 3306这种全开放方式这是我装过N台机器后总结的经验全开放意味着公网也能访问加上云服务器控制台还有一层安全组两层的规则如果都太宽松那就等于裸奔。云服务器阿里云、腾讯云、AWS等还需要在控制台的安全组/防火墙规则里也放行对应端口这个别漏了很多人改了服务器里的ufw却忘了安全组那层结果还是连不上。4.4 远程连接的测试在另一台机器上测试mysql -h 192.168.1.100 -u devops -p如果提示Access denied优先检查账号的host范围是否覆盖了你的来源IPSELECT user, host FROM mysql.user;如果提示Cant connect to MySQL server10060/2003优先检查防火墙和安全组其次是bind-address配置。5. 基础性能调优一套适用于16G内存主机的my.cnf配置5.1 关键参数解释MySQL装完默认配置其实是非常保守的它要考虑在最低配机器上也能跑起来。如果你的是16G内存的主机不改配置直接上业务用不了多久就会遇到性能瓶颈。我最常用的一套基础调优配置如下[mysqld] # 缓冲池大小建议设为物理内存的50%-70% innodb_buffer_pool_size 8G innodb_buffer_pool_instances 8 # 日志相关 innodb_redo_log_capacity 1G max_binlog_size 512M binlog_expire_logs_seconds 2592000 # 连接数 max_connections 500 max_connect_errors 1000 # 临时表 tmp_table_size 64M max_heap_table_size 64M # 慢查询日志 slow_query_log 1 slow_query_log_file /var/log/mysql/slow.log long_query_time 2 # 排序和join缓冲 sort_buffer_size 4M join_buffer_size 4M各参数的作用简单说明一下innodb_buffer_pool_size是最核心的参数InnoDB引擎的索引和行数据在内存中的缓存池大小。8G缓冲池意味着热数据基本都在内存里磁盘的随机读次数会大幅下降。但设置太大会导致内存不足触发Swap反而更慢所以50%-70%是经验值。innodb_redo_log_capacity在8.0.30之后取代了旧的innodb_log_file_sizeRedo Log大小直接影响崩溃恢复的速度和写入吞吐量1G是比较合适的起步值。binlog_expire_logs_seconds取代了废弃的expire_logs_days单位是秒2592000就是30天避免binlog把磁盘塞满。tmp_table_size和max_heap_table_size需要一起设置否则内存临时表超限后会转成磁盘临时表复杂查询会慢得离谱。5.2 应用配置并验证修改配置文件后重启sudo systemctl restart mysql验证参数是否生效SHOW VARIABLES LIKE innodb_buffer_pool_size; SHOW VARIABLES LIKE max_connections;这里有个细节innodb_buffer_pool_size修改后MySQL冷启动时会有初始化和预热过程第一次重启会慢几秒属于正常现象不用惊慌。5.3 一个调优的反面教训连接数和线程池有一次我图省事把max_connections直接设成5000想着反正内存大。结果连续两个星期出现连接数飙升、CPU耗尽的情况。排查下来发现一个业务连接池配置不合理每个Tomcat实例默认建了200个连接几个实例一叠加瞬间把数据库连接榨干。后面把连接数调回500同时优化了业务的连接池配置系统才稳定下来。所以说调优不是调一个参数就完事要先看业务背压的方向再动手改。6. 备份与扩容xtrabackup备份主库和GTID主从同步思路如果你只是学习安装配置到第5节就可以收官了。但既然标题里有“部署”部署就意味着要考虑备份和扩展这也是最近后台私信里问得最多的话题怎么备份MySQL主库怎么部署从库GTID同步到底怎么玩我把关键流程列一遍细节每个都可以单独写一篇这里先给完整路线。6.1 安装XtraBackupXtraBackup是Percona开源的物理备份工具相比mysqldump逻辑备份它的优势是备份速度快、支持热备、恢复时能保留InnoDB表空间和binlog位点信息非常适合做主从搭建和日常备份。Ubuntu 22.04上通过Percona官方仓库安装wget https://repo.percona.com/apt/percona-release_latest.$(lsb_release -sc)_all.deb sudo dpkg -i percona-release_latest.$(lsb_release -sc)_all.deb sudo percona-release setup ps80 sudo apt update sudo apt install -y percona-xtrabackup-80确认版本xtrabackup --version如果输出里有version 8.0.x就装好了。6.2 全量备份与恢复验证备份命令sudo xtrabackup --backup \ --target-dir/data/backup/mysql_full_$(date %Y%m%d) \ --userbackup_user \ --passwordBackupPassw0rd! \ --parallel4记得提前创建备份专用账号并给予相应权限CREATE USER backup_userlocalhost IDENTIFIED BY BackupPassw0rd!; GRANT BACKUP_ADMIN, RELOAD, LOCK TABLES, PROCESS, REPLICATION CLIENT ON *.* TO backup_userlocalhost; FLUSH PRIVILEGES;备份完成后目录里会包含一份xtrabackup_checkpoints文件记录了备份的LSMLog Sequence Number信息做主从同步时这个信息非常关键。恢复的时候不要直接restore到正在运行的数据目录而是先prepare再copy-backsudo xtrabackup --prepare --target-dir/data/backup/mysql_full_20250101 sudo xtrabackup --copy-back --target-dir/data/backup/mysql_full_20250101prepare阶段做了两件事回放Redo Log把数据文件推到一致状态清理未提交的Undo Log事务。不做prepare直接copy-backMySQL启动时会报数据文件不一致错误。6.3 GTID主从同步的配置要点GTIDGlobal Transaction Identifier是MySQL 5.6之后引入的全局事务标识符相比传统的基于binlog文件名位置的同步方式GTID的优点是主从切换时不需要手动找偏移量故障转移复杂度大幅降低。主库开启GTID需要修改配置文件[mysqld] server-id 1 gtid_mode ON enforce_gtid_consistency ON log_bin /var/log/mysql/mysql-bin从库配置[mysqld] server-id 2 gtid_mode ON enforce_gtid_consistency ON注意gtid_modeON不能直接设置MySQL要求按照OFF - OFF_PERMISSIVE - ON_PERMISSIVE - ON的顺序递增设置。在线上环境直接改回ON会报错必须一步步来SET GLOBAL gtid_mode OFF_PERMISSIVE; SET GLOBAL gtid_mode ON_PERMISSIVE; SET GLOBAL gtid_mode ON;6.4 部署从库的流程简述有了全量备份和GTID从库搭建就简单了核心思路是“主库做一次全量备份 - 恢复到从库 - 从库通过GTID自动追平主库”。具体步骤在主库上创建复制账号CREATE USER repl% IDENTIFIED BY ReplPassw0rd!; GRANT REPLICATION SLAVE ON *.* TO repl%; FLUSH PRIVILEGES;对主库使用xtrabackup做一次全量备份步骤见6.2拿到备份目录和其中的xtrabackup_binlog_info文件记录GTID位置。把备份目录拷贝到从库执行prepare和copy-back注意从库的数据目录要先清空。在从库上执行CHANGE MASTER TO MASTER_HOST192.168.1.100, MASTER_USERrepl, MASTER_PASSWORDReplPassw0rd!, MASTER_AUTO_POSITION1; START SLAVE;MASTER_AUTO_POSITION1是GTID自动定位的关键意味着从库会从主库拉取从全量备份时间点之后的所有事务。查看同步状态SHOW SLAVE STATUS\G重点关注两个字段Slave_IO_Running: Yes和Slave_SQL_Running: Yes。如果两个都是YES说明同步正常。我遇到比较多的问题是Slave_SQL_Running: No大都是由主从数据不一致比如有人在从库手动写了数据、事务冲突引起的。处理思路是先跳过出错事务临时手段然后对比数据必要时重建从库。想在GTID模式下安全跳过用以下SQLSTOP SLAVE; SET GLOBAL sql_slave_skip_counter 1; START SLAVE;但这只是缓兵之计最终还是要从主库重新同步一次才干净。7. 卸载与重建Ubuntu 22.04上正确处理MySQL残留7.1 为什么卸载不干净会导致重装失败这节是意外塞进来的起因是一个粉丝反馈“按教程装MySQL装一半报错说数据目录已存在”查了半天发现是他之前卸载过一次MySQL但/var/lib/mysql目录没有清干净。MySQL安装包会检测数据目录如果目录存在且非空就会跳过初始化流程导致安装完成后服务无法启动。这是Ubuntu系列Linux上最典型的重装坑专门写一节讲清楚。7.2 完整卸载流程完整的卸载命令如下sudo systemctl stop mysql sudo apt remove --purge mysql-server mysql-client mysql-common -y sudo apt autoremove -y然后清理残留目录sudo rm -rf /var/lib/mysql sudo rm -rf /etc/mysql sudo rm -rf /var/log/mysql清理依赖包可选但推荐sudo apt purge *mysql* -y sudo apt autoremove -y全部清完后检查dpkg -l | grep mysql如果没有输出说明卸载干净了。这时候重新执行第二章的安装步骤就不会有任何干扰。7.3 保留数据目录的部分卸载有一种场景是你只想重装MySQL服务端但保留数据库文件比如你想换个版本验证兼容性又怕数据丢失那就可以不清/var/lib/mysql只做apt remove --purge mysql-server但装新版本之前最好先备份数据目录sudo cp -a /var/lib/mysql /var/lib/mysql.bak重装后如果数据目录里的版本和新装版本不一致比如从8.0降到5.7MySQL会拒绝启动并提示“data directory was initialized by a different version”。这种情况基本只能恢复备份或升级回原版本没有其他好办法。8. 补充对比Docker Compose部署MySQL的适用场景8.1 什么时候用Docker、什么时候用原生安装最近Docker Compose部署MySQL的热度很高我也在实际项目里用过。简单对比一下维度原生apt安装Docker Compose部署环境隔离直接使用宿主机资源容器隔离端口映射配置修改改/etc/mysql下的配置文件改docker-compose.yml和环境变量升级apt upgrade拉新镜像重启容器数据持久化数据目录原生管理需要挂载卷否则容器删了数据就没了适合环境生产环境、单机高负载开发环境、微服务多容器编排我的个人原则是生产环境的数据库能用原生安装就用原生安装。理由很简单生产数据库的道路要可控、可预测容器化虽然带来了部署便利但也带来了“数据卷权限混乱”“容器重启后IP变化”“日志收集链路复杂”等额外问题。开发环境我反而推荐用Docker Compose因为可以快速起停、随心所欲地切换版本。8.2 一个Docker Compose的参考配置如果你确实需要在开发环境使用Docker部署MySQL这是一份可以直接用的docker-compose.ymlservices: mysql: image: mysql:8.0 container_name: mysql-dev restart: unless-stopped environment: MYSQL_ROOT_PASSWORD: RootPassw0rd! MYSQL_DATABASE: appdb MYSQL_USER: app_user MYSQL_PASSWORD: AppPassw0rd! TZ: Asia/Shanghai ports: - 3306:3306 volumes: - ./data:/var/lib/mysql - ./my.cnf:/etc/mysql/conf.d/custom.cnf command: - --character-set-serverutf8mb4 - --collation-serverutf8mb4_unicode_ci启动docker compose up -d这里有个容易踩的坑./data:/var/lib/mysql这个挂载第一次启动时Docker会自动以镜像内默认配置初始化数据目录但如果宿主机./data目录存在且非空MySQL会直接使用可能触发“目录初始化失败”的错误。建议第一次启动前让./data目录保持空状态。8.3 如果原生安装遇到问题Docker也不失为一种快速恢复手段有一次我给客户调试一个MySQL 8.0的读写性能问题原生环境的配置被之前的同事改得乱七八糟调了半天没还原到干净状态。后来我直接在Docker里起了一个新实例用同样的my.cnf和数据集很快就定位到是某个参数设置异常。这个思路仅供参考Docker不能替代生产数据库但它是很好的调试沙盒。到这一步从环境准备到安装配置、从调优到备份同步、从卸载清理到Docker对比整条部署路径都走通了。我个人实际操作下来最有价值的一句话是装MySQL从来不是难点难点在装完后的每一步配置都带着“默认安全但不方便”与“开放但危险”的权衡。希望这篇整理能让你少走几趟弯路。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑