我创建了一个票务系统,它以最简单的形式记录加入队列的用户,并打印出带有队列号的票证。
当用户按下故障单时,数据库中会发生以下情况
INSERT details INTO All_Transactions_Table
SELECT COUNT(*) as ticketNum FROM All_Transactions_Table WHERE date is TODAY
在大多数情况下,这对我很有帮助。但是,我最近开始看到一些重复的票号。即使在我自己多次运行Web服务之后,我似乎无法复制该问题。
我猜测它是如何发生的,在某些情况下,INSERT
仅发生在 AFTER SELECT COUNT
之后。但这是一个InnoDB表,我没有使用INSERT DELAYED
。 InnoDB是否有任何这样的隐含机制?
答案 0 :(得分:1)
我认为你的问题是你有竞争条件。想象一下,你有两个人来买票。这是第一个人:
INSERT details INTO All_Transactions_Table
然后,在SELECT COUNT(*)
发生之前,第二个人出现并且确实:
INSERT details INTO All_Transactions_Table
现在两个用户都获得相同的票号。这可能很难使用现有代码进行复制,因为它取决于使用MySQL的线程的确切调度,这完全超出了您的控制范围。
最好的解决方案是使用某种AUTO_INCREMENT
列来提供票号,但如果失败,你可以使用交易来达到你想要的目的:
START TRANSACTION
SELECT COUNT(*) + 1 as ticketNum FROM All_Transactions_Table WHERE date is TODAY FOR UPDATE
INSERT details INTO All_Transactions_Table
COMMIT
但是,这是否有效将取决于您设置的事务隔离级别,并且效率不高。