Shell脚本实现条件刷库和幂等升级
直接改 SQL 加条件判断太麻烦,用 Shell 脚本先查库判断,满足条件再执行 SQL 更灵活。但原始代码有坑:明文密码、临时文件不清理、不幂等。安全做法是环境变量传密码、加事务、写日志、判断执行结果。
Shell 脚本实现条件刷库和幂等升级
在系统运维和自动化部署中,经常需要条件式地执行数据库操作,同时要保证操作的幂等性(可以安全地重复执行而不会出现异常)。
本文通过实战案例,展示如何使用 Shell 脚本实现这一需求。
什么是幂等升级
幂等升级指的是:无论执行多少次,最终的结果都是相同的。
例如:
- 第一次执行:版本从 1.0 升级到 2.0(执行所有变更)
- 第二次执行:检测到已是 2.0,直接跳过升级逻辑
- 第三次执行:同样检测到已是 2.0,跳过升级
这样即使脚本被意外多次执行,系统状态也不会出现混乱。
基本思路
- 检查当前状态 - 查询数据库记录的当前版本或已执行的操作
- 条件判断 - 根据状态决定是否需要执行升级
- 执行变更 - 如果需要,执行 SQL 更新
- 记录状态 - 更新版本号或执行标记
脚本框架
#!/bin/bash
# 配置项
DB_HOST="localhost"
DB_USER="root"
DB_PASS="password"
DB_NAME="myapp"
CURRENT_VERSION="2.0"
# 查询当前版本
LATEST_VERSION=$(mysql -h $DB_HOST -u $DB_USER -p$DB_PASS -D $DB_NAME -N -e "SELECT version FROM migration_version ORDER BY id DESC LIMIT 1;")
# 条件判断
if [ "$LATEST_VERSION" = "$CURRENT_VERSION" ]; then
echo "已是最新版本 $CURRENT_VERSION,跳过升级"
exit 0
fi
echo "准备从 $LATEST_VERSION 升级到 $CURRENT_VERSION"
# 执行升级 SQL
mysql -h $DB_HOST -u $DB_USER -p$DB_PASS -D $DB_NAME << EOF
ALTER TABLE users ADD COLUMN updated_at DATETIME DEFAULT CURRENT_TIMESTAMP;
INSERT INTO migration_version (version, executed_at) VALUES ('$CURRENT_VERSION', NOW());
EOF
if [ $? -eq 0 ]; then
echo "升级成功"
else
echo "升级失败"
exit 1
fi
关键技术点
1. 查询条件
使用 mysql 命令行工具的 -N 和 -e 参数实现无格式查询
2. 版本管理表
建议维护一个版本管理表,记录每次升级
3. 错误处理
通过检查 $? 获取上一条命令的退出码
4. 锁机制
防止多个脚本同时执行,使用文件锁
小结
- 条件刷库的核心是先检查再执行
- 使用版本管理表记录升级历史
- 通过幂等设计确保脚本可以安全重复执行
- 加入错误处理和锁机制提高脚本的健壮性
