Flask搭配TinyDB执行删除操作报错 需重启树莓派4恢复服务
问题描述
使用Flask搭配TinyDB开发Web应用时出现固定场景报错,无Flask与Python开发经验,多日排查未解决。
故障现象:对已插入的数据行/字段执行删除操作后立即触发报错,网页服务完全不可用,必须重启树莓派4才能恢复服务运行。
关联问题代码
def index(): phones = d.all()#.sort(key=byPosition) if phones == None: phones = [] return render_template("index.html", phones=phones)
故障原因
故障核心是TinyDB的文件锁机制异常:
- TinyDB基于JSON文件存储,写入/删除操作时会给存储文件加锁,操作完成后正常释放锁,后续请求才能正常读写
- 全局常驻数据库实例、删除操作异常中断未释放锁、多请求并发访问TinyDB三种情况,都会导致文件锁持续被占用,后续所有数据库读写请求直接阻塞,服务假死,这也是必须重启设备才能恢复的根本原因——重启强制释放了被占用的文件锁
- 现有代码里对
d.all()的空值判断是多余的,TinyDB的all()方法在无数据时默认返回空列表,不会返回None
修复方案
- 禁止全局常驻TinyDB连接实例,每次请求使用独立的数据库连接,操作完成后主动关闭,避免锁残留,参考写法:
from tinydb import TinyDB from flask import render_template, request import threading # 初始化线程锁,解决TinyDB不支持并发写入的问题 db_write_lock = threading.Lock() DB_PATH = "你的数据库文件路径.json" def get_db(): # 每次调用返回新的数据库实例 db = TinyDB(DB_PATH) return db @app.route('/') def index(): db = get_db() try: phones = db.all() return render_template("index.html", phones=phones) finally: # 请求处理完主动关闭连接释放锁 db.close()
- 所有涉及写入、删除的操作加线程锁,同时做异常捕获,无论操作成功还是失败都保证连接关闭、锁释放,参考删除接口写法:
@app.route('/delete', methods=['POST']) def delete_phone(): # 加锁保证同一时间只有一个写入操作 with db_write_lock: db = get_db() try: target_id = int(request.form.get("item_id")) # 替换成你实际用的删除查询条件 db.remove(doc_ids=[target_id]) return "删除成功" except Exception as e: # 控制台打印报错方便排查 print(f"删除操作异常:{str(e)}") return "删除失败", 500 finally: db.close()
- 树莓派上部署不要直接用Flask自带的开发服务器,建议搭配gunicorn用单进程多线程模式启动,避免多进程同时读写数据库文件触发锁冲突,启动命令参考:
gunicorn -w 1 --threads 8 -b 0.0.0.0:5000 你的启动文件名:app
内容的提问来源于stack exchange,提问作者Danut Dobre
相关产品推荐
相关产品推荐

