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

预处理语句执行结果是否受初始化位置影响?未提交事务是否被考量?

SQLite预处理语句执行结果与初始化位置的关系

预处理语句的执行结果会因其初始化位置不同而存在差异,具体来说:预处理语句的查询是否纳入未提交变更的考量,完全取决于该语句是否与事务在同一数据库连接中初始化。

跨连接初始化的情况(断言失败)

当预处理语句在一个连接中创建后关闭该连接,后续在新连接的事务中执行该语句时,无法感知新连接里的未提交变更:

// 打开数据库、预处理语句、关闭连接
sqlite3* db = nullptr;
sqlite3_open(filename, &db);
sqlite3_stmt* count_stmt = nullptr;
sqlite3_prepare_v3(db, "SELECT count(*) FROM names", -1, SQLITE_PREPARE_PERSISTENT, &count_stmt, nullptr);
sqlite3_close(db);
// 随后打开数据库、启动事务并执行预处理语句
sqlite3_open(filename, &db);
sqlite3_exec(db, "BEGIN TRANSACTION", nullptr, nullptr, &err);
sqlite3_exec(db, "INSERT INTO names (name) VALUES ('John')", nullptr, nullptr, &err);
sqlite3_step(count_stmt);
int count = sqlite3_column_int(count_stmt, 0);
sqlite3_close(db);
REQUIRE(count == 1); // 断言失败,因为事务未提交,且语句和事务不在同一连接

同连接初始化的情况(断言通过)

如果预处理语句和事务在同一个连接中创建,查询结果会包含该连接内未提交的事务变更:

// 打开数据库、预处理语句、启动事务并查询
sqlite3* db = nullptr;
sqlite3_open(filename, &db);
sqlite3_stmt* count_stmt = nullptr;
sqlite3_prepare_v3(db, "SELECT count(*) FROM names", -1, SQLITE_PREPARE_PERSISTENT, &count_stmt, nullptr);
sqlite3_exec(db, "BEGIN TRANSACTION", nullptr, nullptr, &err);
sqlite3_exec(db, "INSERT INTO names (name) VALUES ('John')", nullptr, nullptr, &err);
sqlite3_step(count_stmt);
int count = sqlite3_column_int(count_stmt, 0);
sqlite3_close(db);
REQUIRE(count == 1); // 断言通过,尽管事务尚未提交

核心原因

SQLite的事务、预处理语句都是与数据库连接强绑定的:

  • 预处理语句创建时会关联当前连接的上下文,包括数据快照、事务状态等。跨连接复用语句时,它无法识别新连接的事务变更,只会基于原连接的视图执行查询。
  • 同一连接内的所有操作共享同一个事务上下文,预处理语句能实时看到该连接内未提交的修改,这是SQLite基于连接的事务隔离机制决定的。

内容的提问来源于stack exchange,提问作者Lucian Thorr

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 13:55:13