From: | "Frank Millman" <frank(at)chagford(dot)com> |
---|---|
To: | <pgsql-general(at)postgresql(dot)org> |
Subject: | Locking question |
Date: | 2016-10-26 08:42:29 |
Message-ID: | 940EF94B8B844413890C2D6F0FCF81E9@FrankLaptop |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Thread: | |
Lists: | pgsql-general |
Hi all
I am designing an inventory application, and I want to ensure that the stock level of any item cannot go negative.
Instead of maintaining a running balance per item, I store the original quantities received in one table (call it ‘inv_rec’), and any amounts removed in another table (call it ‘inv_alloc’).
CREATE TABLE inv_rec
(row_id SERIAL PRIMARY KEY,
product_id INT REFERENCES inv_products,
qty INT);
CREATE TABLE inv_alloc
(row_id SERIAL PRIMARY KEY,
rec_id INT REFERENCES inv_rec,
qty INT);
To get the balance of a particular item -
SELECT SUM(
a.qty + COALESCE(
(SELECT SUM(b.qty) FROM inv_alloc b
WHERE b.rec_id = a.row_id), 0))
FROM inv_rec a
WHERE a.product_id = 99;
To remove a quantity from a particular item -
INSERT INTO inv_alloc (rec_id, qty)
VALUES (23, -1);
I want the application to check that there is sufficient quantity before attempting to execute the INSERT command.
If ok, it will look for a suitable row in ‘inv_rec’ to allocate against.
The danger of course is that, in a multi-user system, another user might have removed an additional quantity from the same item in between the SELECT and the INSERT.
I *think* that the solution is to BEGIN the transaction, then perform SELECT ... WITH UPDATE, then proceed with INSERT and COMMIT if ok, else ROLLBACK.
Is this the correct approach, or am I missing something?
Thanks
Frank Millman
From | Date | Subject | |
---|---|---|---|
Next Message | hubert depesz lubaczewski | 2016-10-26 08:46:56 | Re: Locking question |
Previous Message | Tom Lane | 2016-10-25 22:13:45 | Re: What is the 'data2' directory for? |