我正在开发一个票务系统,用户在认领之前一次性托管大量票(基本上所有没有缺货的票)。这些票显示给用户,他们可以选择他们想要领取的任何票。
如果两个用户试图同时托管同一张票并且没有足够的票,则此托管系统可能会引入竞争条件,例如:
剩余票数:1
用户 A 点击页面,查看剩余票数。还剩 1 张票 用户 B 点击页面,查看剩余票数。还剩 1 张票
由于他们都剩下一张票,他们都会托管这张票,使票剩下-1。
如果可能的话,我想避免锁定,并且想知道带有子查询的语句是否像
INSERT INTO ticket_escrows (`ticket`,`count`)
SELECT ticket,tickets_per_escrow FROM tickets WHERE tickets.total > (
COALESCE(
SELECT SUM(ticket_escrows.count) FROM ticket_escrows
WHERE ticket_escrows.ticket = tickets.id
AND ticket_escrows.valid = 1
,0)
+
COALESCE(
SELECT SUM(ticket_claims.count)
FROM ticket_claims
WHERE ticket_claims.ticket = tickets.id
,0)
)
将是原子的,允许我在不锁定的情况下防止竞争条件。
具体来说,我想知道上述查询是否会阻止以下情况的发生:
Max tickets: 50 Claimed/Escrowed tickets: 49
T1: start tx -> sums ticket escrows --> 40
T2: start tx -> sums ticket escrows --> 40
T1: sums ticket claims --> 9
T2: sums ticket claims --> 9
T1: Inserts new escrow since there is 1 ticket left --> 0 tickets left
T2: Inserts new escrow since there is 1 ticket left --> -1 tickets left
我正在使用 InnoDB。