0

我想做以下事情:

基本上我对事件表有以下设计:

事件:

  • ID
  • 代码
  • 日期

创建新事件时,我想做以下事情:

  • 检查是否有任何可用的代码。如果日期已经过去,则可以使用代码。

    $code1 = select code from event where date_add(date, INTERVAL 7 day) < NOW() AND code NOT IN (select code from event where date_start > NOW()) limit 1

  • 如果代码可用,请获取该代码并将其用于新事件。

    insert into event (code, date) VALUES($code1, NOW())

  • 如果代码不可用,则生成新代码。

问题是我担心当同时创建 2 个事件时,它们都会得到相同的代码。我怎样才能防止这种情况?

目标是为每个事件分配一个 1-100 的代码。所以因为 1-100 只是 100 个数字,我需要回收代码,这就是我检查旧代码以分配给新事件的原因。我希望能够通过回收旧代码为事件分配 1 到 100 的代码。我不想将相同的代码分配给 2 个不同的事件。

4

2 回答 2

0

好的,这是一个很长的镜头,而且我不是数据库人员,所以请谨慎对待我的建议并进行自己的研究...

我认为你想要的是可序列化的交易。基本上,您首先要求MySQL使用SET TRANSACTION ISOLATION LEVEL SERIALIZABLE. 然后,在您的三个步骤之前,您通过运行开始事务START TRANSACTION,并在您的三个步骤之后运行COMMIT

一些进一步的阅读:

我不确定可序列化性产生的开销。希望更熟悉数据库的人可以参与进来。

如果您可以解决您的问题,我个人宁愿这样做而不是使用事务。

于 2012-09-12T15:33:58.153 回答
0

您应该在工作时锁定桌子:

LOCK TABLE event WRITE;
SELECT MIN(code) FROM event WHERE date_add(date_end, INTERVAL 7 day) < NOW()
     AND code NOT IN (SELECT code FROM event WHERE date_start > NOW());
...
INSERT INTO event ...
UNLOCK TABLES;

您还可以保留一个包含所有活动代码的表格(在这种情况下,所有数字都是从 1 到 100)。在这种情况下,您可以INSERT使用单个语句执行以下操作:

INSERT INTO event ( code, <other fields> )
    SELECT MIN(codes.code) AS code, <other values> FROM codes
        LEFT JOIN event ON ( codes.code = event code
        AND ( event.date_end > DATE_ADD(now(), INTERVAL 7 day)
              OR event.date_start >= NOW()) )
    WHERE event.code IS NULL;

这会选择所有未在“活动”事件中使用的代码,并将其中最小的代码插入event(根据需要添加其他字段)。

您也可以使用 subSELECT ( SELECT DISTINCT code FROM event) 代替codes表格,但在这种情况下,您只会选择至少已经使用过一次的代码;任何“新”代码都将被忽略。

上述逻辑的一个副作用是,较大的代码被重复使用的频率较低,即,如果您有 20 个活动事件,它们使用的代码很可能是 1 到 20。如果您想均匀地回收代码,您可以例子SELECT ... ORDER BY RAND() LIMIT 1

于 2012-09-12T15:34:26.740 回答