心智模型#
了解描述 Liquibase 执行模型的主要概念。
变更#
Liquibase 管理数据库变更的执行。变更可以是简单语句,以目标数据库理解的方言编写。例如,"SQL" 变更(由 liquibase-neo4j
称为 Cypher)就是这种情况。
变更也可以是复杂的转换操作,例如 "重命名表"。
复杂变更的优势有两方面:
- 它们封装了多个基本操作,否则编写这些操作会很繁琐且容易出错
- 大多数复杂变更可以在不同的数据库管理系统之间移植
注意
在 liquibase-neo4j
的情况下,可移植性不是问题。liquibase-neo4j
仅支持 Neo4j。目前没有计划支持其他图形数据库。当 即将推出的 GQL 标准 成熟,并且生态系统完全接受它时,这种情况可能会改变。
变更集和事务#
变更分组到变更集中。
默认情况下,单个变更集的变更在单个事务中运行。所有变更都成功或全部失败。
重要
Neo4j 模式操作 和数据操作不能在同一事务中。最好在不同的变更集中定义它们。
可以通过将变更集的 runInTransaction
属性设置为 false
来禁用此行为。在这种情况下,变更集的每个变更都在其自己的自动提交事务中运行。
了解有关 runInTransaction
用法 的最佳实践的更多信息。
变更日志和一致性#
变更集在变更日志中定义,通常存储在本地文件系统的平面文件中。
变更日志可以包含其他变更日志,也可以定义变更集。
变更日志文件可以使用 不同的格式 编写。格式甚至可以混合使用(例如:顶级 XML 变更日志可以包含 SQL 变更日志)。
注意
变更集通过 ID 和作者姓名以及定义它的变更日志路径来唯一标识。这可以防止意外冲突。
Liquibase 运行时需要单个变更日志入口点。它将解析所有变更日志包含到线性变更集序列中。
变更集之间可能存在依赖关系。例如,先前的变更集可以定义一个表,而下一个变更集则假定表存在,并将种子数据插入其中。
在分布式系统中实现这一点所需的 consistency 模型称为 因果一致性,有时称为 "读你自己的写"。
在 Neo4j 的情况下,书签机制满足了该属性。书签会随着事务传递,并标识目标实例在处理该事务之前需要达到的状态。
基于此理念,原生 Neo4j 驱动程序定义了会话。会话绑定到单个执行线程,并自动将先前成功事务的书签链接到下一个事务。
liquibase-neo4j
使用的 JDBC 连接器依赖于原生 Java 驱动程序,并将单个 JDBC 连接绑定到单个 Neo4j 会话。单个 Liquibase 调用会导致打开单个连接。因此,因果一致性属性会自动得到保证。
持久化和历史图#
Liquibase 默认情况下是追加式变更执行程序。实际上,最常见的方法不是更改现有变更集,而是将新的变更集追加到现有序列中。
提示
默认情况下禁止更改变更集。变更集是不可变的。为了使它们可变,变更集需要将其 runOnChange
属性设置为 true
。
Liquibase 默认情况下不会重新运行变更集。一旦它们针对目标数据库执行,它们就不会再运行。
提示
为了重新运行变更集,需要将它们的 runAlways
属性设置为 true
。
已执行的变更集需要被持久化。liquibase-neo4j
将它们存储为历史图(RDBMS 等效项是 DATABASECHANGELOG
表)。
注意
liquibase-neo4j
将此历史图存储在与变更日志运行的数据库(租户)相同的数据库中。不支持针对一个数据库执行变更日志并将历史记录持久化到另一个数据库。
重要
liquibase-neo4j
不保证历史图模式在版本之间保持不变,即使在非主要版本升级期间也是如此。用户不应直接操作历史图。如果模式发生变化,liquibase-neo4j
将自动针对以前版本持久化的历史图运行内部迁移。
并发#
liquibase-neo4j
不得针对同一个服务器和数据库并发执行。与 DATABASECHANGELOGLOCK
表 相似,liquibase-neo4j
尝试存储一个唯一的 __LiquibaseLock
节点。如果失败,则表示另一个执行正在进行,执行将停止。