I have two database tables like so:
CREATE TABLE IF NOT EXISTS accounts (
id INT PRIMARY KEY NOT NULL,
balance INT NOT NULL DEFAULT 0
);
CREATE TABLE IF NOT EXISTS transactions (
from INT FOREIGN KEY REFERENCES accounts(id),
to INT FOREIGN KEY REFERENCES accounts(id),
amount INT NOT NULL
)
In my application logic, whenever a new transaction request comes in, I want to check first if the from account has sufficient balance, then I want to subtract the amount from the from account, add amount to the to account, and add a new row to the transactions table.
However, I want to do all of this atomically, for two reasons:
- Prevent race conditions. If two requests come in to transfer $5 from account 1 to account 2, and account 1 only has $5 total, I want to prevent double spending of the balance. Thus, the checking of sufficient balance and subsequent updating of balances has to happen atomically.
- Prevent inconsistent state if application crashes.
Is it possible to do this in a single SQL statement? assume we are using Postgres.
I know for example I can do UPDATE accounts SET balance = balance - 6 WHERE id = 1 and balance > 6;
to check if account has sufficient balance and simultaneously update the balance at the same time.
I've also heard of something called select ... for update
but I'm not sure if this can help me here.
Also, the result of the query should indicate whether the transaction was successful, so I can display some error message to client if it is not?