各位好
小弟目前碰到可能超賣的問題
上網找了不少資料
但由於mysql資料庫版本非常舊還有一些因素
redis不給裝
也不能用unsigned型態 和 innodb
這讓我不能走transaction這方向
所以小弟想到一個方法
就是假設現在賣A商品限量30個
我先開一個table item_detail
把這30個都塞進去
用一個primary key區別開
當使用者要下訂的時候
會直接從這資料表找沒有賣出(狀態有欄位會記)的商品
並把他的primary key插入到 另一個table order的同樣也是primary key的欄位中
由於mysql會檢查 primary key的重複性
當有人同時操作時
一定不會發生同時下訂同一商品的狀況
而且也不會超過item_detail的總數
但由於還沒實際開放
所以先上來問一下各位大大
小弟這想法會碰到什麼問題嗎?
你的想法不錯,只是做法不好。
如果當有一堆商品且數量都高達1000以上的情況下,這樣做就不太合適。
以前的購物車做法給你參考。
商品欄位會區分「庫存量」「等待售出庫存量」
在下訂商品的當下,就會產生訂單。並將「庫存量」扣除到「等待售出庫存量」
訂單狀態會是在等待確認的情況。「等待確認單」最多只會等15分~1個小時(時間當時設計給業主自行設定)。
當一個小時超過還沒進入「確認」的情況下。
會將該單列為取消單。並將原本在「等待售出庫存量」轉回「庫存量」
在同時間同時下訂的情況下。基本當下會鎖表處理。
感謝大大回覆
我嘗試看看鎖表好了
可是如果我用寫鎖
這樣是不是會導致其他使用者在抓資料的時候卡住
目前商品的table就會變成
欄位:商品編號,商品名稱,價格,庫存數,等待售出庫存量
當第一個連線進來時
會鎖住這個table
同時剛好進來購買頁面的資料是否就會抓不到?
(剛開始有抓這個table來秀相關的資料)
鎖表只在「庫存量」「等待售出庫存量」兩者之間轉換時處理。
時間不會超過1秒,誰叫你一直鎖的。想操爆你的主機啊。
鎖表之後,連查尋都不行的。
鎖表的目的只是為了不要發生讀取錯誤的庫存。
鎖表你要想像所有在用任何這張表的操作。都會變成等待。
雖然叫你用鎖表,但不要隨便鎖表。
其實現在有點害怕教你用鎖表。
哈哈
我前面沒講清楚
抱歉造成大大誤解
我的第一個連線是第一個使用者下單
據我目前的理解
就是送 update query前lock table
執行完unlock
所以我原本的意思是
當第一個使用者下單時
扣庫存那一時刻已經鎖表狀態中(1秒內)了
另一個使用者剛好進頁面讀取資料
這樣是不是就會抓不到了
他會等待到超時或是unlock。不會發生抓不到。(雖然超時就會了沒錯)
我上面說不要超過1秒內。但其實光等待0.5秒就很容易發生可怕的事了。如果人數多的話會更是可怕。
每開啟這個限量商品就從資料庫中取得限量的水號,資料庫同時也標記這筆記錄已被取走,記錄取用時間並更新回資料庫,這時並不代表交易已經完成,只是在取得交易流水號的動作而已,在完成交易後再更新這筆交易編號的狀態為已售出,如果用戶中途離線或交易過久,你的後端再把標記時間超過10分鐘但尚未標記完成交易的記錄收回並重新發給客戶端使用(放SESSION),直到所有水號都已經更動狀態成售出為止
這就不會發生超量的問題
有人會說要是有人故意多開瀏覽器來佔水號,那你不會做同IP只能取一次啊?或是讓用戶必需加入會員,每一會員只能同時開一個..
這只是我的做法,別人或有別的想法,你參考看看
我怎麼覺得,應該先解決 MYSQL 問題,也不能用unsigned型態 和 innodb
,這基本東西不處理掉,沙灘上蓋大樓,安穏嗎?
我並不主張追求太太太新的東西,但對於太太太舊的古董則十分排斥,有些時候,新工具一行或一分鐘能解決的問題,老古董可能得花好幾十倍的心力。