我想做以下事情:
基本上我对事件表有以下设计:
事件:
创建新事件时,我想执行以下操作:
检查是否有可用的代码。如果日期已经过,则可以使用代码。
$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个不同的事件分配相同的代码。
答案 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
。