Skip to content

sqlite: database is locked #57741

Description

@ronag

Multiprocess use of sqlite database sometimes fails with "database is locked"

We are using https://github.com/nxtedition/nxt-undici/blob/main/lib/sqlite-cache-store.js but have the same problem with https://github.com/nodejs/undici/blob/main/lib/cache/sqlite-cache-store.js.

Basically we have a cluster nodejs service which is using the undici http cache. The queries are not super complicated or doing anything exotic.

It's unclear when/how/why this occurs and what to do about it. Might be a normal thing but in that case we should document it.

Refs: nodejs/undici#4124

    this.#getValuesQuery = this.#db.prepare(`
      SELECT
        id,
        body,
        deleteAt,
        statusCode,
        statusMessage,
        headers,
        etag,
        cacheControlDirectives,
        vary,
        cachedAt,
        staleAt
      FROM cacheInterceptorV${VERSION}
      WHERE
        url = ?
        AND method = ?
        AND start <= ?
      ORDER BY
        deleteAt ASC
    `)

    this.#insertValueQuery = this.#db.prepare(`
      INSERT INTO cacheInterceptorV${VERSION} (
        url,
        method,
        body,
        start,
        end,
        deleteAt,
        statusCode,
        statusMessage,
        headers,
        etag,
        cacheControlDirectives,
        vary,
        cachedAt,
        staleAt
      ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
    `)

    this.#deleteExpiredValuesQuery = this.#db.prepare(
      `DELETE FROM cacheInterceptorV${VERSION} WHERE deleteAt <= ?`,
    )

Activity

  1. changed the title [-]database is locked[/-] [+]sqlite: database is locked[/+] on Apr 4, 2025
  2. cjihrig commented on Apr 4, 2025

    @cjihrig
    Contributor

    This is not a bug. This is just how SQLite works. Implementing #57597 may mitigate the issue.

  3. ronag commented on Apr 4, 2025

    @ronag
    MemberAuthor

    Would be nice to have it explained somewhere?

    Also throwing an error seems like a pretty slow way to indiciate busy/tryagain.

  4. ronag commented on Apr 4, 2025

    @ronag
    MemberAuthor

    @cjihrig On a separate note. How does our localStorage implementation handle this? Does it retry?

  5. cjihrig commented on Apr 4, 2025

    @cjihrig
    Contributor
  6. added
    sqliteIssues and PRs related to the SQLite subsystem.
    on Apr 5, 2025
  7. cjihrig commented on Apr 5, 2025

    @cjihrig
    Contributor

    Closing as there is nothing else to do here. Users can leverage PRAGMA busy_timeout already, and #57752 will add an option to the API for this.

  8. ronag commented on Apr 5, 2025

    @ronag
    MemberAuthor

    Would it make sense to change the api to return a Boolean rather than creating and throwing an error for this case?

  9. cjihrig commented on Apr 5, 2025

    @cjihrig
    Contributor

    Does any other SQLite library do that? I'm also not sure how that would work with APIs that already return a value.

  10. cjihrig commented on Apr 5, 2025

    @cjihrig
    Contributor

    I guess another question is, have you tried leveraging the busy timeout at all? It's not the same thing as a timeout in JavaScript for example.

  11. ronag commented on Apr 5, 2025

    @ronag
    MemberAuthor

    I actually think a low value is good as I don't want to block the main thread. This would give a good way to yield.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    sqliteIssues and PRs related to the SQLite subsystem.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions