数据库迁移¶
注意
本文档详细介绍了如何在新的功能或错误修复中生成数据库迁移。有关如何应用现有数据库迁移的信息,请参阅 nova-manage db sync 和 nova-manage api_db sync 命令在 nova-manage 中的文档。有关 nova 部署的常规升级过程的信息,请参阅 升级。
典型的 nova 部署由一个“API”数据库和一个或多个特定单元的“主”数据库组成。有时这些数据库需要模式或数据迁移。
模式迁移¶
版本 24.0.0 中更改: (Xena)
数据库迁移引擎已从 sqlalchemy-migrate 更改为 alembic。
版本 28.0.0 中更改: (Bobcat)
已删除旧的基于 sqlalchemy-migrate 的数据库迁移。
nova 使用 alembic 数据库迁移工具来管理模式迁移。迁移文件和相关元数据可以在 nova/db/api/migrations(API 数据库)和 nova/db/main/migrations(主数据库)中找到。如 升级 中所述,最终用户可以使用 nova-manage api_db sync 和 nova-manage db sync 命令分别运行这些迁移。
注意
旧版迁移也提供在 legacy_migrations 子目录中,用于 API 和主数据库。这些迁移是为了方便从 Xena (24.0.0) 之前的部署升级。它们在 28.0.0 (Bobcat) 版本中已被删除。
alembic 的最佳参考资料是 alembic 文档,但此处提供了一个小示例。您可以手动或自动创建迁移。对于重命名表等一些特殊情况,手动生成可能是必要的,但自动生成通常可以处理您的问题。下面提供了两者的示例。在两个示例中,我们将演示如何将新的模型 Foo 添加到主数据库。
diff --git nova/db/main/models.py nova/db/main/models.py
index 7eab643e14..8f70bcdaca 100644
--- nova/db/main/models.py
+++ nova/db/main/models.py
@@ -73,6 +73,16 @@ def MediumText():
sqlalchemy.dialects.mysql.MEDIUMTEXT(), 'mysql')
+class Foo(BASE, models.SoftDeleteMixin):
+ """A test-only model."""
+
+ __tablename__ = 'foo'
+
+ id = sa.Column(sa.Integer, primary_key=True)
+ uuid = sa.Column(sa.String(36), nullable=True)
+ bar = sa.Column(sa.String(255))
+
+
class Service(BASE, models.SoftDeleteMixin):
"""Represents a running service on a host."""
(您可能无法干净地应用上面的差异 - 这只是一个演示)。
自动生成迁移脚本
为了使 alembic 将迁移与底层模型进行比较,它需要一个可以检查并与模型进行比较的数据库。因此,我们首先需要创建一个可用的数据库。我们将绕过 nova-manage 并直接使用 alembic CLI。为两个数据库提供的 alembic.ini 文件已配置为默认使用 SQLite 数据库(nova.db 用于主数据库,nova_api.db 用于 API 数据库)。创建此数据库并应用当前模式,如当前迁移脚本所规定
$ tox -e venv -- alembic -c nova/db/main/alembic.ini \
upgrade head
完成之后,您应该注意到仓库根目录中的新 nova.db 文件。现在,让我们生成新的修订版
$ tox -e venv -- alembic -c nova/db/main/alembic.ini \
revision -m "Add foo model" --autogenerate
这将在 nova/db/main/migrations 中创建一个新文件,文件名中包含 add_foo_model(希望!)包括添加新模型 Foo 所需的更改。创建后,您 必须 检查此文件,因为您可能会缺少导入或其他需要手动更正的内容。完成此文件的检查并进行任何必要的更改后,您可以应用迁移并确保其正常工作
$ tox -e venv -- alembic -c nova/db/main/alembic.ini \
upgrade head
手动生成迁移脚本
对于更复杂的迁移或 alembic 不理解的内容,您可能需要手动创建一个迁移脚本。这与自动生成步骤非常相似,不同之处在于您不需要事先准备好数据库。因此,您可以简单地运行
$ tox -e venv -- alembic -c nova/db/main/alembic.ini \
revision -m "Add foo model"
与之前一样,这将在 nova/db/main/migrations 中创建一个新文件,文件名中包含 add_foo_model。您可以简单地修改它以进行必要的更改。完成之后,您可以应用迁移并确保其正常工作
$ tox -e venv -- alembic -c nova/db/main/alembic.ini \
upgrade head
数据迁移¶
如 升级 中所述,在线数据迁移发生在两个地方
内联迁移,作为数据以旧格式读取和以新格式写入时的正常运行时活动的一部分而发生。
使用
nova-manage执行的后台在线迁移,以完成由于正常运行时活动而不会偶然发生的转换。
内联数据迁移
内联数据迁移可以说是两者中更容易实现的一个。nova 的几乎所有数据库模型都对应于一个 oslo.versionedobject (o.vo) 或其一部分。这些 o.vo 通过实现 obj_load_attr 方法从底层数据库加载其数据。通过修改此方法,可以检测到数据的缺失更改 - 例如,缺失的字段 - 修改数据,将其保存回数据库,最后返回一个包含新更新数据的对象。更改 I6cd206542fdd28f3ef551dcc727f4cb35a53f6a3 提供了一个本方法的完整示例。
它们的的主要优点是它们对操作员来说是完全透明的,操作员无需采取任何额外的步骤来升级其部署:数据库更新应在运行时发生,因为数据从数据库中提取。这种方法的的主要缺点是,某些记录可能不会经常从数据库中提取,这意味着它们永远没有机会得到更新。这可能会阻止在未来的版本中删除内联迁移。为了避免这个问题,您应该检查对象,看看它是否是作为标准运行时操作(例如,启动时或作为后台任务的一部分)加载的一部分,如果必要,在后续版本中添加一个阻止性在线迁移来捕获和迁移滞后者。
在线数据迁移
与内联数据迁移不同,在线数据迁移需要操作员参与。它们使用 nova-manage db online_data_migrations 命令运行,如 nova-manage 中所述,这应在应用数据库模式迁移和更新代码后,升级到新版本后立即运行。在线迁移可以是阻塞的,也就是说,在升级到 N+1 之前,必须应用给定的迁移,同时运行 N 代码。更改 I44919422c48570f2647f2325ff895255fc2adf27 提供了一个本方法的完整示例。
这种方法的优点和缺点与内联数据迁移方法的优点和缺点相反。虽然它们可用于确保应用数据迁移,但它们需要操作员参与,并且可能会阻止升级,直到完全应用为止。