对于在非传统生产环境中拥有Django应用程序的人,您如何处理数据库迁移? 我知道有 south
,但似乎如果涉及任何实质性内容,它会缺失很多。
另外两个选项(我能想到或使用过的)是在测试数据库上进行更改,然后(离线应用程序并)导入SQL导出文件。 或者,也许是一种更冒险的选择,在生产数据库中实时进行必要的更改,如果出现任何问题,则恢复备份。
您通常如何处理数据库迁移和架构更改?
对于在非传统生产环境中拥有Django应用程序的人,您如何处理数据库迁移? 我知道有 south
,但似乎如果涉及任何实质性内容,它会缺失很多。
另外两个选项(我能想到或使用过的)是在测试数据库上进行更改,然后(离线应用程序并)导入SQL导出文件。 或者,也许是一种更冒险的选择,在生产数据库中实时进行必要的更改,如果出现任何问题,则恢复备份。
您通常如何处理数据库迁移和架构更改?
对于这个问题,我有时会采取一种非常规的方法(读了其他答案后,也许并不那么非常规)。 我之前从未尝试过在django中使用它,所以我进行了一些实验。
简而言之,我让代码捕获由旧架构引起的异常,并应用适当的架构升级。 我并不希望这成为被接受的答案-它只适用于某些情况(有人可能会说永远不适用)。 但我认为它具有丑小鸭般的优雅。
当然,我有一个测试环境,可以随时将其重置为生产状态。 使用该测试环境,我更新我的架构并编写针对其的代码-如往常一样。
然后我还原架构更改并再次测试新代码。 我捕获结果错误,执行架构升级,然后重新尝试出错的查询。
升级函数必须编写成“无害”的形式,以便在多次调用时(可能发生在投入生产时)仅执行一次。
实际的Python代码-我将其放在我的settings.py文件的末尾以测试概念,但您可能希望将其保留在单独的模块中:
from django.db.models.sql.compiler import SQLCompiler
from MySQLdb import OperationalError
orig_exec = SQLCompiler.execute_sql
def new_exec(self, *args, **kw):
try:
return orig_exec(self, *args, **kw)
except OperationalError, e:
if e[0] != 1054: # unknown column
raise
upgradeSchema(self.connection)
return orig_exec(self, *args, **kw)
SQLCompiler.execute_sql = new_exec
def upgradeSchema(conn):
cursor = conn.cursor()
try:
cursor.execute("alter table users add phone varchar(255)")
except OperationalError, e:
if e[0] != 1060: # duplicate column name
raise
su postgres
pg_dump <db> > $(date "+%Y%m%d_%H%M").sql
psql template1
# create database upgrade_test template current_db
# \c upgradetest
# \i upgrade_file.sql
...assuming all well...
# \q
pg_dump <db> > $(date "+%Y%m%d_%H%M").sql # we're paranoid
psql <db>
# \i upgrade_file.sql
\set ON_ERROR_STOP 1
。这会在出现问题时立即停止升级脚本。通过大量测试,您可以确保没有任何问题发生。pg_dump --schema-only production_db > production_schema.sql
pg_dump --schema-only upgraded_db > upgrade_schema.sql
vimdiff production_schema.sql upgrade_schema.sql
or
diff -Naur production_schema.sql upgrade_schema.sql > changes.patch
vim changes.patch (to check/edit)
South并不是在所有地方都使用。比如在我们的组织中,我们有三个级别的代码测试。一个是本地开发环境,一个是暂存开发环境,第三个是生产环境。
本地开发环境由开发人员掌控,可以根据自己的需求进行操作。然后是暂存开发环境,它与生产环境保持相同,当然,在对现场数据库进行更改之前,我们会先在暂存环境中进行数据库更改,并检查是否一切正常,然后再手动更改生产数据库,使其再次与暂存环境相同。