如何在启动时将数据转储到数据库

时间:2016-05-11 23:41:56

标签: flask docker flask-sqlalchemy docker-compose

我有一个烧瓶应用程序,当它旋转时,它需要将数据转储到数据库。数据文件大约是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上运行,但我想你会尽力而为。

1 个答案:

答案 0 :(得分:0)

为了做到这一点,更好的方法是使用异步任务队列,因为您希望应用程序可以自由地响应客户端请求。

如上述评论所述,芹菜可能是一种选择。 (http://www.celeryproject.org/