OpenEuler系统的升级和降级,说实话是运维兄弟们绕不开的活儿。尤其是生产环境里跑着业务,天天盯着安全公告,CVE修复补丁一出来,不升不放心,升了又怕出幺蛾子;遇到新内核、新特性想尝鲜,或者升级之后发现服务兼容性崩了,又得想办法退回去。这套“进退自如”的本事,比单纯会敲几条命令重要得多。
这篇内容我围绕OpenEuler的实际操作来写,涵盖小版本在线升级、大版本跨版本升级,以及降级回滚的几种主流方案。不管你是刚接触欧拉的运维新人,还是被线上故障逼着找方案的研发同学,按着里面的步骤走,基本能覆盖大部分场景。文章里所有命令我都实测过或见过同行踩坑总结出来的,不搞花架子,直接说怎么做、为什么这么做。
1. 升级与降级的整体思路拆解
1.1 为什么OpenEuler的升级/降级比普通软件更新更“敏感”
很多人第一次接触Linux系统升级,脑子里想的是“不就是yum update嘛”。这句话对一半。OpenEuler作为服务器操作系统,升级的本质不是把几个软件包换新,而是涉及内核、glibc、systemd、编译器工具链、OpenSSL等底层组件的整体变更。这些底层件一旦更新,直接影响上层所有应用的运行环境。
举个例子,你在OpenEuler 22.03 LTS上跑着MySQL 8.0和JDK 8,执行dnf update之后,系统可能顺手把openssl从1.1.1升级到3.0。openssl大版本变更意味着加密库API不兼容,MySQL的SSL连接、Java的JCE Provider可能直接报错。你说我只想修个安全漏洞,结果把数据库搞崩了,这谁顶得住。
所以升不升级不是问题,怎么控制升级范围和可回退才是核心。这也是为什么我在第二、三、四节反复强调:动手之前先搞清楚版本体系,动手之后留好后路。
1.2 OpenEuler的版本生命周期:LTS和创新版怎么选
OpenEuler的版本分两类,理解了这个你才知道自己该升到哪。
LTS版本(Long Term Support):比如22.03 LTS、24.03 LTS,官方承诺维护周期长,企业生产环境默认选这个。LTS版本之间的升级属于大版本升级,通常需要专门的迁移方案。
创新版本:比如24.09、25.09这类,每半年左右发一个,功能新、内核新,但维护周期短,适合开发测试环境尝鲜,不建议直接上生产。
我见过不少兄弟在生产环境跑创新版,理由是“内核版本高,对新硬件支持好”。这个心态能理解,但创新版的生命周期结束之后,安全补丁没人管,出事只能自己扛。如果你一定要追新特性,我的建议是在虚拟机或者容器里跑创新版验证,生产机老老实实待在LTS版本上。
另外说一句,OpenEuler官网提供版本生命周期表,操作前务必去确认一下你当前版本还剩多少维护期。如果只剩半年就结束维护了,那这次升级基本属于“强制任务”,不是可选项。
1.3 升级、降级的常见方案选型对比
我整理了一张表,把OpenEuler几种常用方案的思路差异列出来,方便你按场景对号入座。
| 操作类型 | 方案名称 | 核心机制 | 适用场景 | 风险等级 |
|---|---|---|---|---|
| 小版本升级 | dnf update / dnf upgrade | 更新当前大版本内的软件包到最新 | 日常安全补丁、bugfix | 低 |
| 大版本升级 | dnf upgrade --releasever=新版本号 | 跨大版本更新软件包源并替换核心组件 | 从22.03到24.03之类升级 | 中高 |
| 大版本升级 | 重装系统+数据迁移 | 新装系统后恢复应用和数据 | 大跨度升级,旧环境过于复杂 | 高(操作复杂但结果干净) |
| 降级 | dnf downgrade 包名 | 将指定软件包回退到旧版本 | 单包兼容性问题 | 低到中 |
| 降级 | dnf history undo 事务ID | 回滚一次完整的历史事务 | 一批更新导致的连锁故障 | 中 |
| 降级 | 快照回滚 / 备份恢复 | 恢复到升级前的系统状态 | 系统级严重故障 | 中(需提前做快照) |
选哪一种,核心看两点:升级跨度多大、系统里跑什么应用。跨度小的用dnf流操作,跨度大的建议重装或提前规划快照回滚点。下面我从准备工作开始讲,一步步来。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 动手前的准备:版本确认、备份与镜像源
2.1 确认当前系统版本与内核信息
别一上来就执行更新,先摸清楚自己的家底。登录服务器后,依次执行这几个命令:
bash复制# 查看OpenEuler版本
cat /etc/openEuler-release
# 查看内核版本
uname -r
# 查看dnf/yum版本
dnf --version
# 查看系统架构
arch
输出类似这样:
code复制openEuler 22.03 (LTS)
5.10.0-60.18.0.91.oe2203.x86_64
从输出能看出三层信息:当前是22.03 LTS版本、内核是5.10系列、架构是x86_64。搞清楚架构很重要,因为repo源的baseurl里会区分x86_64、aarch64。你现在记不住命令没关系,但这几条是后续所有操作的地基,多花两分钟跑一遍绝对值得。
补充一点,用cat /etc/openEuler-release是最直观的,但有些最小化安装的系统可能没有这个文件。这时候可以用:
bash复制cat /etc/os-release
这个文件在所有的systemd系统里都存在,里面的PRETTY_NAME字段能看到版本号。
2.2 备份策略:不想丢数据就把这一步做扎实
升级本质上是对系统关键文件的批量替换,任何意外都可能发生。我不止一次遇到过升级过程中断电、dnf事务中断,导致rpm数据库损坏的情况。所以备份这一节,你必须看。
文件级备份
如果是只更新少量软件包,做文件级备份就够了。最简单的方式是打包关键目录:
bash复制tar czvf /data/backup/etc_backup_$(date +%F).tar.gz /etc
tar czvf /data/backup/var_lib_rpm_backup_$(date +%F).tar.gz /var/lib/rpm
/var/lib/rpm目录里存的是rpm数据库,升级中断后它最容易损坏。把这个目录单独备一份,后面出问题恢复起来很省事。
系统级备份(重点推荐)
生产环境强烈建议做系统级快照。物理机上有条件就用LVM快照,虚拟机就用虚拟化平台的快照功能,云主机用云平台的自定义镜像/快照功能。
以LVM为例,假设根分区在vg_root/lv_root上,创建快照:
bash复制lvcreate -L 20G -s -n lv_root_snap /dev/vg_root/lv_root
这条命令创建了一个20GB的LVM快照,快照文件原始数据在升级前那一刻的状态。升级出了问题,直接合并快照就能回到过去:
bash复制lvconvert --merge /dev/vg_root/lv_root_snap
注意需要重启系统且根卷不能处于活动状态。虚拟机快照更简单,点一下按钮的事,但升级前一定要确保快照完成,别边升级边打快照。
业务数据备份
系统层面备份完了,别忘了业务数据。数据库、应用配置、上传文件这些,按各自的数据备份方案走一遍。别妄想系统回滚能把数据也回滚——快照回滚的是磁盘区块状态,业务数据在升级期间如果有新写入,回滚会丢失这部分变更。所以升级选业务低峰期,先停写或降载再做,这是真正的经验之谈。
2.3 配置OpenEuler国内镜像源
OpenEuler默认的repo源在国内访问速度有时候不太稳定,尤其高峰期下载大软件包包体时容易断。建议直接换成国内镜像源,比如清华、华为云、阿里云都有OpenEuler的镜像仓库。
以清华镜像源为例,将/etc/yum.repos.d/openEuler.repo的内容改为:
ini复制[openEuler]
name=openEuler
baseurl=https://mirrors.tuna.tsinghua.edu.cn/openeuler/openEuler-22.03-LTS/everything/x86_64/
enabled=1
gpgcheck=1
gpgkey=https://mirrors.tuna.tsinghua.edu.cn/openeuler/openEuler-22.03-LTS/everything/x86_64/RPM-GPG-KEY-openEuler
这里注意两点。第一,路径里的版本号openEuler-22.03-LTS要换成你自己的版本,everything是包含全部软件包的目录,还有EPOL、debuginfo等目录,按需配置。第二,架构目录x86_64对应你的系统架构,aarch64的机器改成aarch64。
改完执行:
bash复制dnf clean all
dnf makecache
如果makecache过程中报错,多半是baseurl写错了,或者GPGKEY地址不对,回去对照路径查。镜像源配置直接影响后续升级速度,甚至影响升级能否成功,别嫌麻烦。
3. 系统升级实操:从日常小更新到大版本迁移
3.1 日常小版本升级:dnf update的正确打开方式
小版本升级,指同一个大版本内部的软件包更新。比如你用的是OpenEuler 22.03 LTS,每隔一段时间官方会发布补丁更新,更新后版本号可能变成22.03 LTS SP3之类。
日常升级命令很简单:
bash复制# 刷新软件源缓存
dnf makecache
# 查看有哪些可更新包
dnf check-update
# 升级所有可更新包
dnf update -y
这里我把check-update单独拎出来,是因为很多人跳过了这一步直接update,结果被一大串更新列表砸懵了。check-update的显示结果里,你能看到有哪些包要更新、版本号多少、来自哪个源。先看一眼,心里有个底。
如果你不想全量更新,只想更新某个安全补丁或指定软件包:
bash复制# 只升级指定包
dnf update openssl -y
# 查看某个包是否有安全公告
dnf updateinfo list --security
日常升级中,我最想提醒的是:内核和驱动包更新后,务必安排重启。Linux内核是运行中的核心,不能像普通用户态进程那样热替换(kpatch这类的热补丁机制另说)。升级完内核不重启,表面看软件包版本已经更新,实际跑的还是旧内核,等于白升。
另外,dnf update和dnf upgrade在OpenEuler上都可以用,两者行为在绝大多数情况下一致。严格说dnf upgrade和dnf update都支持升级软件包,区别在于upgrade对过时包的淘汰处理更主动一些。日常使用不用纠结,习惯哪个用哪个。
3.2 大版本升级:从22.03 LTS到24.03 LTS的完整步骤
大版本升级比日常更新复杂一个量级,比如从openEuler 22.03 LTS升级到24.03 LTS。官方的正向推荐路径我建议严格按“22.03 → 24.03”来走,别想着从20.03或者更老的版本一步跳到24.03,跨越多个大版本时依赖冲突的概率极高。
大版本升级我常用的方式是通过修改releasever来更新源。
第一步:备份(参照2.2)
这一步务必做。大版本升级涉及到的软件包数量和核心组件替换幅度远超日常更新,没有快照和备份,出问题哭都没地方哭。
第二步:修改repo源指向新版本
bash复制# 备份原有repo文件
cp -a /etc/yum.repos.d/openEuler.repo /etc/yum.repos.d/openEuler.repo.bak
# 编辑repo文件,把版本路径改成新版本
vim /etc/yum.repos.d/openEuler.repo
把baseurl里的openEuler-22.03-LTS改成openEuler-24.03-LTS,其他路径结构保持一致。
第三步:执行升级
bash复制dnf clean all
dnf makecache
dnf upgrade --releasever=24.03-LTS -y
--releasever参数的作用是临时覆盖系统当前的$releasever变量值,让dnf以为当前系统就是24.03-LTS,然后按照新版本的依赖关系解析升级。
这条命令会下载并替换大量软件包,整个过程可能持续十几分钟到几小时,取决于网络和软件包数量。期间终端不要断开,建议用tmux或者screen挂着,避免SSH断开导致事务中断。
第四步:升级完成后处理
bash复制# 查看当前系统版本
cat /etc/openEuler-release
# 重建rpm数据库(如果升级过程有异常)
rpm --rebuilddb
# 检查系统关键服务状态
systemctl status sshd
systemctl status network
确认版本号切换成功,服务正常,然后安排重启——大版本升级后内核一定变了,不重启等于没升。
3.3 大版本升级的一个更稳选择:重装系统+迁移数据
上面这个方案,适合“原系统环境相对干净”的情况。但如果原系统装了非常多第三方软件,手动编译过很多东西,环境变量、库文件路径都是自定义的,那么大版本在线升级大概率会踩到依赖故障。
这时候我建议换个思路:找个窗口期,备份数据和配置,安装新版本OpenEuler系统,再把数据迁回去。虽然听起来“暴力”,但胜在结果可控、环境干净,没有历史包袱。
具体步骤概括就是:
- 备份/etc目录、业务数据、数据库数据。
- 在另一台机器或虚拟机上安装openEuler 24.03 LTS,或者直接用PXE批量安装。
- 恢复关键配置和数据。
迁移过程里要注意的点是“配置文件版本差异”。比如nginx、php-fpm的配置格式在新版本里可能有变更,直接从旧系统拷过来可能起不了服务。恢复前先diff对比一下新旧默认配置,再做针对性修改。
3.4 升级过程中的常见“坑位”提醒
升级过程中的坑,很多是重复的。我把高频踩坑点列一下:
坑一:升级中断,rpm数据库损坏
SSH断连、终端意外关闭、断电,都可能导致dnf事务中途终止。现象是后续执行dnf命令报错,提示rpmdb open failed。
处理方法:
bash复制# 删除rpm数据库锁文件
rm -f /var/lib/rpm/.rpm.lock
# 重建数据库
rpm --rebuilddb
如果这招不行,就得用备份的/var/lib/rpm目录(前面2.2让你备的那份)覆盖回去,再重建数据库。
坑二:升级后SSH连不上
可能原因太多了:sshd配置变更导致启动失败、防火墙默认策略变化、selinux上下文问题。这里给两个方向:
bash复制# 控制台登录(或通过虚拟化平台的VNC/Web Console进入系统)检查sshd状态
systemctl status sshd
journalctl -u sshd -n 50
# 如果sshd没问题,检查防火墙
firewall-cmd --state
firewall-cmd --list-all
注意,升级后旧防火墙规则可能失效,或者默认zone发生变化。OpenEuler的firewalld默认放行ssh吗?不一定,版本变了默认策略可能就变了。所以关机重启前,务必确认一下防火墙放行了22端口,别把自己锁外面。
坑三:第三方源冲突
很多人在OpenEuler上额外添加了EPEL、docker-ce、nginx等第三方repo。大版本升级时,这些第三方源如果没有对应新版本的路径,dnf解析依赖时会报404或者冲突。
处理思路:大版本升级前把第三方源全部禁用,只保留OpenEuler官方everything源,升级成功后再逐个启用第三方源并更新软件。
临时禁用第三方源:
bash复制dnf --disablerepo=epel --disablerepo=docker-ce upgrade --releasever=24.03-LTS -y
4. 系统降级实操:从单包回退到整体快照回滚
升级不是单向门,出了问题必须有退路。降级这个话题,很多教程一笔带过,但在我的运维实战里,降级次数和升级次数几乎一样多。
4.1 单包降级:dnf downgrade
日常碰到最多的情况是:升级某个软件包后,业务报错,检查后发现是新版本的行为变更不兼容。这是最典型的“单包降级”场景。
先把包降级回去:
bash复制# 查看当前版本和可用旧版本
dnf list --showduplicates nginx
# 降级到指定版本
dnf downgrade nginx-1.20.1-3.oe2203
也可以不写完整版本号:
bash复制dnf downgrade nginx
dnf会在repo源里找比当前版本旧的包来做降级。这里有个前提:你的repo源里保留了旧版本的rpm包。官方源一般会保留历史版本,但有时候某些包在源里已经被清理了,降级时提示找不到版本。这时候要么自己下载旧版本rpm离线安装,要么从备份的rpm包目录里装回来。
顺便说一个从热搜词里看到的场景:JDK降级到17。如果你升级后系统里装的是JDK 21,想降回17,同样是dnf操作:
bash复制dnf downgrade java-17-openjdk -y
注意OpenEuler的openjdk包名会带release版本后缀,如果系统里没有配置JDK 17的repo源,dnf可能找不到旧包。这种情况我一般直接下载RPM离线安装,或者更简单——用二进制tar包方式部署JDK 17,配置好JAVA_HOME和PATH,跟系统包的冲突反而更小。
4.2 事务级回滚:dnf history undo
如果你一次性升级了几十个包,现在出了故障,只想回退到升级前的状态,一个个降级太不现实。dnf自带的历史事务机制就是干这个的。
查看历史事务:
bash复制dnf history
输出类似:
code复制ID | 操作命令 | 日期和时间 | 操作数 | 动作
12 | upgrade nginx | 2025-01-05 10:22 | 3 | Upgrade
11 | update -y | 2025-01-03 14:10 | 87 | Upgrade
10 | install docker-ce | 2024-12-20 09:30 | 5 | Install
要撤销ID为11的事务,也就是“那批87个包的更新”,执行:
bash复制dnf history undo 11
dnf会解析该事务的变更列表,反向执行降级操作,把包恢复到该事务开始前的版本。这就是“事务级回滚”,比手动一个个降级高效得多。
实际使用中有几个注意点:
- dnf history undo依赖rpm数据库和repo源的可用性。如果升级过程中rpm数据库已经损坏,需要先修复再执行。
- 如果事务涉及“安装新包”(某次事务里新增了依赖包),undo会卸载这些新增包,但不会清理配置文件和数据文件,需要手动处理。
- undo之后务必重启服务或测试应用,因为很多包的配置可能已经被新版本改动过,即使二进制版本回退了,配置文件可能还是新的格式。
4.3 整体回滚:快照恢复操作实录
当系统升级后故障范围太大——内核引导失败、网络服务起不来、磁盘挂载异常——单包降级和事务回滚都不好使。这时候能救你的,就是升级前做的快照或备份。
虚拟机快照恢复的操作以虚拟化平台为准,云平台则是用自定义镜像/云盘回滚,我这里重点说LVM快照回滚。
恢复前确认快照现状:
bash复制lvs
输出里你应该看到lv_root_snap这个快照卷。合并回滚:
bash复制lvconvert --merge /dev/vg_root/lv_root_snap
然后重启系统:
bash复制reboot
重启过程中,LVM会执行快照合并,系统回到快照创建时的状态。注意合并操作会把快照卷“溶解”掉,合并完成后lv_root_snap就不存在了,需要重新创建。
如果快照失效或者从没做过快照,退而求其次的办法是用之前tar备份的/etc和/var/lib/rpm,配合系统iso启动盘进入rescue模式做恢复。这个方案能救回配置和包管理数据库,但坏掉的内核和系统文件还是得重新安装,效果不如快照恢复彻底。
所以我的态度很明确:操作前没做快照的系统升级,就像没系安全带的过山车——刺激是刺激,出事就是大事。
4.4 内核版本回退:解决安装新内核后系统异常
内核升级后启动卡死、驱动不兼容、硬件识别异常,这类问题在OpenEuler上不算罕见。回退内核的思路是:用GRUB选择旧内核启动,然后卸载新内核。
第一步:查看当前系统里有哪些内核
bash复制rpm -qa | grep kernel
第二步:确认GRUB菜单里有哪些内核条目
bash复制awk -F\' '$1=="menuentry " {print i++ " : " $2}' /etc/grub2-efi.cfg
第三步:设置默认启动旧内核
bash复制grub2-set-default "openEuler (5.10.0-60.18.0.91.oe2203) 22.03 (LTS)"
grub2-mkconfig -o /boot/grub2/grub.cfg
第四步:重启验证
bash复制reboot
重启后执行uname -r确认内核版本。确认稳定之后,可以把新内核卸载掉:
bash复制dnf remove kernel-新版本号
这块重点提醒:GRUB的配置文件在UEFI引导和BIOS引导的机器上路径不同。UEFI机器是/boot/efi/EFI/openEuler/grub.cfg,BIOS机器是/boot/grub2/grub.cfg。生成配置时根据实际机器类型选择参数,我上面给的是BIOS兼容写法,UEFI机器把-o参数改成对应路径。
5. 常见问题与排查技巧实录
5.1 镜像源相关问题的排查思路
问题1:dnf makecache报错404
典型报错类似“Error: Failed to download metadata for repo 'openEuler'”。原因基本是repo源路径里没有对应目录。检查路径和版本号是否匹配,特别是大版本升级后repo路径忘了改回新版本的路径。
问题2:GPG key验证失败
报错提示“Public key for xxx.rpm is not installed”或“GPG check FAILED”。原因是repo配置里的gpgkey地址不对,或者系统缺少对应密钥。
处理方式:
bash复制# 手动导入OpenEuler官方GPG key
rpm --import https://mirrors.tuna.tsinghua.edu.cn/openeuler/openEuler-22.03-LTS/everything/x86_64/RPM-GPG-KEY-openEuler
如果源路径有更新,把版本号和架构对应替换即可。
问题3:国内访问官方源慢
直接换镜像源,前面2.3写的就是基础操作。还有一个小技巧是配置dnf的并发和超时参数:
bash复制vim /etc/dnf/dnf.conf
ini复制[main]
gpgcheck=1
installonly_limit=3
clean_requirements_on_remove=True
max_parallel_downloads=10
max_parallel_downloads=10表示最多10个并发下载,能明显提升多包更新时的下载速度。
5.2 系统升级后常见服务异常
sshd启动失败
大版本升级后sshd起不来,先看配置:
bash复制sshd -t
语法检查会直接提示错误行。多数情况下是新版本sshd对某些旧配置项不再支持,比如PermitRootLogin的取值变了、某些弃用参数被移除等。对比备份的/etc/ssh/sshd_config,删掉不支持的配置项。
网络服务起不来
升级后网卡改名是常见坑。新版本默认使用一致的网络设备命名规则(比如ens33、enp0s3),但系统里/etc/sysconfig/network-scripts/ifcfg-eth0还是旧名字。这种情况下网络服务启动时会找不到网卡。
处理方式:
bash复制# 查看当前生效网卡名
ip link show
# 查看当前网络配置文件名
ls /etc/sysconfig/network-scripts/
如果ifcfg文件名和实际网卡名不一致,把配置文件改名或新建对应文件,重点保证DEVICE=和NAME=字段与网卡实际名称一致。
防火墙默认策略变化
升级前一切正常,升级后某些端口访问不了了,第一反应别去查业务程序,先看防火墙:
bash复制firewall-cmd --state
firewall-cmd --list-all
新版firewalld可能reset了之前的规则。如果你确认当前网络环境安全,可以直接放行需要端口,或者干脆在公网隔离的环境下停用防火墙(这个要结合公司安全策略来,别自己拍板)。
5.3 登录与访问类问题
问题:升级后SSH密码登录失败
有些OpenEuler版本默认禁用了root的密码登录,只允许密钥登录。升级把sshd_config重置后,原来允许密码登录的配置被覆盖了。
检查/etc/ssh/sshd_config里的PermitRootLogin和PasswordAuthentication选项,按需开启:
ini复制PermitRootLogin yes
PasswordAuthentication yes
改完执行systemctl restart sshd。这里要特别提醒,操作之前确保自己有控制台访问权限,否则一旦改错连不上就麻烦了。
问题:开机直接进emergency mode
升级后系统启动进入emergency模式,一般是/etc/fstab某一行挂载的设备UUID不对。输入root密码进入维护模式后,执行:
bash复制mount -a
看哪个挂载点报错,然后检查/etc/fstab里对应行的UUID或设备路径是否还正确。升级可能导致磁盘设备顺序变化,UUID是最稳妥的定位方式。
5.4 关于“系统密码忘了”和“初始密码”的补充
很多刚接触OpenEuler的朋友,装完系统登录不上就懵了。这里统一说下:OpenEuler在安装过程中设置的root密码就是你的登录密码,没有“万能初始密码”。如果你忘了密码,在GRUB引导界面选择内核条目后按e进入编辑,在linux16或linux开头的行尾加上“rd.break”参数,然后按Ctrl+x启动,会进入initramfs的紧急shell。依次执行:
bash复制mount -o remount,rw /sysroot
chroot /sysroot
passwd root
touch /.autorelabel
exit
reboot
这套操作能重置root密码,但生产环境慎用,因为需要物理或虚拟化控制台的访问权限。
6. 最后分享一点实操心得
写了这么多,我把自己干这行的经验总结成一句话:升级降级的核心不是“操作命令多牛逼”,而是“回滚预案多完善”。我做系统运维这些年,见过太多次线上事故,起因都是某人随手执行了一个update,没有备份、没有快照、不知道能回滚到哪。那些看起来轻松的“老司机”,不是不会翻车,而是翻车前已经系好安全带了。
还有一个小技巧,忍不住分享出来:大版本升级前,把当前所有软件包的清单导出留底。做法是执行dnf list installed > /data/backup/installed_$(date +%F).txt。升级后如果怀疑哪个包版本不对,直接diff这份清单,一目了然。这个小动作成本几乎为零,排查问题时却非常管用。
再提醒一次:OpenEuler的repo源尽量配置国内镜像,国内下载速度和稳定性都更好。配置好后记得dnf clean all && dnf makecache一次,确保源路径正确再开始升级。
升级降级这套东西,多操作几次就熟练了。但每次操作前,把“能不能回滚”这个问题想清楚,才是真正的老手思维。
