回滚脚本怎么写?

wen 实用脚本 46

本文目录导读:

回滚脚本怎么写?

  1. 数据库回滚脚本(最常用)
  2. 应用代码回滚脚本(部署回滚)
  3. Kubernetes 回滚脚本
  4. 通用回滚脚本框架(推荐结构化)
  5. 关键原则

“回滚脚本”的写法取决于你具体使用的技术栈和场景(数据库、应用部署、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(支持自动回滚)

这样回滚脚本(或命令)通常就只有一行,由工具管理版本。

抱歉,评论功能暂时关闭!