
之前的痛还记得吗改了Model加字段运行报table posts has no column named xxx——因为create_all()只建新表、不改旧表。今天给数据库装上git表结构变更进入版本管理可升级、可回滚、可追溯。本篇产出Alembic接管早报站的表结构两个真实迁移的生成与执行一次回滚演示。含代码约80行。 太长不看版给想快速上手的你项目信息一句话说明本篇目标用Alembic管理数据库表结构变更代码行数~80行迁移脚本配置依赖alembic已装SQLAlchemy核心功能autogenerate迁移 升级 回滚跑起来的命令alembic revision --autogenerate -m 描述→alembic upgrade head核心知识点迁移脚本数据库的commit、autogenerate原理、手写迁移做完你能得到数据库有了git改表结构不再删库重建核心认知迁移脚本只增不改。已经执行过的迁移脚本等于历史——改历史等于篡改Alembic会用版本号对不上来抗议第八节①。一、心智模型迁移脚本 数据库的commitGit是代码的安全网。Alembic把同样的安全网装到数据库上Git代码Alembic表结构每次改动一个commit每次变更一个迁移脚本git log看历史alembic history看历史HEAD指针指向最新提交alembic_version表里的版本号就是HEADgit revert回退alembic downgrade回退分支合并alembic merge多人协作冲突时用迁移脚本只增不改——改历史等于篡改。二、第0步初始化与接线pipinstallalembic alembic init migrations生成alembic.inimigrations/目录。接线两步让Alembic认识你的模型和数据库 接线①让它知道表结构长什么样migrations/env.py里把target_metadata None改为importosfromcore.modelsimportBase configcontext.config# 密钥军规连接串走环境变量不写死在配置里config.set_main_option(sqlalchemy.url,os.environ.get(DATABASE_URL,postgresqlpsycopg://postgres:你的密码localhost:5432/daily))...target_metadataBase.metadata 接线②让它知道连哪个库上面的sqlalchemy.url已完成。 注意postgresqlpsycopg://SQLAlchemy需要指明驱动。 macOS设置环境变量exportDATABASE_URLpostgresqlpsycopg://postgres:你的密码localhost:5432/daily# 永久生效写进~/.zshrc三、第1步第一个迁移——把存量表纳入管理之前的表是create_all手工建的Alembic还不认识它们。先autogenerate一次对齐alembic revision--autogenerate-minitial modelsalembic upgradehead autogenerate的原理对比models.py你声明的结构与数据库实际的结构把差异写成迁移脚本。打开生成的脚本看一眼——users/rss_sources/favorites三张缺的表被补上了articles因为已存在而被跳过。四、第2步变更迭代——加字段的全流程现在体验真正的高潮给模型加两个字段。① 改models.pyclassUser(Base):__tablename__usersid:Mapped[int]mapped_column(primary_keyTrue)username:Mapped[str]mapped_column(uniqueTrue)email:Mapped[str|None]mapped_column(defaultNone)# 新增...classArticle(Base):...view_count:Mapped[int]mapped_column(server_default0)# 新增Tips: 注意view_count字段设置的是server_default0如果只设置default0这是Python层面插入新行进行的设置不会进入DDL如果数据库有字段使用alembic进行字段的新增会导致字段非空而出现的错误。而设置server_default会写进DDL不会出现错误。② 生成第二个迁移alembic revision--autogenerate-madd user email and article view_count打开生成的脚本核对——op.add_column两条正是差异所在defupgrade()-None:op.add_column(users,sa.Column(email,sa.String(),nullableTrue))op.add_column(articles,sa.Column(view_count,sa.Integer(),server_default0,nullableFalse))defdowngrade()-None:op.drop_column(articles,view_count)op.drop_column(users,email)③ 执行alembic upgradeheaddockerexec-itpg-daily psql-Upostgres-ddaily-c\d articles# view_count列已经在那了④ 回滚演示诚实版alembic downgrade-1字段消失。再upgrade head回来——但注意回滚再升级字段里的数据不会凭空回来。Alembic管结构不自动管数据。这就是为什么重要变更前要备份数据库。五、第3步手写迁移——autogenerate管不了的事autogenerate只会对比表结构。两类场景需要手写迁移 场景一改列名autogenerate会把它理解成删旧列 加新列——数据全丢。安全做法是手写迁移三步安全舞defupgrade()-None:# ① 加新列op.add_column(articles,sa.Column(author,sa.String(80)))# ② 把旧列数据搬过去op.execute(UPDATE articles SET author title WHERE author IS NULL)# ③ 确认无误后可分两次部署再删旧列op.drop_column(articles,title_copy) 场景二批量数据修正比如把所有空摘要填默认值op.execute(UPDATE articles SET summary 暂无摘要 WHERE summary ) 纪律手写迁移必须先在本地/测试库跑一遍确认无误再上生产——迁移脚本也是代码也要走先测再上。六、命令速查贴墙系列命令作用alembic init migrations初始化一次性alembic revision --autogenerate -m 描述对比模型生成迁移alembic upgrade head升级到最新alembic upgrade 1/downgrade -1前进一步 / 回退一步alembic history/alembic current看历史 / 看当前版本alembic heads多人协作出现分叉时看heads七、验收清单1. alembic upgradehead→ 迁移成功执行2. psql\d articles → view_count列已存在3. alembichistory→ 看到两条迁移记录4. alembic downgrade-1→ 字段消失upgradehead→ 字段回归但数据不回来5. alembic current → 显示当前版本号6. 全程无报错后提交Gitgitadd.gitcommit-mAlembic接管表结构两个迁移 回滚演示八、常见报错这6个Alembic的标配重点①FAILED: Cant locate revision identified by a1b2c3 原因数据库的alembic_version里记录的版本号在migrations/目录里找不到——删过旧迁移、或换了分支。✅ 解法alembichistory# 核对历史确需重置就清空alembic_version表重新stamp谨慎。②Target database is not up to date 原因有新迁移脚本还没执行。✅ 解法alembic upgrade head。 这也是部署流程的一部分上线先upgradeservice前置命令。③ autogenerate生成了空迁移 原因env.py没接target_metadata——Alembic不知道你的模型。✅ 解法回到第2节接好线。生成空迁移时先怀疑接线再怀疑模型。④ 改列名被autogenerate拆成加列 删列 原因autogenerate只对比结构不读你的心思。✅ 解法人工核对生成的脚本改成第5节的三步安全舞。autogenerate是草稿人工核对才是定稿。⑤ 多人协作出现两个head 原因你和同事各生成了一个迁移历史分叉了。✅ 解法alembic heads# 看到两个头alembic merge heads-mmerge# 生成合并迁移⑥ 生产库upgrade卡住 / 大表加列很慢 原因大表加列会锁表不同数据库行为不同。✅ 解法低峰期执行表特别大时了解数据库的在线加列方案。迁移脚本上生产前永远先在测试库跑一遍。九、课后练习#练习难度提示1加列实战给Article加tags列autogenerate upgradepsql验证⭐⭐Mapped[str] mapped_column(default)2回滚演练downgrade -1再upgrade head观察psql里列的消失与回归⭐⭐体会结构回来、数据不回来3数据迁移给favorites表加note列并写一条op.execute给旧记录回填⭐⭐⭐手写迁移4选做CI接入GitHub Actions里跑alembic upgrade head pytest⭐⭐⭐⭐迁移和测试一起进流水线 配套代码迁移脚本与env.py配置已上传Gitpython_daily/【gitee仓库地址】