4 ms·
On a large scale "rare" events happen every day. That is why people use locks and transactions or other measures. In case with shopify, they want to decide whe
by codedokode 2mo ago
On a large scale "rare" events happen every day. That is why people use locks and transactions or other measures.
In case with shopify, they want to decide whether the user may place order or not, at the moment when the user clicks "Pay" or some other button. If the user cannot place an order, they are shown the error, if they can, the items are reserved and the user is redirected to the payment page. So payment is processed only after successful reservation, and reservation is made only if the user wants to pay. The similar system works for buying train tickets online in my country, for example.
In you case, when user A clicks a button, following happens (as I understand):
1 the server increments the counter
2 the server calculates available amount as (amount_in_stock - amount reserved by carts with time < counter)
3 if the amount is large enough, the server updates the "time" field for user's cart thus reserving the item
Imagine that at step 2 the user A sees that there is one item left. However before user A does step 3, another user B might reserve the item (complete all 3 steps), and proceed to the payment. Then user A then completes step 3 and proceeds to the payment too. Now we end up with both user A and B paying for the last remaining item which doesn't solve the stated problem. Shopify's solution doesn't have such issues.
This is a classical TOCTTOU situation. There were exploits against Linux kernel based on similar issues.
- bijowo1676 2mo agoshopify is wrapping their entire dance with locking and moving rows inside a transaction. if you wrap step 1-3 inside transaction you will get same atomicity guarantee but again, my idea was: 1) do not use throwaway placeholder rows to imitate a single item 2) do not rely on db engine to decide which transaction gets committed first (which customer gets the last item) 3) model queue explicitly by introducing counter field that sorts and prioritizes customers' orders and decides which order gets fulfilled and which customers gets the last item
- codedokode 2mo agoNo, using transactions won't change anything here. > do not use throwaway placeholder rows to imitate a single item The point of using multiple rows for one product is to distribute the locks.