BEGIN TRANSACTION
SELECT stock FROM products WHERE id = 1 FOR UPDATE;
-- Row is now locked, other users must wait
IF stock > 0 THEN
UPDATE products SET stock = stock - 1 WHERE id = 1;
INSERT INTO orders (user_id, product_id) VALUES (?, ?);
COMMIT;
Advantage: Guaranteed consistency
Disadvantage: Performance impact, potential deadlocks
SELECT stock, version FROM products WHERE id = 1;
-- Client performs business logic
UPDATE products SET
stock = stock - 1,
version = version + 1
WHERE id = 1 AND version = @original_version;
-- If affected rows = 0, then conflict occurred
Advantage: Better performance, no blocking
Disadvantage: Retry logic needed
CREATE PROCEDURE BuyProduct(@userId INT, @productId INT)
AS BEGIN
BEGIN TRANSACTION
DECLARE @stock INT
SELECT @stock = stock FROM products WHERE id = @productId
IF @stock > 0
UPDATE products SET stock = stock - 1 WHERE id = @productId
INSERT INTO orders VALUES(@userId, @productId, GETDATE())
COMMIT
ELSE
ROLLBACK
END
let isProcessing = false;
function buyNow() {
if (isProcessing) return;
isProcessing = true;
document.getElementById('buyBtn').disabled = true;
fetch('/api/purchase', { method: 'POST' })
.then(response => {
isProcessing = false;
document.getElementById('buyBtn').disabled = false;
});
}