本文目录导读:

“回滚脚本”的写法取决于你具体使用的技术栈和场景(数据库、应用部署、Kubernetes 等),下面分最常见的数据库回滚和应用版本回滚两种情况说明。
数据库回滚脚本(最常用)
通常采用“版本化迁移”工具(如 Flyway、Liquibase、MyBatis Migrations),但纯 SQL 脚本也常用。
单次变更的回滚(纯 SQL 示例)
假设你执行了一个 V1.1__add_user_email.sql 的升级脚本:
-- 升级(正向) ALTER TABLE users ADD COLUMN email VARCHAR(255) NOT NULL DEFAULT ''; CREATE INDEX idx_user_email ON users(email);
对应的回滚脚本(通常命名为 V1.1__add_user_email__rollback.sql):
-- 回滚(逆向) DROP INDEX IF EXISTS idx_user_email; ALTER TABLE users DROP COLUMN IF EXISTS email;
Flyway / Liquibase 自动化回滚
- Flyway:
flyway undo命令,需要 Flyway Teams 版(付费),或手动执行回滚 SQL。 - Liquibase: 支持
rollback标签,在 changelog 中定义回滚语句:<changeSet id="1" author="me"> <createTable tableName="test"> <column name="id" type="int"/> </createTable> <rollback> DROP TABLE test; </rollback> </changeSet>
手动版本控制(推荐方式)
建立一个 migrations 目录,每个变更包含正向和回滚两个文件:
migrations/
├── V1.0__init.sql
├── V1.0__init__rollback.sql
├── V1.1__add_email.sql
├── V1.1__add_email__rollback.sql
执行时记录当前版本,回滚时找到对应版本的文件执行。
应用代码回滚脚本(部署回滚)
基于 Git 的回滚脚本(shell)
适用于代码级别回滚:
#!/bin/bash
# rollback.sh - 回滚到上一个版本
set -e
APP_DIR="/opt/myapp"
BACKUP_DIR="/opt/deploys/backups"
# 1. 停止当前服务
systemctl stop myapp.service
# 2. 备份当前版本(可选)
cp -r "$APP_DIR" "${BACKUP_DIR}/$(date +%Y%m%d_%H%M%S)_before_rollback"
# 3. Git 回滚
cd "$APP_DIR"
git checkout --force HEAD~1 # 回退到上一个提交
# 或者指定 tag: git checkout v1.0.5
# 4. 重新构建(如果需要)
npm install && npm run build
# 或 mvn clean package
# 5. 重启服务
systemctl start myapp.service
echo "回滚完成,当前版本: $(git log --oneline -1)"
Docker 镜像版本回滚脚本
假设使用 myapp:2.0.1 回滚到 myapp:2.0.0:
#!/bin/bash
# docker_rollback.sh
OLD_TAG="$1" # 2.0.0
CONTAINER_NAME="myapp"
# 拉取旧镜像
docker pull myapp:${OLD_TAG}
# 停止并删除当前容器
docker stop ${CONTAINER_NAME}
docker rm ${CONTAINER_NAME}
# 使用旧镜像启动
docker run -d --name ${CONTAINER_NAME} \
-p 8080:8080 \
-v /opt/config:/config \
myapp:${OLD_TAG}
echo "应用已回滚至版本: ${OLD_TAG}"
Kubernetes 回滚脚本
使用 kubectl rollout undo(最简单)
#!/bin/bash
# k8s_rollback.sh
DEPLOYMENT_NAME="myapp-deployment"
NAMESPACE="default"
# 回滚到上一个版本
kubectl rollout undo deployment/${DEPLOYMENT_NAME} -n ${NAMESPACE}
# 或回滚到指定版本
# kubectl rollout undo deployment/${DEPLOYMENT_NAME} --to-revision=3
# 查看回滚状态
kubectl rollout status deployment/${DEPLOYMENT_NAME} -n ${NAMESPACE}
Helm 回滚
#!/bin/bash helm rollback myapp 1 # 回滚到 revision 1 # 或回滚到上一个版本 # helm rollback myapp
通用回滚脚本框架(推荐结构化)
将升级和回滚做成可逆操作对:
#!/bin/bash
# migrate.sh - 通用迁移脚本
ACTION=${1:-upgrade} # upgrade / rollback
case $ACTION in
upgrade)
echo "=== 执行升级 ==="
# 步骤1: 备份
cp config.yml config.yml.bak
# 步骤2: 修改
sed -i 's/version: 1/version: 2/' config.yml
# 步骤3: 执行DB变更
mysql -e "ALTER TABLE ..."
;;
rollback)
echo "=== 执行回滚 ==="
# 步骤1: 还原备份
cp config.yml.bak config.yml
# 步骤2: 逆向DB变更
mysql -e "ALTER TABLE ... DROP COLUMN ..."
# 步骤3: 清理备份
rm config.yml.bak
;;
esac
关键原则
| 原则 | 说明 |
|---|---|
| 幂等性 | 回滚脚本可多次执行而不出错(使用 IF EXISTS / DROP IF EXISTS) |
| 版本追踪 | 记录当前版本号,避免重复回滚 |
| 备份优先 | 任何变更前先备份数据或配置 |
| 原子性 | 脚本失败时要能回退到一致状态(考虑事务) |
| 测试 | 在预发环境验证回滚脚本再上生产 |
一个具体的建议:不用自己造轮子,直接用成熟的工具:
- 数据库:Flyway / Liquibase
- 应用部署:Ci/CD 工具(Jenkins/GitLab CI)配合 Git tag 回滚
- 容器/K8s:Helm / ArgoCD(支持自动回滚)
这样回滚脚本(或命令)通常就只有一行,由工具管理版本。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播