postgresql - 基于函数的数据库的非线性开发与版本控制

标签 postgresql version-control liquibase flyway

我正在开发一个后端高度基于数据库函数的 Web 应用程序,即大部分业务逻辑发生在 Postgres PLV8 函数中。 (无论好坏,我们都坚持使用这种结构。)

目前,我们正在使用Flyway来管理功能代码。如果一切都保持线性,那效果很好。但是,想象一下以下情况:

给定这样一个函数:

CREATE OR REPLACE FUNCTION public.feed_dog()
  RETURNS jsonb AS
$BODY$
   plv8.execute("SELECT prepare_cat_food()");
   plv8.execute("UPDATE dog SET hunger_status = 'good'");
$BODY$
  LANGUAGE plv8;

假设今天将此功能部署到生产环境中,明天我们将开始研究我们的新功能“狗粮健康检查”(对于文件系统上的“正常”代码,我们为此创建一个 Git 分支。对于数据库: 也许是一个新的数据库?)。 5 天后,新功能分支中的功能可能如下所示:

CREATE OR REPLACE FUNCTION public.feed_dog()
  RETURNS jsonb AS
$BODY$
   plv8.execute("SELECT dog_food_health_check()");
   plv8.execute("UPDATE dog_food_health SET 'status' = 'healthy'");
   plv8.execute("SELECT prepare_cat_food()");
   plv8.execute("UPDATE dog SET hunger_status = 'good'");
$BODY$
  LANGUAGE plv8;

但是,我们还没有部署,因为缺少重要的部分。

现在,就在同一天,有人发现我们混淆了狗和猫,执行的是 prepare_cat_food 而不是 prepare_dog_food

因此,完成了一个修补程序,使用 Flyway 迁移将完全覆盖整个函数 feed_dog:

CREATE OR REPLACE FUNCTION public.feed_dog()
  RETURNS jsonb AS
$BODY$
   plv8.execute("SELECT prepare_dog_food()");
   plv8.execute("UPDATE dog SET hunger_status = 'good'");
$BODY$
  LANGUAGE plv8;

因此,如果我将该迁移应用到“狗粮健康检查”分支,则 feed_dog 函数中开发的所有新功能都将被 Flyway 迁移覆盖。 相反,我们需要的是一种 Git 风格的合并和冲突解决机制,在这种情况下,它会在 plv8.execute("SELECT prepare_dog_food()"); 行停止并需要手动审查,以便最终,新功能将保留在那里并修复错误。

我们如何使用 Flyway 做到这一点?

或者它可以与 Liquibase 一起使用吗?他们不知何故有一个分支概念,但到目前为止我还不明白它是如何用于非线性开发的。

最佳答案

如果我正确理解您的问题,您需要结合使用两种技术:

(1) 将每个函数保存在一个源代码文件中: 您需要它来利用版本控制系统的冲突解决功能。

(2) Flyway支持乱序迁移: 此处的一篇优秀文章描述了如何实现这一点: http://www.jeremyjarrell.com/using-flyway-db-with-distributed-version-control/

基本上您需要做的是在每次更改函数后,您必须在包含新版本函数的相关分支中创建一个 Flyway 迁移脚本。鉴于您的示例,这在实践中将如下所示:

  1. 初始状态:

主干中的 feed_dog.sql

CREATE OR REPLACE FUNCTION public.feed_dog()
  RETURNS jsonb AS
$BODY$
   plv8.execute("SELECT prepare_cat_food()");
   plv8.execute("UPDATE dog SET hunger_status = 'good'");
$BODY$
  LANGUAGE plv8;
  1. 创建健康检查分支后

分支中的feed_dog.sql:

CREATE OR REPLACE FUNCTION public.feed_dog()
  RETURNS jsonb AS
$BODY$
   plv8.execute("SELECT dog_food_health_check()");
   plv8.execute("UPDATE dog_food_health SET 'status' = 'healthy'");
   plv8.execute("SELECT prepare_cat_food()");
   plv8.execute("UPDATE dog SET hunger_status = 'good'");
$BODY$
  LANGUAGE plv8;
  1. 在主干中应用修复后:

主干中的feed_dog.sql:

CREATE OR REPLACE FUNCTION public.feed_dog()
  RETURNS jsonb AS
$BODY$
   plv8.execute("SELECT prepare_dog_food()");
   plv8.execute("UPDATE dog SET hunger_status = 'good'");
$BODY$
  LANGUAGE plv8;

主干中的V20170830_124459_hotfix_dogfood.sql: 与 feed_dog.sql 内容相同

  1. 将主干的更改合并到功能分支后:

特性分支中的feed_dog.sql:

CREATE OR REPLACE FUNCTION public.feed_dog()
  RETURNS jsonb AS
$BODY$
   plv8.execute("SELECT dog_food_health_check()");
   plv8.execute("UPDATE dog_food_health SET 'status' = 'healthy'");
   plv8.execute("SELECT prepare_dog_food()");   -- Merged here
   plv8.execute("UPDATE dog SET hunger_status = 'good'");
$BODY$
  LANGUAGE plv8;

特性分支中的V20170831_135559_merged.sql: 与 feed_dog.sql 内容相同

feed_dog.sql 是函数 feed_dog() 的源代码文件。 “V”文件是根据上述文章中的建议命名的迁移脚本。 重新集成功能分支后,Flyway 将执行 V20170830_124459_hotfix_dogfood.sql,然后执行 V20170831_135559_merged.sql。

关于postgresql - 基于函数的数据库的非线性开发与版本控制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45862272/

相关文章:

version-control - 提交如何保持有序

xml - 将 Liquibase XML 转换为 YAML?

c# - 插入、子查询、值

postgresql - 慢触发器使用 postgresql 检查主键约束

PostgreSQL 将 cidr 扩展到单独的地址

version-control - 本地网络上的版本控制系统,无需服务器

sql - 如何按多个行值分组?

version-control - 你什么时候应该分支?

jpa - Spring Boot 。在 hsqldb 上生成 jpa 自动 dll 表后运行 liquibase 更改日志

java - spring项目中大量的数据库迁移