有些小工具会用 SQLite 当本地状态库。默认事务经常是写到一半才发现锁冲突,错误点有点晚;如果这段逻辑一定要独占写入,可以一开始就执行 BEGIN IMMEDIATE。
环境:Python 3.10+,Linux/macOS/Windows,只用标准库。保存为 sqlite_lock_demo.py:
import sqlite3
import tempfile
from pathlib import Path
path = Path(tempfile.gettempdir()) / "sqlite-lock-demo.db"
try:
path.unlink()
except FileNotFoundError:
pass
init = sqlite3.connect(path)
init.execute("create table kv (key text primary key, value text)")
init.execute("insert into kv values ('mode', 'old')")
init.commit()
init.close()
# timeout=0 方便演示:拿不到锁就立刻报错
a = sqlite3.connect(path, timeout=0, isolation_level=None)
b = sqlite3.connect(path, timeout=0, isolation_level=None)
a.execute("BEGIN IMMEDIATE")
print("a got write lock")
try:
b.execute("BEGIN IMMEDIATE")
except sqlite3.OperationalError as exc:
print(f"b failed early: {exc}")
a.execute("update kv set value = 'new' where key = 'mode'")
a.commit()
print(dict(a.execute("select key, value from kv")))
a.close()
b.close()
运行:
python3 sqlite_lock_demo.py
输出里第二个连接会在 BEGIN IMMEDIATE 这一行就失败。这样适合“抢不到写锁就本轮跳过”的脚本,比业务逻辑跑到一半再炸要好处理一点。