Matrix第4部分和MySql困境

时间:2012-09-12 15:06:02

标签: php mysql

我想做以下事情:

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

事件:

  • 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个不同的事件分配相同的代码。

2 个答案:

答案 0 :(得分:0)

好的,这是一个很长的镜头,而且我不是一个数据库人员,所以请大家带着我的建议进行自己的研究......

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

进一步阅读:

我不确定可序列化产生的开销。希望有更熟悉数据库的人可以填补。

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

答案 1 :(得分: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