直接说结论:SQLite 在腾讯云轻量应用服务器(Lighthouse)上跑 Python 网站完全没问题,但要注意“单文件并发”和“备份”这两个坑。
很多新手觉得 SQLite 是“玩具数据库”,其实对于个人博客、小型 CMS、内部工具或者日活几千以内的项目,它比 MySQL 更香。原因很简单:不用装服务、配置极简、就是一个个文件,迁移方便得像复制粘贴。
但在腾讯云上跑,有几个实操层面的细节,不踩坑才能稳。
1. 为什么选 SQLite?(以及为什么不选别的)
轻量应用服务器通常内存小(2G/4G起步),如果你挂一个 MySQL,光是数据库进程就要吃掉不少资源,还要调优参数防止 OOM(内存溢出)。SQLite 是进程内数据库,没有独立的守护进程,省下的内存全给 Python 应用用,性能反而可能更高。
适用场景:
- 个人技术博客、作品集网站。
- 后台管理系统、数据看板。
- 日访问量 < 5000 的中小型 Web 应用。
- 原型开发、MVP 验证阶段。
不适用场景:
- 高并发写入(比如秒杀系统)。
- 需要复杂的多表关联查询且数据量极大(百万级以上行,千万级列)。
- 需要主从复制、分布式部署的企业级架构。
2. 核心痛点:并发写入锁
SQLite 最大的限制是写锁。同一时刻只能有一个线程/进程向数据库写入数据。如果你的 Python 网站用的是多线程或多进程部署(比如 Gunicorn + 多 Worker),多个请求同时尝试更新数据,就会报 database is locked 错误。
解决方案:
-
方案 A(推荐):使用连接池 + 重试机制
不要每次请求都新建连接。使用sqlite3自带的连接管理,或者 SQLAlchemy 的连接池。在代码里捕获OperationalError: database is locked,然后 sleep 几毫秒后重试。这是最稳妥的做法。 -
方案 B:调整 WAL 模式
默认情况下,SQLite 使用传统的日志模式。开启 WAL(Write-Ahead Logging)可以显著提高并发读取性能,并允许读写同时进行(虽然写还是排队,但读不会阻塞写)。在 Python 初始化数据库时执行:
import sqlite3 conn = sqlite3.connect('mydb.sqlite') # 启用 WAL 模式,提高并发性能 conn.execute("PRAGMA journal_mode=WAL;") # 设置同步模式为 NORMAL,平衡性能和安全性 conn.execute("PRAGMA synchronous=NORMAL;") -
方案 C:避免长事务
确保你的业务逻辑中,数据库操作尽量短平快。不要在持有数据库连接的情况下去调用外部 API、等待用户输入或进行大量 CPU 计算。
3. 腾讯云环境下的特殊注意事项
3.1 文件系统权限与路径
轻量服务器的 Linux 实例(通常是 Debian/CentOS/Ubuntu)对权限比较严格。
- 绝对不要用
/root目录存数据库文件,除非你的 Python 进程是以 root 身份运行(强烈不建议)。 - 创建一个专门的用户或目录,比如
/opt/app/data/,并确保 Python 进程有读写权限。 - 如果使用 Docker 部署,记得挂载 Volume,否则容器重启后数据丢失。
3.2 备份!备份!备份!
SQLite 的本质是一个 .sqlite 文件。腾讯云轻量应用服务器虽然有快照功能,但那是针对整个云盘的。你需要的是应用层的数据备份。
- 手动备份:写一个简单的 shell 脚本,每天凌晨把
.sqlite文件复制到 COS(腾讯云对象存储)或其他地方。# 示例 cron 任务 0 2 * * * cp /path/to/your/db.sqlite /backup/db_$(date +%Y%m%d).sqlite && aws s3 cp /backup/db_$(date +%Y%m%d).sqlite s3://your-bucket/backups/ - 在线备份:SQLite 支持热备份。可以使用
sqlite3命令行工具的.backup命令,或者在 Python 中使用sqlite3.backup()方法,在不锁定数据库的情况下拷贝一份完整副本。
3.3 监控磁盘 I/O
轻量服务器的磁盘 IO 有限。如果数据库文件过大(比如超过 1GB),频繁读写会导致 IOPS 打满,网站响应变慢。
- 定期清理无用数据。
- 考虑将静态资源(图片、CSS、JS)放到 COS 或 CDN,只让数据库存结构化数据。
4. 实战建议:如何优雅地集成
如果你用的是 Flask/Django/FastAPI 等框架,推荐这样设计:
Flask 示例:
from flask import Flask, g
import sqlite3
import os
app = Flask(__name__)
DATABASE = '/opt/app/data/app.db'
def get_db():
if 'db' not in g:
g.db = sqlite3.connect(DATABASE)
g.db.row_factory = sqlite3.Row
# 关键:启用 WAL 模式
g.db.execute("PRAGMA journal_mode=WAL;")
return g.db
@app.teardown_appcontext
def close_db(exception):
db = g.pop('db', None)
if db is not None:
db.close()
@app.route('/data')
def get_data():
db = get_db()
# 假设你有个 users 表
cursor = db.execute('SELECT * FROM users LIMIT 10')
users = [dict(row) for row in cursor.fetchall()]
return {"users": users}
Django 示例:
在 settings.py 中:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
'OPTIONS': {
'timeout': 20, # 等待锁释放的时间(秒)
},
}
}
然后在中间件或信号中处理 OperationalError 并重试。
5. 什么时候该换 MySQL?
当你遇到以下情况时,别犹豫,立刻迁移到腾讯云 RDS MySQL 或自建 MySQL:
- 频繁出现
database is locked错误,即使加了重试也无法解决。 - 查询速度明显变慢,尤其是多表 JOIN 操作。
- 团队规模扩大,需要多人同时编辑数据库结构或查看实时数据。
- 数据量增长到单表超过 500 万行,且查询复杂度增加。
总结
在腾讯云轻量应用服务器上,SQLite 是性价比极高的选择。它简单、可靠、易维护。只要处理好并发锁和定期备份,它能稳稳支撑起一个中小型 Python 网站的后端。别被“SQLite 不适合生产环境”这种老黄历吓住,关键在于你怎么用。
CLOUD云计算