我有一个烧瓶应用程序,当它旋转时,它需要将数据转储到数据库。数据文件大约是100MB,目前有三个,但很快就会有~15个。
@app.before_first_request
def populateDB():
reader = csv.DictReader(file, delimiter='\t', fieldnames=["not relevant"])
OCRs = [dict(row.items()) for row in reader]
db.engine.execute(OpenChromatinRegion.__table__.insert(), OCRs)
我有一个名为populateDB的函数,只要文件很小(300行)就可以工作。当我在任何大文件上运行它时:
[2016-05-11 23:22:09 +0000] [7] [INFO] working on datafile MCF7-all.fdr0.01TF_anno.txt
[2016-05-11 23:22:24 +0000] [7] [INFO] Datafile MCF7-all.fdr0.01TF_anno.txt properly configured in memory
[2016-05-11 23:22:39 +0000] [1] [CRITICAL] WORKER TIMEOUT (pid:7)
[2016-05-11 23:22:41 +0000] [11] [INFO] Booting worker with pid: 11
然后它就会挂起。
有没有更好的方法来解决这个问题,或者某种方式没有失败?或许可以逐步进行而不是试图一次性转储100MB?
- 更新 -
我逐渐尝试了1000行的块,虽然它通过了几个这样的块,但工人仍然超时。
所以我目前的问题是: - 如果我使用芹菜会是什么样子? - alembic的op.bulk_insert会做得更好吗?
- 更新2 -
尝试使用Flask-Script,但它也没有用。
from flask.ext.sqlalchemy import SQLAlchemy
from flask.ext.script import Manager
from app import app, db
from models import *
manager = Manager(app)
@manager.command
def populateDB():
(same function as above)
工作仍然超时。这可能与Docker有关吗?我使用this project as my base。
- 更新3 -
奇怪的是,我为每个示例db.session.add()
,db.session.commit()
本地处理了一个文件。但根据the documentation,这似乎是最慢的方式。该解决方案在数字海洋上也无法远程工作。我认为这可能与内存压力有关。在它崩溃之前我经历了大约1,750,000行。
- 更新4 -
机器死后,我运行dmesg
并输出显示:
[ 2323.138921] Out of memory: Kill process 6578 (python) score 843 or sacrifice child
毕竟这是一个记忆问题。但我相信数据库不在内存中,它在磁盘上,那么占用所有内存的是什么?这通过所有千兆字节的内存吃掉了什么部分,或者码头工人将它限制在那个以下? (注意,我不是上面的函数,而是以10k行的方式逐步将数据放入数据库中。
- 更新5 -
我搬到了一个可笑的大VM,错误消失了。但是现在,当我一次用1000个密钥查询数据库时,它仍然失败。所有这一切都说是"工人被杀"。日志似乎没有任何相关信息,使得这种调试变得困难和令人沮丧。
我看了docker stats <container>
,内存压力似乎是10%,应该足够低。
我对码头工具有什么了解?为什么要随意杀死我的容器?
- 更新6 -
我认为这个问题的范围太大了。似乎可能有两个单独的问题:没有足够的内存来将所有内容先前插入数据库,现在查询超时。工作者超时我认为实际上是来自gunicorn的消息。我打算开一个关于gunicorn超时和sqlalchemy查询的新问题。
如果有人在将来发现类似的问题,我无法添加所有内容的方式只会增加VM的大小。似乎应该能够在较小的VM上运行,但我想你会尽力而为。
答案 0 :(得分:0)
为了做到这一点,更好的方法是使用异步任务队列,因为您希望应用程序可以自由地响应客户端请求。
如上述评论所述,芹菜可能是一种选择。 (http://www.celeryproject.org/)