Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Concurrency issues on SQLite #33

Closed
RealOrangeOne opened this issue Jun 8, 2024 · 3 comments · Fixed by #69
Closed

Concurrency issues on SQLite #33

RealOrangeOne opened this issue Jun 8, 2024 · 3 comments · Fixed by #69
Assignees
Labels
bug Something isn't working database-backend Issues relating to the database backend
Milestone

Comments

@RealOrangeOne
Copy link
Owner

SQLite doesn't support select_for_update, which is a key component of the database worker to ensure that a task is only picked up by a single database worker.

In Django 5.1, it's possible to change how the transactions are created. If transactions are created using EXCLUSIVE, this solves the concurrency issues, although increases the risk of locking errors (something we already work around with a retry, but it can reduce throughput). Therefore, without EXCLUSIVE, the task semantic changes from "at most once" to non-deterministic "zero or more times", which is at best unhelpful and at most a great source of confusion and complexity.

I see 2 possible solutions for this:

  1. Require that EXCLUSIVE transactions be used if SQLite is in a system check, and prevent usage without it
  2. Backport the functionality into django-tasks. This is far more complex, but it allows users of Django 4.2 and 5.0 to use SQLite.
@RealOrangeOne RealOrangeOne added the database-backend Issues relating to the database backend label Jun 8, 2024
@mustafa0x
Copy link

update ... returning can be used in place of select for update, if I understand the issue correctly.

@RealOrangeOne
Copy link
Owner Author

You'd still need a lock on the table to ensure 2 UPDATEs weren't running at the same time, which I think could still cause concurrency issues. I'm also not sure RETURNING is supported by Django, and I'd much rather avoid any custom SQL if we can avoid it.

@mustafa0x
Copy link

mustafa0x commented Jun 13, 2024

It replicates a lock. Eg,

UPDATE jobs
SET started_at = NOW()
WHERE started_at IS NULL
RETURNING *
LIMIT 1;

So if a row is returned, a lock has been acquired.

@RealOrangeOne RealOrangeOne added the bug Something isn't working label Jun 21, 2024
@RealOrangeOne RealOrangeOne added this to the 1.0 milestone Jul 7, 2024
@RealOrangeOne RealOrangeOne self-assigned this Jul 10, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working database-backend Issues relating to the database backend
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants