python - 从多个 uWSGI worker 查询 MySQL 返回不匹配的行

标签 python mysql flask uwsgi pymysql

我正在从一个 Flask 应用程序运行一个针对 MySQL 数据库的查询,该应用程序与 uWSGI 一起运行,有多个工作人员。我注意到有时当我通过 id 查询资源时,返回行的 id 与我查询的不同。

我认为查询隔离意味着这是不可能的。然而,MySQL 似乎混淆了查询。当我不使用 uWSGI 时我无法重现这一点,但这可能只是因为当它自己测试 Flask 服务器时它运行在本地主机上而不是服务器上。

为什么输入id和结果id不匹配?

from flask import Flask
import pymysql.cursor, random

class Database:
    def __init__(self, user, password, host, database):
        self.connection = pymysql.connect(
            user=user,
            password=password,
            host=host,
            database=database,
            cursorclass=pymysql.cursors.DictCursor
        )

    def query(self, sql, **kwargs):
        with self.connection.cursor() as cursor:
            cursor.execute(sql, kwargs)
            return cursor

app = Flask(__name__)
database = Database('user', 'password', 'localhost', 'database')

@app.route('/resources/<path:id>')
def resource(id):
    item = database.query(
        'SELECT resources.id FROM resources WHERE resources.id = %(id)s',
        id=id
    ).fetchone()

    identifier = random.random()
    print(identifier, 'ID 1:', id)
    print(identifier, 'ID 2:', item['id'])

    if int(item['id']) != int(id):
        print('Error found!!!')

    return 'Done', 200

if __name__ == '__main__':
    app.run()
[pid: 2824|app: 0|req: 1/1] xxx.xxx.xxx.xxx () {44 vars in 737 bytes} [Wed Oct 19 18:38:07 2016] GET /resources/10 => generated 4 bytes in 6 msecs (HTTP/1.1 200) 2 headers in 78 bytes (1 switches on core 0)
0.687535338604848 ID 1: 11
0.687535338604848 ID 2: 11
[pid: 2821|app: 0|req: 1/2] xxx.xxx.xxx.xxx () {44 vars in 737 bytes} [Wed Oct 19 18:38:07 2016] GET /resources/11 => generated 4 bytes in 5 msecs (HTTP/1.1 200) 2 headers in 78 bytes (1 switches on core 0)
0.9216930740141296 ID 1: 13
0.9216930740141296 ID 2: 13
[pid: 2823|app: 0|req: 1/3] xxx.xxx.xxx.xxx () {44 vars in 737 bytes} [Wed Oct 19 18:38:07 2016] GET /resources/13 => generated 4 bytes in 6 msecs (HTTP/1.1 200) 2 headers in 78 bytes (1 switches on core 0)
0.9053128320497649 ID 1: 12
0.9053128320497649 ID 2: 14
Error found!!!
0.794023616025622 ID 1: 15
0.794023616025622 ID 2: 15
[pid: 2824|app: 0|req: 2/4] xxx.xxx.xxx.xxx () {44 vars in 737 bytes} [Wed Oct 19 18:38:07 2016] GET /resources/15 => generated 4 bytes in 1 msecs (HTTP/1.1 200) 2 headers in 78 bytes (1 switches on core 0)
[pid: 2822|app: 0|req: 1/5] xxx.xxx.xxx.xxx () {44 vars in 737 bytes} [Wed Oct 19 18:38:07 2016] GET /resources/12 => generated 4 bytes in 31 msecs (HTTP/1.1 200) 2 headers in 78 bytes (1 switches on core 0)
0.3608322871408709 ID 1: 14
0.3608322871408709 ID 2: 16
Error found!!!
[pid: 2825|app: 0|req: 1/6] xxx.xxx.xxx.xxx () {44 vars in 737 bytes} [Wed Oct 19 18:38:07 2016] GET /resources/14 => generated 4 bytes in 18 msecs (HTTP/1.1 200) 2 headers in 78 bytes (1 switches on core 0)
0.8346421078513786 ID 1: 16
0.8346421078513786 ID 2: 17
Error found!!!

最佳答案

对于遇到此问题的其他人,我找到了以下解决方案。

根据 http://uwsgi-docs.readthedocs.io/en/latest/ThingsToKnow.html .

uWSGI tries to (ab)use the Copy On Write semantics of the fork() call whenever possible. By default it will fork after having loaded your applications to share as much of their memory as possible. If this behavior is undesirable for some reason, use the lazy-apps option. This will instruct uWSGI to load the applications after each worker’s fork().

看了uWSGI, Flask, sqlalchemy, and postgres: SSL error: decryption failed or bad record mac之后,我意识到我的问题与正在创建多个进程这一事实有关。

然而,因为 uWSGI 默认从一个 master worker 加载所有进程(并且不会每次都运行整个 Flask 应用程序),结果是所有的 worker 最终共享一个数据库连接(这不是'结局很好!)。

解决方案是包含 lazy-apps 参数,它强制所有代码在创建每个 worker 时运行。

关于python - 从多个 uWSGI worker 查询 MySQL 返回不匹配的行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40138527/

相关文章:

python - 快速将多列添加到 Pandas 数据框

python - 检索 Pandas 中上个月交易的列名称

python - tuple(aValidTupleOfTypeString) 没有返回我期望的结果

python - 模板文件更改时重新加载 Flask 应用程序

python - 创建简单的 flask 错误应用程序来记录异常

python - 将python编译成二进制——pypy性能

mysql - 了解mytop显示来监控mysql

mysql - Magento 中的自定义查询以将数据插入数据库

mysql - 查询(子查询)中的位置不起作用

python - 如何在 SQLAlchemy、Flask、Python 中处理唯一数据