sqlite3: wrap sqlite3_txn_state and sqlite3_stmt_readonly C functions
还没有人认领这个 Issue。
- 主要语言
- Python
- 星标
- 77.2k
- 派生
- 35.9k
- PR 合并指标
- PR 指标待抓取
描述
Feature or enhancement
Proposal:
SQLite is well known for having locking problems, as it's serverless. WAL mode reduces these but does not eliminate them. Debugging SQLITE_BUSY errors is hard since they can be triggered by any Cursor/Connection execute method call, anywhere in the codebase. It can be difficult to identify the blocking process without instrumenting every one of these calls, since it's not obvious from higher up whether a particular query is read-only or read-write, or what locks are already held.
It would be helpful to be able to identify whether our own connection currently has a read lock (SHARED) or a write lock (EXCLUSIVE) and whether it's about to (try to) acquire one. This can be done using the C API functions:
- sqlite3_txn_state (current transaction state/held lock type)
- sqlite3_stmt_readonly (whether executing this statement will try to acquire a write lock)
These functions are not wrapped and not available in Python, not even using ctypes since we can't get access to the raw sqlite3 structure pointer/handle from Python.
I'm imagining being able to use a custom Cursor class to do something like this:
- In overridden execute() method
- If we are about to execute a non-readonly statement
- And we are not already in a write transaction
- Check for another PID in a shared state file (e.g. a lock-type file)
- If there is one, our own attempt to acquire the lock may be delayed or fail, so log that
- Attempt to acquire a write lock with BEGIN IMMEDIATE
- If it was delayed, log the delay
- If it fails, log the PID that was holding the lock before and reraise
- Write our own PID to the shared state file
- Execute the non-readonly statement (this should not now block)
- If we were not in a transaction before, then COMMIT (this may also block as a checkpoint could require exclusive access/no readers) and remove the shared state file
I might be able to submit a PR for this as it should not be too difficult to wrap these C functions. I've been able to use sqlite3_txn_state by creating and loading a custom SQLite3 extension (in C) that creates a custom function that calls this function.
Has this already been discussed elsewhere?
This is a minor feature, which does not need previous discussion elsewhere
Links to previous discussion of this feature:
sqlite3_stmt_readonly used to be used internally by Cursor for a minor feature (the row count indication), but not exposed to Python.
贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
调研方向
定位 CPython 中与 Cursor 和 Connection 执行相关的 sqlite3 绑定,然后查看 issue 73541 中引用的此前内部使用情况。确认如何将 sqlite3_txn_state 和 sqlite3_stmt_readonly 暴露给 Python,并找出相关测试。当这两个 SQLite C 函数都可从 Python 访问,且其行为有测试覆盖时,即视为完成。
由索引模型根据 Issue 内容生成。
评估
- 技术栈
- python, sqlite
- 领域
- databases
- Issue 类型
- 功能
- 难度
- 3/5
- 预计耗时
- 1-2 天
- 活跃度
- 停滞
- 描述清晰度
- 基本清楚
- 新手友好度
- 42/100