2012-09-12 32 views
0

我要做到以下幾點:矩陣部分4和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個不同的事件。

+0

這段代碼代表邏輯明智嗎?看起來事件可以很容易地具有與另一個相同的代碼,因爲您的第二步就是這樣。你是從字面上給事件另一個代碼。 – thatidiotguy

回答

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表,但在這種情況下,您只會選擇至少已經使用過一次的代碼;任何「新」代碼都將被忽略。

上述邏輯的一個副作用是較大的代碼重用次數較少,也就是說,如果您有二十個活動事件,則可能是他們使用的代碼是1到20.如果您反而想要均勻地回收代碼,你可以例如SELECT ... ORDER BY RAND() LIMIT 1

+0

如果插入是更新狀態,而不是如何更改您必須更新語句代碼的插入代碼?像更新事件SET ... – jewelwast

+0

更新?但是你創造了一個事件......也許你需要澄清你的問題並提供一個完整的例子。 – LSerni

+0

無論如何,LOCK TABLE方法會起作用。 – LSerni

0

好吧,這是一個長鏡頭,我不是一個數據庫的人,所以把我的建議與一粒鹽,做自己的研究...

我想你想要的是序列化交易。基本上,您首先要求MySQL使用SET TRANSACTION ISOLATION LEVEL SERIALIZABLE來生成transaction isolation serializable。然後,在您的三個步驟之前,您通過運行START TRANSACTION開始交易,並在您執行三步後運行COMMIT

一些進一步閱讀:

我不知道的串行化會帶來的開銷。希望有人更熟悉數據庫可以芯片英寸

如果你能解決你的問題,我個人寧願做比使用交易。