1、升级脚本概述
各位同学好,我是老张。今天咱们开始聊升级脚本。说实话,这玩意儿在运维开发里看着不起眼,但坑是真不少。我见过太多项目因为升级脚本写得烂,上线出问题,最后回滚回得鸡飞狗跳。
先问个问题:你写代码的时候,有没有想过——代码写完了,怎么让它跑到线上?怎么保证旧版本的数据不丢?怎么让用户无感知?
嗯,这就是升级脚本要干的事。
1.1 什么是升级脚本
升级脚本,说白了就是一段自动化程序。它负责把系统从旧版本平滑迁移到新版本。不是简单的「把新代码部署上去」,而是要考虑数据、配置、依赖、兼容性等一系列问题。
我个人习惯把升级脚本分成三类:
| 类型 | 典型操作 | 风险等级 |
|---|---|---|
| 数据库迁移 | 加字段、改索引、数据转换 | 高 |
| 配置文件更新 | 新增配置项、调整参数 | 中 |
| 应用代码热更新 | 替换类文件、重启服务 | 中高 |
你看,数据库迁移风险最高。为什么?因为数据是命根子。我曾经在项目里遇到过,一个 ALTER TABLE 跑了半小时,结果锁表了,线上服务直接挂了半小时。嗯,从那以后我再也不敢在生产环境直接跑 DDL 了。
1.2 升级脚本在项目中的作用
你想想看,一个项目从开发到上线,要经历多少次版本迭代?每次迭代都可能涉及数据库结构变化、配置调整、代码逻辑更新。如果全靠人工操作,迟早会出问题。
升级脚本的核心作用有三个:
- 自动化:把重复性操作写成脚本,一键执行,减少人为失误
- 可追溯:每次升级都有记录,出了问题能快速定位
- 可回滚:升级失败能快速恢复到上一个稳定版本
我记得有一次,一个同事手动执行 SQL 语句,结果少写了一个 WHERE 条件,把整个表的数据都更新错了。要是当时有升级脚本,这种低级错误完全可以避免。
1.3 常见的升级场景
咱们来看看实际项目中,升级脚本最常见的三种场景。
1.3.1 数据库迁移
这是最频繁、也最容易出问题的场景。比如:
- 新增一个字段,用来存储用户手机号
- 修改字段类型,从
VARCHAR(50)改成VARCHAR(100) - 添加索引,优化查询性能
- 数据清洗,把旧数据转换成新格式
举个例子,假设我们要给用户表加一个 phone 字段:
-- 正向脚本:upgrade_v1.2.0.sql
ALTER TABLE `users` ADD COLUMN `phone` VARCHAR(20) DEFAULT '' COMMENT '手机号';
CREATE INDEX `idx_phone` ON `users`(`phone`);
-- 回滚脚本:rollback_v1.2.0.sql
DROP INDEX `idx_phone` ON `users`;
ALTER TABLE `users` DROP COLUMN `phone`;
你看,正向和回滚脚本成对出现。这是基本要求。
1.3.2 配置文件更新
配置文件更新看起来简单,但坑也不少。比如:
- 新增配置项,需要给默认值
- 废弃配置项,需要清理
- 配置格式变化,需要做兼容
我建议用模板引擎来处理配置文件。比如用 Jinja2 或者 Go template,把配置项和模板分开。升级脚本只负责更新配置值,不直接修改配置文件内容。
1.3.3 应用代码热更新
热更新,就是在不重启服务的情况下,替换部分代码逻辑。常见于:
- Java 应用的类文件替换
- Python 模块的热加载
- 前端资源的增量更新
说实话,热更新风险很高。我一般只在紧急修复 bug 时才用。常规版本迭代,还是建议走完整的发布流程。
热更新的核心步骤:
- 备份旧代码文件
- 上传新代码文件
- 触发热加载机制
- 验证新代码是否生效
- 如果失败,自动回滚到备份
你想想看,如果热更新过程中出了问题,没有自动回滚机制,那线上服务就处于一个「半死不活」的状态。用户访问可能报错,数据可能写乱。所以,热更新脚本一定要有健康检查。
这张图把升级脚本的知识体系串起来了。你看,不管是数据库迁移、配置文件更新还是代码热更新,最终都要落到三个核心要求上:回滚脚本、版本管理、健康检查。缺一个,都不算完整的升级方案。
好了,这一章就聊这么多。记住一句话:升级脚本不是锦上添花,而是项目稳定运行的基石。后面咱们会深入每个场景,讲具体的语法和调试技巧。