简体   繁体   English

烧瓶:PK违规使用flask-sqlalchemy

[英]Flask: PK Violations Using flask-sqlalchemy

I'm having concurrency problems leading to PK violations in flask-sqlalchemy with MySQL using uwsgi with two worker threads and nginx. 我使用带有两个工作线程和nginx的uwsgi来解决使用带有MySQL的flask-sqlalchemy中的PK违规的并发问题。

I'm using keys that come from the payload. 我正在使用来自有效载荷的密钥。 If the contact comes in with a key that exists in the database, update the record, if not, create a new record. 如果联系人带有数据库中存在的密钥,则更新记录,否则,创建新记录。

Here is the setup and what I think is happening. 这是设置和我认为正在发生的事情。

#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

The issue comes when we receive two requests for the same contact at the exact same time (requestA is 12:10:49,063 and requestB is 12:10:49,066). 当我们在同一时间收到同一联系人的两个请求时,问题就出现了(requestA是12:10:49,063,requestB是12:10:49,066)。 One of the requests ends in a PK violation. 其中一个请求以PK违规结束。

I suspect they're coming in on different worker threads and each request gets a scoped session (sessionA - requestA and sessionB - requestB) from flask-sqlalchemy. 我怀疑他们正在进入不同的工作线程,每个请求都从flask-sqlalchemy获得一个范围会话(sessionA - requestA和sessionB - requestB)。

I suspect both sessions contain nothing at the beginning of the requests that are now in the above code flow simultaneously. 我怀疑两个会话在请求的开头不包含任何内容,这些请求现在同时出现在上面的代码流中。

requestA goes through the appropriate code flow and merges new_contact into sessionA. requestA遍历相应的代码流并将new_contact合并到sessionA中。

At the same time requestB goes through the same code path where contact is None (because sessionA hasn't committed yet) and merges new_contact into sessionB. 同时requestB通过相同的代码路径,其中contact是None(因为sessionA尚未提交)并将new_contact合并到sessionB中。

Then sessionA commits before sessionB. 然后sessionA在sessionB之前提交。 When sessionB goes to commit, it gets the PK violation. 当sessionB进入提交时,它会获得PK违规。

Can we do anything else other than catch the PK violation and react accordingly? 除了捕获PK违规并做出相应反应之外,我们还能做其他事情吗?

You have two options: 您有两种选择:

  1. Catch the PK violation and react accordingly, like you already said. 抓住PK违规并做出相应的反应,就像你已经说过的那样。

  2. Lock your transaction based on your id: this is more complicated, you need something to synchronize your locks, like redis. 根据你的id锁定你的交易:这更复杂,你需要一些东西来同步你的锁,比如redis。 Take a look at python-redis-lock. 看看python-redis-lock。 It is just one option, the solution here is to avoid concurrency for a PK. 它只是一个选项,这里的解决方案是避免PK的并发性。

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

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

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