Django迁移部署感知工具。
项目描述
Django应用程序,提供数据库迁移工具,以自动化其部署。
灵感来自Ludwig Hähne于2015年的一篇帖子(无停机时间的Django迁移)以及与Zapier(Zapier)处理迁移的经验。
目前仅支持PostgreSQL和SQLite,因为它们是唯一两个支持事务DDL的开源核心后端,此工具就是围绕这一预期构建的。
安装
pip install django-syzygy
用法
将'syzygy'添加到您的INSTALLED_APPS
# settings.py
INSTALLED_APPS = [
...
'syzygy',
...
]
设置您的部署流程,在推出代码更改之前运行migrate --pre-deploy,之后运行migrate以应用延迟的迁移。
概念
在高度可用应用程序的上下文中处理数据库迁移时,Django迁移在操作序列方面有很多不足。
自动生成的模式更改(字段添加、删除、重命名等)没有考虑到旧版本和新版本代码必须共存一段时间的部署。
例如,添加一个带有默认值的字段并不会在数据库级别持久化默认值,这会阻止从现有代码中进行INSERT操作,因为现有代码忽略了临时添加的字段的存在,从而可能导致操作失败。
找出操作的正确顺序是可行的,但并不简单,且容易出错。Syzygy应通过引入关于部署和生成了解这种顺序的前提和推迟迁移的概念来解决此问题。
默认情况下,迁移被视为部署的前提,除非它包含破坏性操作或迁移的阶段类属性设置为Stage.POST_DEPLOY。当定义此属性时,它将绕过操作启发式方法。
例如,这个迁移将被视为前提。
class Migration(migrations.Migration):
operations = [
AddField('model', 'field', models.IntegerField(null=True))
]
而以下迁移将被推迟。
class Migration(migrations.Migration):
operations = [
RemoveField('model', 'field'),
]
from syzygy import Stage
class Migration(migrations.Migration):
stage = Stage.POST_DEPLOY
operations = [
RunSQL(...),
]
为了利用这种新的迁移阶段概念,migrate命令允许使用–pre-deploy标志针对要在部署之前运行的迁移进行目标定位。
它做了什么和没做什么
它做了
引入了预部署和后部署迁移的概念,并支持通过调整makemigrations和migrate命令来创建、管理和部署序列。
自动在预部署和后部署阶段分割已知会导致部署顺序问题的操作。
在模糊不清的情况下拒绝猜测,并迫使开发者在处理非平凡更改时反思其操作顺序。它的目的是提供带有安全质量默认值的护栏。
它没做
生成保证最小化数据库争用的操作。你应该调查特定于数据库的解决方案。
允许开发者完全抽象操作顺序的概念。有一些更改本质上是不可安全或不能以原子方式部署的,你应该准备好处理这些问题。
特殊操作
Syzygy覆盖了makemigrations命令,以自动分割和组织操作,以便它们可以在预部署和后部署阶段安全应用。
字段添加
当向现有模型添加字段时,Django将生成一个AddField操作,该操作大致相当于以下SQL:
ALTER TABLE "author" ADD COLUMN "dob" int NOT NULL DEFAULT 1988;
ALTER TABLE "author" ALTER COLUMN "dob" DROP DEFAULT;
这不是安全的,因为立即删除数据库级别的DEFAULT会阻止在迁移应用时部署的代码插入新记录。
为了使此更改安全,Syzygy将操作分为两部分,一个特殊的AddField操作,该操作在不执行DROP DEFAULT的情况下执行列添加,以及后续的PostAddField操作,该操作删除数据库级别的默认值。第一个被标记为Stage.PRE_DEPLOY,第二个被标记为Stage.POST_DEPLOY。
字段删除
当从现有模型中删除字段时,Django将生成一个RemoveField操作,该操作大致相当于以下SQL:
ALTER TABLE "author" DROP COLUMN "dob";
此类操作不能在部署之前运行,因为这会导致任何由现有代码发起的SELECT、INSERT和UPDATE操作崩溃,而在部署后执行会导致新部署的代码在“忘记”字段存在的情况下发生INSERT崩溃。
为了使这个变更安全,Syzygy 将操作分为两步。一个专门的 PreRemoveField 操作,如果存在 Field.default,则在列中添加数据库级别的 DEFAULT,否则使字段可空,第二个是普通的 RemoveField 操作。第一个标记为 Stage.PRE_DEPLOY,第二个标记为 Stage.POST_DEPLOY,就像任何 RemoveField 一样。
数据库级别的 DEFAULT 的存在或删除 NOT NULL 约束确保了顺利的推出顺序。
检查
为了防止创建混合不同 阶段 操作的迁移,这个包注册了 系统检查。这些检查将为每个具有模糊 阶段 的迁移生成错误。
例如,一个混合推断阶段的迁移将导致检查错误
class Migration(migrations.Migration):
operations = [
AddField('model', 'other_field', models.IntegerField(null=True)),
RemoveField('model', 'field'),
]
默认情况下,Syzygy 应该 不会 自动生成迁移,并且你只有在手动创建迁移或将 Syzygy 添加到历史项目时才会遇到检查失败。
对于触发此检查失败的项目迁移,建议手动添加正确的 stage: syzygy.stageStage 注释。对于第三方迁移,请参阅以下部分。
第三方迁移
只要迁移阶段的概念没有普及,你的项目可能依赖于包含模糊操作顺序的迁移的第三方应用程序。
由于无法通过编辑这些迁移来明确分配显式的 阶段,因此可以通过相应的 MIGRATION_STAGES_FALLBACK 和 MIGRATION_STAGES_OVERRIDE 设置指定回退或覆盖阶段。
默认情况下,具有模糊操作顺序的第三方应用程序迁移将回退到 Stage.PRE_DEPLOY,但可以通过将 MIGRATION_THIRD_PARTY_STAGES_FALLBACK 设置为 Stage.POST_DEPLOY 或将其设置为 None 来更改此行为。
回滚
迁移回滚也受到支持,并导致反转迁移的性质。当一个通常被认为是 先决条件 的迁移被回滚时,它将被 推迟。
CI 集成
为了确保没有功能分支包含模糊的操作顺序,鼓励用户包含一个作业,该作业尝试在一个仅包括目标分支更改的数据库上运行 migrate --pre-deploy 命令。
例如,对于一个功能分支 add-shiny-feature 和目标分支 main,一个脚本将如下所示
git checkout main
python manage.py migrate
git checkout add-shiny-feature
python manage.py migrate --pre-deploy
假设功能分支包含一系列无法在一个由预部署、部署和后部署阶段组成的单一原子部署中应用的操作,则migrate --pre-deploy命令将因AmbiguousPlan异常失败,详细说明歧义和解决方案路径。
迁移法定人数
当将迁移部署到共享同一数据库的多个集群时,确保
迁移只应用一次
在任一集群部署之前,先应用预部署迁移
只有在所有集群完成部署后,才会应用后部署迁移
内置的migrate命令不提供关于调用序列化保证,换句话说,在部署前后从多个集群天真地调用migrate可能会导致某些迁移尝试被重复应用。
为了克服这一限制,Syzygy在migrate命令中引入了一个--quorum <N:int>标志,允许集群进行协调。
当指定时,migrate --quorum <N:int>命令将等待至少N次migrate调用,然后才会应用计划中的迁移一次,并阻塞所有调用者直到操作完成。
为了使用--quorum功能,您必须将MIGRATION_QUORUM_BACKEND设置配置为指向一个法定人数后端,例如Syzygy提供的基于缓存的其中一个。
MIGRATION_QUORUM_BACKEND = 'syzygy.quorum.backends.cache.CacheQuorum'
或者
CACHES = {
...,
'quorum': {
...
},
}
MIGRATION_QUORUM_BACKEND = {
'backend': 'syzygy.quorum.backends.cache.CacheQuorum',
'alias': 'quorum',
}
开发
进行更改,然后通过tox运行测试
tox
项目详情
django_syzygy-1.1.0.tar.gz 的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 999120fd159a4ec7600c914a85e99321121ceaf2d0199e480c0fdcbf56c17436 |
|
MD5 | 5388bae4316d04e17e4306ef3c907f50 |
|
BLAKE2b-256 | f1d552d41950e85df1fa34b7a28e576beebe3d1cea8cab7cf739004ce5aede57 |
django_syzygy-1.1.0-py2.py3-none-any.whl 的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 4c5a26b77467b41cee3c8dcaac5b0dc6b4de0843921b9f619dc04d02de5c43aa |
|
MD5 | 9c02d8182c3d6eb3030b51748ae98d39 |
|
BLAKE2b-256 | db8f39287b43dac283dba5666cf19fdef5ad806084288e09ca555bc984e6054b |