database - 并发 BEGIN–SELECT–INSERT 导致即时 SQLite3.7.6 "database locked"-error,覆盖忙超时?

标签 database concurrency transactions sqlite

sqlite3 控制台中:

sqlite>
    CREATE TABLE items (id PRIMARY KEY);
    BEGIN;
    SELECT * FROM items;
    INSERT INTO items VALUES(78);
sqlite> _

然后在第二个控制台中:

sqlite>
    .timeout 10000;
    BEGIN;
    SELECT * FROM items;
    INSERT INTO items VALUES(78);
Error: database is locked
sqlite> _

“数据库已锁定”- 错误立即发生,这不可能是对的,对吧?

如果我在第二个控制台中省略了 SELECT,繁忙的处理程序将在 INSERT 处等待 10 秒。我发现使用 BEGIN EXCLUSIVE 也会使第二个事务等待 10 秒,但随后在 BEGIN 语句处。 (我已经解决了这个问题。)

我的问题:这是一个错误,还是应该如此?如果这是预期的行为,那么为什么?

谢谢!

(SQLite v3.7.6)

最佳答案

第二个事务在第一个事务释放其写锁之前无法完成,而第一个事务在第二个事务释放其读锁之前无法完成。因此,立即回滚第二个是有意义的,因为它无法在任何时间内完成,所以第一个可以完成,您可以重试。

BEGIN EXCLUSIVE 立即获取独占锁,而不是等待第一个查询,这解释了您看到的差异。

您应该在事务中注意锁定的数据库(SQLITE_BUSY),如果发生这种情况,请回滚并重试。超时繁忙处理程序不会保护这些。

关于database - 并发 BEGIN–SELECT–INSERT 导致即时 SQLite3.7.6 "database locked"-error,覆盖忙超时?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6002333/

相关文章:

java - 从 Oracle 数据库检索 Java 代码中自动生成的 ID

MySQL语句选择特定列的最新条目

android - 即使使用 synchronized 关键字也有 ConcurrentModificationException

java - 如何在我的 swing 应用程序中旋转正方形

java - 具有非最终字段的可运行对象是否不安全地提交给执行者?

linux - 如何在linux上实现写事务?全部写入或不执行任何操作

java - 什么是数据库 session ?

mysql - 如何在 MySQL 中获取多个插入行的 ID?

MYSQL - 两列中的 WHERE 值

mysql - 使用 SQL 脚本和事务管理 mysql 模式更改