2

排错:Drizzle ORM 在多分支开发场景下,发现产品环境缺失 migrate 记录

 9 months ago
source link: https://blog.dteam.top/posts/2023-09/drizzle-lost-migrate.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

排错:Drizzle ORM 在多分支开发场景下,发现产品环境缺失 migrate 记录

冯宇 Posted at — Sep 14, 2023 阅读 37

我们在多分支开发场景下,发现在不同分支下生成 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 值来判断是否执行。

这样就会导致这样的问题:

  1. hotfix 分支先发布,也就先执行了 0004_even_cyclops.sql,并且记录了 hash 值
  2. 但是主线分支的 0004_bumpy_katie_power.sql,实际生成在前,但是并没有发布到发布分支上执行,也就没有记录 hash 值
  3. 最终由于 drizzle 的算法 —— 只会比对最后一条记录的 hash 值,所以 0004_bumpy_katie_power.sql 始终得不到执行

最终,我们通过手动修复 migrate 的方案解决这个问题。

本地用空库重新生成 drizzle.__drizzle_migrations 表的记录,将这个表记录同步到产品环境中。

如果产品环境数据库可以在本地连接 (例如通过 ssh tunnel 等方式或直连),可以直接通过 drizzle-kit push:pg 同步 schema 到产品环境。否则只能在产品环境手工执行缺失的 migrate 脚本。

关于这个问题,我已经给官方提交了 issue,希望后续可以解决: [FEATURE]:Support multiple branch development ?

觉得有帮助的话,不妨考虑购买付费文章来支持我们 🙂 :

付费文章

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK