【问题标题】:Flask: PK Violations Using flask-sqlalchemyFlask:使用 flask-sqlalchemy 的 PK 违规
【发布时间】:2015-11-03 16:32:04
【问题描述】:

我在使用带有两个工作线程和 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 违规并做出相应反应外,我们还能做其他事情吗?

【问题讨论】:

    标签: python flask sqlalchemy flask-sqlalchemy


    【解决方案1】:

    你有两个选择:

    1. 如您所说,发现 PK 违规并做出相应反应。

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

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

    【讨论】:

      猜你喜欢
      • 2020-05-15
      • 2021-04-14
      • 2019-07-13
      • 1970-01-01
      • 2014-01-31
      • 2015-03-25
      • 2021-10-02
      • 1970-01-01
      • 2020-09-15
      相关资源
      最近更新 更多