一、错误现象与成因分析
当多个进程或线程同时访问SQLite数据库时,开发者经常会遇到"OperationalError: database is locked"错误。这种锁定状态通常发生在:
- 一个事务未提交时另一个连接尝试写入
- 多个线程共享同一个连接对象
- 长时间运行的查询阻塞了其他操作
二、核心解决方案
1. 增加超时等待参数
import sqlite3
conn = sqlite3.connect('mydb.db', timeout=30) # 设置30秒等待超时
2. 使用WAL模式(Write-Ahead Logging)
WAL模式显著提升并发性能:
conn.execute("PRAGMA journal_mode=WAL")
3. 确保及时提交事务
try:
cursor.execute("BEGIN IMMEDIATE") # 立即获取锁
# 执行操作...
conn.commit()
except Exception as e:
conn.rollback()
三、高级优化策略
| 策略 | 实现方法 | 适用场景 |
|---|---|---|
| 连接池管理 | 使用SQLAlchemy等ORM工具 | 高并发Web应用 |
| 读写分离 | 主数据库写,副本读 | 读密集型应用 |
四、性能对比测试
通过基准测试发现:
- WAL模式比DELETE模式吞吐量高3-5倍
- 适当增加busy_timeout可减少70%的锁定错误
五、最佳实践建议
- 为每个线程创建独立连接
- 避免长时间持有事务
- 定期执行
VACUUM维护数据库