You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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的文件锁机制异常:

  1. TinyDB基于JSON文件存储,写入/删除操作时会给存储文件加锁,操作完成后正常释放锁,后续请求才能正常读写
  2. 全局常驻数据库实例、删除操作异常中断未释放锁、多请求并发访问TinyDB三种情况,都会导致文件锁持续被占用,后续所有数据库读写请求直接阻塞,服务假死,这也是必须重启设备才能恢复的根本原因——重启强制释放了被占用的文件锁
  3. 现有代码里对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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 19:27:22