并发 BEGIN–SELECT–INSERT 导致即时 SQLite3.7.6“数据库锁定”错误,覆盖繁忙超时?

发布于 2024-11-07 21:29:17 字数 643 浏览 0 评论 0原文

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)

In an sqlite3-console:

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

And then in a second console:

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

The "database is locked"-error happends instantly, which can't be right, right?

If I omit the SELECT in the second console the busy handler waits for 10 seconds at the INSERT. I've found that using BEGIN EXCLUSIVE also makes the second transaction wait for 10 seconds, but then at the BEGIN-statement. (Which I've resolved to as a workaround.)

My question: Is this a bug, or as it should be? If this the expected behaviour, then why?

Thanks!

(SQLite v3.7.6)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

梦途 2024-11-14 21:29:17

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

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

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

The second transaction cannot complete until the first one releases its write lock, and the first one can't complete until the second transaction releases its read lock. It thus makes sense to rollback the second one right away, since it cannot complete in any amount of time, so the first one can finish and you can try again.

BEGIN EXCLUSIVE acquires the exclusive lock right away, instead of waiting for the first query, which explains the difference you see.

You should watch out for locked database (SQLITE_BUSY) while in transactions, and rollback and try again if that happens. The timeout busy handler won't protect these.

凹づ凸ル 2024-11-14 21:29:17

是的,这是正常的。请阅读:http://www.sqlite.org/lockingv3.html

Yes this is normal. Please read: http://www.sqlite.org/lockingv3.html

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文