Django 迁移被杀死
Django migration being killed
我对 Django 很有信心,但直到最近才主要依赖生成的迁移。我写了一个小的自定义迁移,在我的 CI 开始抱怨超时后不久,它最终与部署期间从 Django 的迁移有关。
起初,我能够解决这个问题,但我不知道我做了什么(如果有的话)来修复它。这个问题似乎与我为特定迁移输入的一些自定义代码有关。这是我所知道的:
- 最初,一切都很好,但是在添加我的自定义代码后,迁移开始花费 真的 很长时间到 运行(相对)。一次大约 10 秒。
- 它有时有效。 IE。如果我从命令行 运行 迁移十次,有时会成功,有时会失败。
输出如下(app名称被删掉):
[web@dev myapp]$ ./manage.py migrate
Operations to perform:
Apply all migrations: myapp1, myapp2, myapp3, myapp4
Running migrations:
Killed
- 起初我以为是因为我正在使用
RunPython
到 运行 一个 Python 函数,该函数在删除其中一个字段之前在两个字段之间复制数据。该文档不鼓励将其用于 PostgreSQL,但是有更好的方法吗?
- 这里的业务场景是我有一个布尔字段,我需要切换到一组选项(CharField with
options
)。该代码检查布尔值是否为真并为字符字段设置正确的值。我已经这样做了两次。第一次最终成功了,但我还没有在另一个数据库上测试过它。
这是迁移(删除了应用名称):
from __future__ import unicode_literals
from django.db import migrations
def fix_consulting(apps, schema_editor):
my_model = apps.get_model("myapp", "MyModel")
for m in my_model._default_manager.all():
if m.consulting:
m.detail = "CONSLT"
m.save()
class Migration(migrations.Migration):
dependencies = [
('myapp', '0024_auto_20160117_1113'),
]
operations = [
migrations.RunPython(fix_consulting,atomic=False),
]
我的想法:
也许我在这里写的代码花费的时间太长 运行?数据库中只有不到一百个模型,所以我不知道为什么 fix_consulting
功能会花费这么长时间。
如果我在fix_consulting
的开头添加打印语句,它们有时只会运行,而其他时候会被杀死。就目前而言,我已经 运行 它 6-8 次并且每次都被杀死,但在不同的点
其他信息:
- 使用 Django 1.9
- 使用 PostgreSQL 9.4.4
- 错误主要发生在 CentOS 上,但也有 OSX
我认为您的问题是由使用 all
时可能需要缓存的数据量引起的,因为此 returns 对象的所有实例,因此您可以对在返回对象之前更改数据库级别,因为您随后只需要更改字段的值,您也可以在数据库级别上执行此操作。总之,这会将您的代码更改为以下内容。
def fix_consulting(apps, schema_editor):
my_model = apps.get_model("myapp", "MyModel")
my_model._default_manager.filter(consulting=True).update(detail="CONSLT")
这将内存管理责任放在数据库上,这似乎已经解决了您的问题。
展望未来,我建议尝试始终过滤从数据库返回的内容,仅保留实际需要的内容(通过拼接或过滤)
如果您模型的任何字段都很大,那么问题可能出在内存用完了。如果迁移计算不需要此字段,只需使用 defer()
或 only()
.
将其省略
例如要 只加载必要的字段 位置 和 类别 你可以这样做:
for item in Item.objects.only('location', 'category').all()
Item.objects.filter(pk=item.pk).update(location=category.default_location)
背景:
我在 Google 计算 VM 上遇到了类似的问题 - 当 运行 在大型数据库上时,我的 Django 迁移被终止。我发现不仅 CPU 使用率激增,而且内存和内存交换导致大量交换磁盘 I/O。
我尝试了 Sayse 的解决方案(从 save() 切换到 update()),虽然它确实有助于加快我的(较小的)测试数据库的速度,但在主生产数据库上迁移仍然失败。
最终,我意识到由于我模型中的一个特定 json 字段非常大,内存已用完。这个字段对于处理迁移来说是不必要的,所以我只是通过使用 only()
.
来加强从数据库加载的字段
我对 Django 很有信心,但直到最近才主要依赖生成的迁移。我写了一个小的自定义迁移,在我的 CI 开始抱怨超时后不久,它最终与部署期间从 Django 的迁移有关。
起初,我能够解决这个问题,但我不知道我做了什么(如果有的话)来修复它。这个问题似乎与我为特定迁移输入的一些自定义代码有关。这是我所知道的:
- 最初,一切都很好,但是在添加我的自定义代码后,迁移开始花费 真的 很长时间到 运行(相对)。一次大约 10 秒。
- 它有时有效。 IE。如果我从命令行 运行 迁移十次,有时会成功,有时会失败。
输出如下(app名称被删掉):
[web@dev myapp]$ ./manage.py migrate
Operations to perform:
Apply all migrations: myapp1, myapp2, myapp3, myapp4
Running migrations:
Killed
- 起初我以为是因为我正在使用
RunPython
到 运行 一个 Python 函数,该函数在删除其中一个字段之前在两个字段之间复制数据。该文档不鼓励将其用于 PostgreSQL,但是有更好的方法吗? - 这里的业务场景是我有一个布尔字段,我需要切换到一组选项(CharField with
options
)。该代码检查布尔值是否为真并为字符字段设置正确的值。我已经这样做了两次。第一次最终成功了,但我还没有在另一个数据库上测试过它。
这是迁移(删除了应用名称):
from __future__ import unicode_literals
from django.db import migrations
def fix_consulting(apps, schema_editor):
my_model = apps.get_model("myapp", "MyModel")
for m in my_model._default_manager.all():
if m.consulting:
m.detail = "CONSLT"
m.save()
class Migration(migrations.Migration):
dependencies = [
('myapp', '0024_auto_20160117_1113'),
]
operations = [
migrations.RunPython(fix_consulting,atomic=False),
]
我的想法:
也许我在这里写的代码花费的时间太长 运行?数据库中只有不到一百个模型,所以我不知道为什么
fix_consulting
功能会花费这么长时间。如果我在
fix_consulting
的开头添加打印语句,它们有时只会运行,而其他时候会被杀死。就目前而言,我已经 运行 它 6-8 次并且每次都被杀死,但在不同的点
其他信息: - 使用 Django 1.9 - 使用 PostgreSQL 9.4.4 - 错误主要发生在 CentOS 上,但也有 OSX
我认为您的问题是由使用 all
时可能需要缓存的数据量引起的,因为此 returns 对象的所有实例,因此您可以对在返回对象之前更改数据库级别,因为您随后只需要更改字段的值,您也可以在数据库级别上执行此操作。总之,这会将您的代码更改为以下内容。
def fix_consulting(apps, schema_editor):
my_model = apps.get_model("myapp", "MyModel")
my_model._default_manager.filter(consulting=True).update(detail="CONSLT")
这将内存管理责任放在数据库上,这似乎已经解决了您的问题。
展望未来,我建议尝试始终过滤从数据库返回的内容,仅保留实际需要的内容(通过拼接或过滤)
如果您模型的任何字段都很大,那么问题可能出在内存用完了。如果迁移计算不需要此字段,只需使用 defer()
或 only()
.
例如要 只加载必要的字段 位置 和 类别 你可以这样做:
for item in Item.objects.only('location', 'category').all()
Item.objects.filter(pk=item.pk).update(location=category.default_location)
背景:
我在 Google 计算 VM 上遇到了类似的问题 - 当 运行 在大型数据库上时,我的 Django 迁移被终止。我发现不仅 CPU 使用率激增,而且内存和内存交换导致大量交换磁盘 I/O。
我尝试了 Sayse 的解决方案(从 save() 切换到 update()),虽然它确实有助于加快我的(较小的)测试数据库的速度,但在主生产数据库上迁移仍然失败。
最终,我意识到由于我模型中的一个特定 json 字段非常大,内存已用完。这个字段对于处理迁移来说是不必要的,所以我只是通过使用 only()
.