Flask连接MySQL后无法获取新增记录问题求助
问题原因分析
你遇到的核心问题是全局数据库连接的事务隔离导致无法读取新数据:
- 应用启动时创建的
db_conn是全局长连接,MySQL InnoDB默认的REPEATABLE READ隔离级别下,该连接的事务会一直使用启动时的数据快照,看不到其他事务提交的新增记录。 - 每次查询都在同一个未提交的事务内执行,自然只能拿到应用启动时存在的数据,后续新增的记录无法被查询到。
解决方案
有两种可行的解决方式,其中第一种是Web应用的标准实践:
方案1:每次请求时获取独立连接
把数据库连接的创建放到路由函数内部,每个请求使用独立的连接(flask_mysql底层会用连接池管理,不会频繁创建销毁连接,性能有保障),用完后关闭。这是符合Flask Web应用模型的常规用法:
from flask import Flask, render_template from flaskext.mysql import MySQL app = Flask(__name__) mysql = MySQL() app.config['MYSQL_DATABASE_USER'] = 'root' app.config['MYSQL_DATABASE_PASSWORD'] = 'test' app.config['MYSQL_DATABASE_DB'] = 'test_db' app.config['MYSQL_DATABASE_HOST'] = 'localhost' mysql.init_app(app) @app.route('/') def index(): # 每次请求时获取连接 db_conn = mysql.connect() cursor = db_conn.cursor() cursor.execute("SELECT created_at, loudness FROM readings WHERE created_at >= DATE_SUB(NOW(), INTERVAL 60 second);") data = cursor.fetchall() # 关闭游标和连接(放回连接池) cursor.close() db_conn.close() labels, values = format_data(data) return render_template("graph.html", labels=labels, values=values) def format_data(data): labels = [] values = [] for created_at, loudness in data: labels.append(created_at.strftime("%d/%m %H:%M")) values.append(loudness) return labels, values
方案2:全局连接开启自动提交
如果坚持使用全局连接,需要开启自动提交,让每次查询后都结束当前事务,下次查询会读取最新的数据快照:
from flask import Flask, render_template from flaskext.mysql import MySQL app = Flask(__name__) mysql = MySQL() app.config['MYSQL_DATABASE_USER'] = 'root' app.config['MYSQL_DATABASE_PASSWORD'] = 'test' app.config['MYSQL_DATABASE_DB'] = 'test_db' app.config['MYSQL_DATABASE_HOST'] = 'localhost' mysql.init_app(app) db_conn = mysql.connect() # 开启自动提交,每次查询后自动结束事务 db_conn.autocommit(True) @app.route('/') def index(): cursor = db_conn.cursor() cursor.execute("SELECT created_at, loudness FROM readings WHERE created_at >= DATE_SUB(NOW(), INTERVAL 60 second);") data = cursor.fetchall() cursor.close() labels, values = format_data(data) return render_template("graph.html", labels=labels, values=values) def format_data(data): labels = [] values = [] for created_at, loudness in data: labels.append(created_at.strftime("%d/%m %H:%M")) values.append(loudness) return labels, values
注意事项
- 方案1更推荐,因为Web应用是多请求并发模型,全局长连接存在线程安全风险,而每个请求独立连接能避免这类问题,同时连接池机制也不会影响性能。
- 你之前认为“把连接放路由不符合常规用法”是误解,flask_mysql的设计就是支持在请求中动态获取连接,这才是实际项目中的标准做法。
内容的提问来源于stack exchange,提问作者pkenrick
相关产品推荐
相关产品推荐

