如何安全地处理最大参与者数量?

时间:2017-11-24 06:50:45

标签: sql postgresql sqlite

我们有:

  • Room
  • Person
  • 中间表PersonRoom
<{1>} Room我的最大 Person,相当于可以进入房间的最多人数。 像这样:

Room
  id
  maximum_persons
Person
  id
  name
PersonRoom
  id
  room_id
  person_id

每次有&#34; my_person_id&#34;我想和#34; my_room_id&#34;进入一个房间,我应该这样做:

INSERT INTO PersonRoom (room_id, person_id)
                VALUES (my_room_id, my_person_id)

如果房间已满,我不应该插入一个人即我应该做的事情(我知道这不是有效的SQL ):< / p>

@TOTAL = SELECT COUNT(*) FROM PersonRoom
         WHERE room_id = my_room_id;
IF @TOTAL < (SELECT maximum_persons) FROM Room WHERE id = my_room_id:
    INSERT INTO PersonRoom (room_id, person_id)
                    VALUES (my_room_id, my_person_id)

我想在数据库端处理这个问题

  • SQLite有解决方案吗?如果没有,是否有PostgreSQL的解决方案
  • SQL会是什么?
  • 如果我在一次交易中执行此操作,如果有很多人尝试同时注册同一个房间,那么它是否100%安全?

2 个答案:

答案 0 :(得分:1)

在SQLite中,您可以使用trigger

来阻止此操作
CREATE TRIGGER max_persons_check
BEFORE INSERT ON PersonRoom
WHEN (SELECT COUNT(*) FROM PersonRoom WHERE room_id = NEW.room_id)
  >= (SELECT maximum_persons FROM Room WHERE id = NEW.room_id)
BEGIN
  SELECT RAISE(FAIL, "too many persons in this room");
END;

或者只是执行查询以在代码中进行检查。 (在SQLite中,所有事务都是可序列化的。)

答案 1 :(得分:0)

我只能代表PostgreSQL。

有两种解决方案:

  1. 在一个事务中运行SELECTINSERT,并在执行personroom之前锁定表SELECT

    您需要ACCESS EXCLUSIVE锁定模式,这意味着所有此类操作都已序列化。这对并发性有害,但简单而安全。

  2. 在一次SELECT交易中运行INSERTSERIALIZABLE

    这将允许并发修改,但仍然可以防止在序列化执行顺序中不可能发生的任何事情。如果存在冲突,其中一个事务将收到序列化错误,并且必须重试该事务。