简体   繁体   English

MySQL InnoDB插入并选择锁定

[英]MySQL InnoDB insert and select lock

I created a ticketing system that in its simplest form just records a user joining the queue, and prints out a ticket with the queue number. 我创建了一个票务系统,它以最简单的形式记录了一个加入队列的用户,并打印出带有队列号的票证。

When the user presses for a ticket, the following happens in the database 当用户按下车票时,数据库中将发生以下情况

INSERT details INTO All_Transactions_Table
SELECT COUNT(*) as ticketNum FROM All_Transactions_Table WHERE date is TODAY

This serves me well in most cases. 在大多数情况下,这对我很有用。 However, I recently started to see some duplicate ticket numbers. 但是,我最近开始看到一些重复的票号。 I cant seem to replicate the issue even after running the web service multiple times myself. 即使自己多次运行Web服务,我似乎也无法复制该问题。

My guess of how it could happen is that in some scenarios the INSERT happened only AFTER the SELECT COUNT . 我的猜测是,在某些情况下, INSERT仅在SELECT COUNT 之后发生。 But this is an InnoDB table and I am not using INSERT DELAYED . 但这是一个InnoDB表,我没有使用INSERT DELAYED Does InnoDB have any of such implicit mechanisms? InnoDB是否有任何这样的隐式机制?

I think your problem is that you have a race condition. 我认为您的问题是您有比赛条件。 Imagine that you have two people that come in to get tickets. 想象一下,您有两个人来获得门票。 Here's person one: 这是一个人:

INSERT details INTO All_Transactions_Table

Then, before the SELECT COUNT(*) can happen, person two comes along and does: 然后,在发生SELECT COUNT(*)之前,第二个人出现并执行:

INSERT details INTO All_Transactions_Table

Now both users get the same ticket number. 现在,两个用户都获得了相同的票号。 This can be very hard to replicate using your existing code because it depends on the exact scheduling of threads withing MySQL which is totally beyond your control. 使用现有代码很难复制,因为这取决于使用MySQL进行线程的确切调度,这完全超出了您的控制范围。

The best solution to this would be to use some kind of AUTO_INCREMENT column to provide the ticket number, but failing that, you can probably use transactions to achieve what you want: 最好的解决方案是使用某种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

However, whether or not this works will depend on what transaction isolation level you have set, and it will not be very efficient. 但是,这是否有效取决于您设置的事务隔离级别,并且效率不是很高。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM