Mysql Rails验证唯一性在并发输入上失败
我有一个Mysql Rails验证唯一性在并发输入上失败,mysql,ruby-on-rails,Mysql,Ruby On Rails,我有一个Ticket模型,在字符串属性Ticket\u number validates :ticket_number, uniqueness: true 这是车票号的输入代码 <%= f.number_field :ticket_number, :value => @ticket.ticket_number || (Ticket.exists? ? Ticket.maximum(:ticket_number).next) : 1 , :class => 'form-cont
Ticket
模型,在字符串属性Ticket\u number
validates :ticket_number, uniqueness: true
这是车票号的输入代码
<%= f.number_field :ticket_number, :value => @ticket.ticket_number || (Ticket.exists? ? Ticket.maximum(:ticket_number).next) : 1 , :class => 'form-control' %>
@ticket.ticket_number | |(ticket.exists→ticket.maximum(:ticket_number).next):1,:class=>'表单控件'>
验证似乎如预期的那样工作,但是当我们部署应用程序时,可能有多个用户同时输入票证
,这不应该引起问题(对吗?)我们在数据库(MySQL)中发现了重复的记录(相同的票证号)
到目前为止,在总共600多张门票中,这只发生过一次,但为什么以及如何防止这种情况发生?这是非常罕见的,你可能非常不幸,因为它发生了,这是可能的 阅读: 考虑以下几点: 用户提交表单
- 用户提交表单
- Rails检查数据库中是否存在用户A的现有ID-未找到
- 用户B提交表单
- Rails检查数据库中是否存在用户B的现有ID-未找到
- Rails为用户保存一条记录
- Rails保存用户B记录
我建议在数据库级别(主键)添加一个约束。@Yule-answer非常有用,它解释了为什么会发生这种情况,并且添加数据库级别的约束将防止这种情况发生 这将抛出一个
ActiveRecord::RecordNotUnique
exseption,我当然不希望用户看到它,因此下面就是如何应用@Yule建议的解决方法:
add_index(:tickets, :ticket_number, :unique => true)
当然,控制器的更新操作也应该这样做谢谢你的提示。我一直面临着一个类似的问题,但我担心我无法在数据库级别设置唯一的索引。我还有别的选择吗?谢谢
def create
@ticket = Ticket.new(ticket_params)
if @ticket.save
flash[:success] = 'Ticket was successfully created.'
else
render action: 'new'
end
#catch the exception
rescue ActiveRecord::RecordNotUnique
flash[:danger] = 'The ticket number you entered is already taken !'
render action: 'new'
end