心智模型#
了解描述 Liquibase 执行模型的主要概念。
变更#
Liquibase 管理数据库变更的执行。变更可以是目标数据库理解的方言编写的简单语句。例如,"SQL" 变更(由 liquibase-neo4j
别名为 Cypher)就是这种情况。
变更也可以是复杂的转换操作,例如 "重命名表"。
复杂变更的好处有两方面
- 它们封装了多个基本操作,否则编写这些操作会繁琐且容易出错
- 大多数这些复杂变更在不同的数据库管理系统之间是可移植的
注意
对于 liquibase-neo4j
而言,可移植性不是一个关注点。liquibase-neo4j
仅支持 Neo4j。目前没有支持其他图数据库的计划。当即将到来的 GQL 标准成熟并且生态系统完全接受它时,这种情况可能会改变。
变更集和事务#
变更被分组到变更集中。
单个变更集中的变更默认在单个事务中运行。要么所有变更都成功,要么都失败。
重要
Neo4j 模式操作和数据操作不能属于同一个事务。它们最好定义在不同的变更集中。
您可以通过将变更集的 runInTransaction
属性设置为 false
来禁用此行为。在这种情况下,变更集的每个变更都在其自己的自动提交事务中运行。
了解更多关于 runInTransaction
使用的最佳实践。
变更日志和一致性#
变更集在变更日志中定义,通常作为平面文件存储在本地文件系统上。
变更日志可以包含其他变更日志和/或定义变更集。
变更日志文件可以用不同的格式编写。格式甚至可以混合使用(例如:顶级 XML 变更日志可以包含 SQL 变更日志)。
注意
变更集由 ID、作者名以及定义它的变更日志路径唯一标识。这防止了意外冲突。
Liquibase 运行时需要一个单一的变更日志入口点。它会将所有变更日志包含解析为一个变更集的线性序列。
变更集可能相互依赖。例如,前一个变更集可能定义一个表,后一个变更集假定该表存在并向其中插入种子数据。
在分布式系统中实现这一点所需的一致性模型称为因果一致性,有时也称为"读己之写"。
对于 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
节点。如果此操作失败,则意味着另一个执行正在进行,并且当前执行将停止。