gpt4 book ai didi

mysql - 解决 rails 中的竞争条件(Y 中 X 的数量有限)

转载 作者:行者123 更新时间:2023-11-29 01:04:31 25 4
gpt4 key购买 nike

编辑:使用 MySQL...

假设您有一个可以将学生添加到类(class)的应用程序,而该类(class)的空间有限...所以您可以这样做:

def add
if some_classroom.size < MAX_SIZE
add_student_to_class
end
end

这是多线程环境中的竞争条件。蹩脚的。

假设我们

  1. 不想要这个,并且
  2. 不想锁定我们的教室 table 或记录(这会导致我们的应用程序在其他地方很糟糕)

我们做什么?

我建议:

class Classroom < ActiveRecord::Base
has_one :classroom_lock
after_create :create_lock_record

def create_lock_record
c = ClassroomLock.new
c.classroom = self
c.save!
end
end

class ClassroomLock < ActiveRecord::Base
belongs_to :classroom
end

def add
c = Classroom.first
ActiveRecord::Base.transaction do
c.classroom_lock.lock!
c = Classroom.first #load this again (it might have changed)
if c.size < MAX_SIZE
c.add_new_student(some_student)
else
do_stuff_about_not_enough_room
end
end
end

这看起来应该非常有效。我的(虚构的)Classroom#show 方法不会阻塞,因为教室记录实际上并未锁定,并且 add 方法实际上是单线程的,因为任何其他进程都将被迫在锁定处等待!行直到锁被释放。

这个有用吗?或许?我想是这样?我不知道……

我已经用多个进程同时进行了相当多的锤击,但很难确定(毕竟这是一个竞争条件)。

谁能提供一些额外的见解?

最佳答案

你好,

我想象一个非常简单的 SQL 方法,只有一个警告:添加一个名为 list_position 的额外列,并向包含 的 classroom-student-relation-table 添加一个唯一索引classroom_idstudent_idlist_position

通过将 list_position 设置为类(class)学生人数加一来插入。 Ruby 代码可能会在某个地方

classroomStudent = ClassroomStudent.new
classroomStudent.list_position = classroom.size + 1
until classroomStudent.save
classroomStudent.list_position += 1
do_stuff_about_not_enough_room if classroomStudent.list_position > MAX_SIZE
end

结果:如果两个插入尝试同时将一个学生插入同一个类(class),则唯一索引会将一个学生排除在外(INSERT 失败)。这意味着您可能必须重试直到 list_position=MAX_SIZE,但可以保证类里面的学生永远不会太多。您也可以使用这种方法来建立等待队列。

如果您的关系表中已有数据,您必须先为 list_position 添加一个值。我猜是这样的

UPDATE ClassroomStudents AS c1 SET c1.list_position = COALESCE((SELECT MAX(c2.list_position) FROM ClassroomStudents AS c2 WHERE c2.classroom_id = c1.classroom_id), 0) + 1;

会在这里完成这项工作,尽管它可能有点慢。

我知道该解决方案仍有一些粗糙的边缘,但也许它会有所帮助。

问候

优化

关于mysql - 解决 rails 中的竞争条件(Y 中 X 的数量有限),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9535800/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com