我们在多分支开发场景下,发现在不同分支下生成 migrate 文件之后,由于发布周期不同会导致有些脚本得不到执行。
例如在 hotfix
分支下创建了一个 0004_even_cyclops.sql
脚本,并且紧急合并到产品环境发布,后在主线分支上创建另一个 migrate 脚本 0004_bumpy_katie_power.sql
,生成的 drizzle/
目录如下:
drizzle
├── 0000_calm_talos.sql
├── 0001_reflective_malice.sql
├── 0002_careful_northstar.sql
├── 0003_blushing_martin_li.sql
├── 0004_bumpy_katie_power.sql
├── 0004_even_cyclops.sql
├── 0006_luxuriant_bloodscream.sql
└── meta
├── 0000_snapshot.json
├── 0001_snapshot.json
├── 0002_snapshot.json
├── 0003_snapshot.json
├── 0004_snapshot.json
├── 0006_snapshot.json
└── _journal.json
则最终合并分支之后再次发布到产品环境,发现 0004_bumpy_katie_power.sql
始终得不到执行。
对比了下产品环境数据库和本地数据库的 drizzle.__drizzle_migrations
表记录,也可以验证这一点:
# select * from drizzle.__drizzle_migrations;
id | hash | created_at
----+------------------------------------------------------------------+---------------
1 | 73e00ad97a659f73bd51194eeee283d667f14d6b0b9de5b4d5490f3619bf14e4 | 1687266312031
2 | 7bdb1311c466d102f24d535d7734813d9a0facc72b68d306f1b2c3e32cba3842 | 1688633592510
3 | 31948976f9c8d9575e60e1f8b26f974ca368692cbffd03b9d4a5f55467cbb67a | 1690341446264
4 | d23bbcfbdd0079d83c75104679690e7c4e119bbb0fbbc830dc99f7fa73510964 | 1692003212319
5 | cfc87892e506ede48fba2481456cf59a43d4eec8973a28e72376b1d627d93944 | 1692870925275 #<==== 产品环境缺失这条记录
6 | bdd1b7528769c2019e1e7359d10f82dca0e3d8e90f6858b197cb3a8c826a42ef | 1693282336886
7 | 82ed06acbb97c6ff42db7e8abda50a00e1ed914249ec3ca3adf6d08c4f3fdb2c | 1693794387936
(7 行记录)
发现产品环境确实少了中间一条 migrate hash 记录。
通过打开 drizzle 的日志,我们发现了端倪:
// 打开 drizzle 的日志
const db = drizzle(sql, { logger: true });
migrate(db, { migrationsFolder: "drizzle" }).then(() => sql.end());
执行 migrate 的时候输出如下:
Query: CREATE SCHEMA IF NOT EXISTS "drizzle"
Query:
CREATE TABLE IF NOT EXISTS "drizzle"."__drizzle_migrations" (
id SERIAL PRIMARY KEY,
hash text NOT NULL,
created_at bigint
)
Query: select id, hash, created_at from "drizzle"."__drizzle_migrations" order by created_at desc limit 1
Query: begin
Query: commit
我们发现 drizzle orm 在执行 migrate 的时候,并不是通过比对每一个 migrate 脚本的 hash 值来判断是否执行,而是通过查询 __drizzle_migrations
表的最后一条记录的 hash 值来判断是否执行。
这样就会导致这样的问题:
hotfix
分支先发布,也就先执行了 0004_even_cyclops.sql
,并且记录了 hash 值0004_bumpy_katie_power.sql
,实际生成在前,但是并没有发布到发布分支上执行,也就没有记录 hash 值0004_bumpy_katie_power.sql
始终得不到执行最终,我们通过手动修复 migrate 的方案解决这个问题。
本地用空库重新生成 drizzle.__drizzle_migrations
表的记录,将这个表记录同步到产品环境中。
如果产品环境数据库可以在本地连接 (例如通过 ssh tunnel 等方式或直连),可以直接通过 drizzle-kit push:pg
同步 schema 到产品环境。否则只能在产品环境手工执行缺失的 migrate 脚本。
关于这个问题,我已经给官方提交了 issue,希望后续可以解决: [FEATURE]:Support multiple branch development ?
觉得有帮助的话,不妨考虑购买付费文章来支持我们 🙂 :
付费文章