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

Telethon部署Fly.io后遇sqlite3.OperationalError数据库锁定问题求助

解决Telegram机器人Fly.io部署后SQLite锁错误

问题根源

SQLite是单文件嵌入式数据库,仅支持单写多读的并发模型。你的机器人分为监听脚本+Celery worker两个独立进程,再加上Fly.io默认的多实例部署,多个进程/机器同时读写同一个SQLite文件时,必然触发sqlite3.OperationalError: database is locked错误——尤其是Fly.io的共享卷属于网络文件系统,SQLite的文件锁机制在这类环境下完全不可靠。

可行解决方案

1. 替换为客户端-服务器型数据库(推荐生产环境)

直接切换到PostgreSQL或MySQL,Fly.io提供免费的PostgreSQL实例,配置流程:

  • 用Fly CLI创建PostgreSQL实例:fly postgres create
  • 将数据库关联到你的机器人应用:fly postgres attach <postgres-app-name>
  • 修改代码中的数据库连接字符串,替换为Fly.io提供的PostgreSQL URL(可通过fly secrets list查看)。

2. 临时调整SQLite连接参数(仅用于测试)

如果暂时不想换库,给SQLite连接添加以下参数缓解锁冲突:

  • 设置timeout=30:延长等待锁释放的时间
  • 开启check_same_thread=False:允许跨线程共享连接(注意:多进程共享仍有风险)
  • 启用isolation_level=None:开启自动提交模式,减少锁持有时间

示例(以Pyrogram会话存储为例):

from pyrogram import Client

app = Client(
    "bot_session",
    api_id=YOUR_API_ID,
    api_hash=YOUR_API_HASH,
    bot_token=YOUR_BOT_TOKEN,
    sqlite_connection_params={
        "timeout": 30,
        "check_same_thread": False,
        "isolation_level": None
    }
)

3. 限制Fly.io单实例运行

强制应用仅启动一个实例,避免多机器共享SQLite文件:

  • 修改fly.toml,添加进程配置:
[processes]
app = { auto_stop_machines = true, auto_start_machines = true, min_machines_running = 1, max_machines_running = 1 }
  • 将Celery worker与监听脚本合并到同一个进程中,避免跨进程的数据库冲突。

4. 分布式锁控制数据库访问

用Redis实现分布式锁,确保同一时间只有一个进程能读写SQLite:

import redis
from contextlib import contextmanager

# 初始化Redis客户端(Fly.io可直接添加Redis实例)
redis_client = redis.Redis.from_url("redis://your-redis-url")

@contextmanager
def db_lock(lock_name="sqlite_lock", timeout=15):
    lock = redis_client.lock(lock_name, timeout=timeout)
    try:
        lock.acquire(blocking=True)
        yield
    finally:
        lock.release()

# 使用锁包裹数据库操作
with db_lock():
    conn = sqlite3.connect("bot.db")
    cursor = conn.cursor()
    cursor.execute("INSERT INTO messages (content) VALUES (?)", (message_content,))
    conn.commit()
    conn.close()

报错栈验证

你遇到的报错栈应该类似:

sqlite3.OperationalError: database is locked
Traceback (most recent call last):
  File "./listener.py", line 52, in on_new_message
    db.save_message(message)
  File "./db.py", line 31, in save_message
    self.conn.commit()
sqlite3.OperationalError: database is locked

该错误直接指向多进程并发写SQLite的冲突,上述方案可彻底解决。

内容的提问来源于stack exchange,提问作者Kashyap Sayani

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 04:37:56