我对Django非常有信心,但直到最近才主要依赖生成的迁移。我写了一个小的自定义迁移,在我的CI开始抱怨超时后不久,它最终说明它与部署期间Django的迁移有关。
起初,我能够解决这个问题,但我不知道我做了什么(如果有的话)修复了它。这个问题似乎与我为特定迁移输入的一些自定义代码有关。这就是我所知道的:
输出如下(应用程序名称已删除):
[web@dev myapp]$ ./manage.py migrate
Operations to perform:
Apply all migrations: myapp1, myapp2, myapp3, myapp4
Running migrations:
Killed
RunPython
运行Python函数,在删除其中一个字段之前复制两个字段之间的数据。该文档不鼓励将其用于PostgreSQL,但是有更好的方法吗?options
)。代码检查布尔值是否为true并为字符字段设置正确的值。我做了两次。第一次最终结束了工作,但我还没有在另一个数据库上测试它。 这是迁移(已删除的应用名称):
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
的开头添加print语句,它们有时只会运行,并且会被杀死。按照目前的情况,我已经运行了6-8次并且每次都被杀死,但是在不同的地方
其他信息: - 使用Django 1.9 - 使用PostgreSQL 9.4.4 - 错误主要发生在CentOS上,但也发生在OSX上
答案 0 :(得分:8)
我认为您的问题是由使用all
时可能需要缓存的数据量引起的,因为这会返回对象的所有实例,因此您可以在返回对象之前对数据库级别进行过滤,因为您只需要更改字段的值,您也可以在数据库级别上执行此操作。总而言之,这会将您的代码更改为以下内容。
def fix_consulting(apps, schema_editor):
my_model = apps.get_model("myapp", "MyModel")
my_model._default_manager.filter(consulting=True).update(detail="CONSLT")
这会将内存管理职责放在数据库上,这似乎解决了您的问题。
接下来,我建议尝试始终将从db返回的内容过滤到实际需要的内容(通过拼接或过滤)
答案 1 :(得分:0)
如果您模型的任何字段的大小都很大,那么问题可能是内存已用完。如果迁移计算不需要此字段,只需使用 defer()
或 only()
将其省略。
例如要只加载必要的字段 location 和category,您可以执行以下操作:
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()
来收紧从数据库加载的字段。