跳转到内容

Mental Model#

学习描述 Liquibase 执行模型的主要概念。

Changes#

Liquibase 管理数据库变更的执行。一次变更可以是目标数据库所支持的方言写成的简单语句。例如 SQL” 变更(在 liquibase-neo4j 中别名为 Cypher)。

一次变更也可以是复杂的转换操作,例如 “Rename Table”

复杂变更的价值体现在两个方面:

  1. 它们封装了多个基本操作,避免了手动编写时的繁琐与出错风险
  2. 大多数复杂变更能够在不同的数据库管理系统之间移植

注意

liquibase-neo4j 来说,可移植性不是问题。liquibase-neo4j 仅支持 Neo4j,暂无计划支持其他图数据库。随着 即将到来的 GQL 标准 成熟并被生态系统充分采用,这一点可能会改变。

Change Sets and Transactions#

变更会被归入变更集(change set)。

默认情况下,同一变更集中的所有变更在同一个事务中执行——要么全部成功,要么全部失败。

重要提示

Neo4j 的 模式操作 与数据操作不能放在同一个事务中,最好将它们拆分到不同的变更集。

可以通过将变更集的 runInTransaction 属性设为 false 来关闭此行为。此时,变更集中的每个变更都会在各自的自动提交事务中执行。

了解关于 runInTransaction 使用 的最佳实践。

Change Logs and Consistency#

变更集定义在变更日志(change log)中,通常以平面文件的形式存放在本地文件系统。

一个变更日志可以包含其它变更日志,亦或直接定义变更集。

变更日志文件可以使用 多种格式 编写,甚至可以混合使用(例如:顶层 XML 变更日志中可以包含 SQL 变更日志)。

注意

每个变更集通过 ID、作者名称以及定义它的变更日志路径唯一标识,从而避免意外冲突。

Liquibase 运行时只接受一个变更日志入口点,并会解析所有包含的变更日志,生成一个线性的变更集序列。

变更集之间可能存在依赖关系。例如,前一个变更集创建了一张表,后一个变更集则假设该表已存在并向其插入种子数据。

在分布式系统中实现此类依赖所需的“一致性模型”称为 因果一致性,有时也被称作 “Read Your Own Write”

对于 Neo4j,书签(bookmark)机制满足了上述属性。书签随事务一起传递,用来标识目标实例在处理该事务前必须达到的状态。

基于此理念,原生 Neo4j 驱动定义了会话(session)。会话绑定到单个执行线程,并自动将前一次成功事务的书签链入下一次事务。

liquibase-neo4j 使用的 JDBC 连接器依赖原生 Java 驱动,并将单个 JDBC 连接绑定到单个 Neo4j 会话。一次 Liquibase 调用只会打开一个连接。因此,因果一致性属性会自动得到保障。

Persistence and History Graph#

默认情况下,Liquibase 以“追加”方式执行变更。也就是说,与其修改已有的变更集,通常的做法是向现有序列追加新的变更集。

Tip

默认禁止修改变更集。变更集是不可变的。若希望其可变,需要将变更集的属性 runOnChange 设置为 true

Liquibase 默认不会重新运行已执行过的变更集。它们一旦在目标数据库上执行完毕,就不会再次运行。

Tip

若希望重新运行变更集,需要将其属性 runAlways 设置为 true

已执行的变更集必须被持久化。liquibase-neo4j 将其存储为历史图(在关系型数据库中对应的是 DATABASECHANGELOG)。

liquibase-neo4j schema

注意

liquibase-neo4j 将该历史图存放在与变更日志运行所在的同一数据库(租户)中。不支持在一个数据库上执行变更日志、在另一个数据库中持久化历史的情形。

重要提示

liquibase-neo4j 不保证历史图的模式在版本之间(即使是非主版本升级)保持不变。用户不应直接操作历史图。如果模式发生变化,liquibase-neo4j 会自动对先前版本持久化的历史图执行内部迁移。

Concurrency#

liquibase-neo4j 不应在同一服务器和同一数据库上并发执行。类似于 DATABASECHANGELOGLOCK 的机制,liquibase-neo4j 会尝试创建唯一的 __LiquibaseLock 节点。若创建失败,则说明已有其他执行正在进行,此时当前执行会被终止。

© . This site is unofficial and not affiliated with Neo4j, Inc.