valderman / selda

A type-safe, high-level SQL library for Haskell
https://selda.link
MIT License
478 stars 58 forks source link

missing support for concurrent db access? (lock/serializable transaction) #190

Open mauke opened 1 year ago

mauke commented 1 year ago

I want to safely run certain queries from multiple concurrent clients. For example, consider the following pseudo-code:

x <- SELECT MAX(my_column) FROM my_table;
INSERT INTO my_table(my_column) VALUES ($x + 1);

or

x <- SELECT EXISTS(SELECT * FROM my_table);
if not x, then: INSERT INTO my_table(my_column) VALUES (CURRENT_TIMESTAMP);

I thought I could use transactions to make sure that, no matter how concurrent clients are scheduled, each INSERT uses a value consistent with the previous SELECT (as in example 1) or only happens if the table is empty (as in example 2). But this would require serializable transactions, and according to https://www.postgresql.org/docs/15/transaction-iso.html the default isolation level is read committed.

Alternatively, I could use explicit table locks of type ACCESS EXCLUSIVE as described in https://www.postgresql.org/docs/15/explicit-locking.html.

selda has a transaction function described as:

Perform the given computation atomically.

I don't think that's true. The source code shows that transaction translates to a pair of BEGIN TRANSACTION and COMMIT statements, but it does not set the isolation level, so it runs at read committed, not serializable.

As far as I can see, selda does not support locking tables or changing the transaction isolation level. Is there no way to do what I want? Or am I just missing something?