2016-12-30 98 views
1

目前,我們有一個票務管理系統,就像所有票務系統一樣,它需要以循環方式將情況分配給座席。同時,代理可以應用自己的過濾邏輯並在其隊列中工作。MySql邏輯優化

問題,

  1. 表與門票現在是非常大的,跨越超過1000萬行。
  2. 一張票不應該分配給兩個不同的用戶。
  3. 爲了解決上述問題,這是我們擁有的流量,
  4. 選擇查詢與過濾條件解僱,限制0,1
  5. 上述查詢返回的行然後可以將選定基於ID和鎖定更新。
  6. 最後我們開始更新,說用戶X選擇了這個案例。
  7. 雖然第3步執行其他用戶無法獲得相同的情況下鎖,所以他們發射3.查詢可能會多次獲取下一個可用的情況。
  8. 隨着用戶數量的增加,在步驟4中這個時間越來越高。

我們嘗試在第4步本身的查詢中進行select更新,但它使整個查詢變慢。假設這是因爲select查詢中有大量的行。

問題,

  • 是否有不同的方法,我們需要完全承擔?
  • 會在存儲過程中進行選擇和更新以確保與選擇更新然後更新相同的結果?

P.S - 我問了同樣的問題stackexchange。

+0

是否需要鎖定該行。你也可以在沒有鎖的情況下執行它:通過SELECT讀取一行並獲得舊用戶,並在UPDATE處添加條件WHERE ... AND user = old_user。所以如果更新一行,那麼所有其他進程都可以獲得這張票 –

回答

0

問題是您正在嘗試使用MySQL級別鎖定來確保票證不能分配給多個人。這樣就無法檢測用戶是否鎖定了票證。

我將通過向票據表中添加2個與鎖相關的字段來實現應用級鎖:應用鎖的時間戳和告訴你哪個用戶持有鎖的用戶ID字段。與鎖相關的字段可以保存在另一個表格中(例如購物車可以用於此目的)。

當用戶選擇了票,然後嘗試用一個有條件更新語句來更新這些鎖定字段:代替...

update tickets 
set lock_time=now(), lock_user=... 
where ticket_id=... and lock_time is null 

值由您的應用程序提供。 lock_time is null條件是爲了確保如果票證已被其他用戶選中,則後面的用戶不會覆蓋該鎖定。更新語句後檢查受影響的行數。如果是1,則當前用戶獲得鎖定。如果它是0,則其他人鎖定票證。

如果您在另一個表中具有鎖定數據,那麼在該表中的票證ID字段上放置一個唯一的限制,並使用insert獲取一個鎖。如果插入成功,則獲取鎖。如果失敗,則另一個用戶已鎖定票證。

鎖定通常會持續數分鐘,之後您的應用程序必須釋放鎖定(將鎖定字段設置爲null或從其他表中刪除鎖定記錄)。