繁体   English   中英

烧瓶:PK违规使用flask-sqlalchemy

[英]Flask: PK Violations Using flask-sqlalchemy

我使用带有两个工作线程和nginx的uwsgi来解决使用带有MySQL的flask-sqlalchemy中的PK违规的并发问题。

我正在使用来自有效载荷的密钥。 如果联系人带有数据库中存在的密钥,则更新记录,否则,创建新记录。

这是设置和我认为正在发生的事情。

#project/__init__.py
app = Flask(__name__)
db = SQLAlchemy(app)
from project import views, models

#project/views.py
from project import db

@app.route('/receive', methods = ['POST'])
def receive():

    #Check to see if the contact exists in the database
    contact = models.Contact.getIssue(contact_payload['id'])

    if contact is None:
        #If not in the DB, create a new contact
        new_contact = models.Contact(contact_payload)
        db.session.merge(new_contact)
    else:
        #If in the DB, create an updated representation of this contact
        updated_issue = contact.updateContact(contact_payload)
        db.session.merge(updated_issue)

    ...Some other stuff...

    #Commit to DB
    db.session.commit()

    #Respond
    resp = jsonify({'Result' : 'Success'})
    resp.status_code = 200
    return resp

当我们在同一时间收到同一联系人的两个请求时,问题就出现了(requestA是12:10:49,063,requestB是12:10:49,066)。 其中一个请求以PK违规结束。

我怀疑他们正在进入不同的工作线程,每个请求都从flask-sqlalchemy获得一个范围会话(sessionA - requestA和sessionB - requestB)。

我怀疑两个会话在请求的开头不包含任何内容,这些请求现在同时出现在上面的代码流中。

requestA遍历相应的代码流并将new_contact合并到sessionA中。

同时requestB通过相同的代码路径,其中contact是None(因为sessionA尚未提交)并将new_contact合并到sessionB中。

然后sessionA在sessionB之前提交。 当sessionB进入提交时,它会获得PK违规。

除了捕获PK违规并做出相应反应之外,我们还能做其他事情吗?

您有两种选择:

  1. 抓住PK违规并做出相应的反应,就像你已经说过的那样。

  2. 根据你的id锁定你的交易:这更复杂,你需要一些东西来同步你的锁,比如redis。 看看python-redis-lock。 它只是一个选项,这里的解决方案是避免PK的并发性。

https://pypi.python.org/pypi/python-redis-lock

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM