Python 从多个uWSGI工作者查询MySQL返回不匹配的行
我正在运行一个针对MySQL数据库的查询,该数据库来自一个Flask应用程序,该应用程序使用uWSGI和多个worker运行。我注意到,有时当我按id查询资源时,返回行的id与我查询时使用的id不同 我认为查询隔离意味着这是不可能的。然而,MySQL似乎把查询搞混了。在不使用uWSGI时,我无法再现这一点,但这可能只是因为它在本地主机上运行,而不是在单独测试Flask服务器时在服务器上运行 为什么输入id和结果id不匹配Python 从多个uWSGI工作者查询MySQL返回不匹配的行,python,mysql,flask,uwsgi,pymysql,Python,Mysql,Flask,Uwsgi,Pymysql,我正在运行一个针对MySQL数据库的查询,该数据库来自一个Flask应用程序,该应用程序使用uWSGI和多个worker运行。我注意到,有时当我按id查询资源时,返回行的id与我查询时使用的id不同 我认为查询隔离意味着这是不可能的。然而,MySQL似乎把查询搞混了。在不使用uWSGI时,我无法再现这一点,但这可能只是因为它在本地主机上运行,而不是在单独测试Flask服务器时在服务器上运行 为什么输入id和结果id不匹配 from flask import Flask import pymysq
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()
对于其他面临此问题的人,我找到了以下解决方案。 根据 只要可能,uWSGI尝试(ab)使用fork()调用的写时复制语义。默认情况下,它将在加载应用程序后分叉,以尽可能多地共享它们的内存。如果出于某种原因不希望出现这种行为,请使用lazy apps选项。这将指示uWSGI在每个工人的fork()之后加载应用程序 看了一眼之后,我意识到我的问题与创建多个流程有关 但是,由于默认情况下uWSGI从一个主辅助进程加载所有进程(并且每次都不运行整个Flask应用程序),因此所有辅助进程最终都共享一个数据库连接(结果不太好!)
解决方案是包含
lazy apps
参数,该参数强制在创建每个worker时运行所有代码。我对uwsgi也有同样的问题,在运行一天后,一些记录丢失,即使它们存在于数据库中。但我不明白共享数据库连接是如何导致这个问题的??!它们不仅仅共享同一个连接,它们实际上在内存中共享同一个Python数据库
对象!在我的示例中(参见问题),这导致了同时运行不同查询的两个fork之间的竞争条件。这意味着不同调用方的查询结果有时会由我的共享数据库对象返回。