台灣最大程式設計社群網站
線上人數
974
 
會員總數:246136
討論主題:189720
歡迎您免費加入會員
討論區列表 >> ASP.NET >> 在一個規劃不當的系統中, 限制報名人數
[]  
[我要回覆]
回應主題 加入我的關注話題 檢舉此篇討論 將提問者加入個人黑名單
在一個規劃不當的系統中, 限制報名人數
價值 : 500 QP  點閱數:3554 回應數:24
樓主

小羊窒息
高級顧問
52736 128
20940 5959
發送站內信

捐贈 VP 給 缺氧的羊:窒息
在一個規劃不完美的系統中, 限制報名人數



前言:

這是一個 ... 至民國93年 運作至今的系統(那一年是我的大學畢業年)
使用的是SQL Server 2000

這個系統有提供[報名功能]
讓民眾填寫資料

================

情境(系統機制)說明:
以往系統都是限制30人為上限, 滿了之後就不允許再報名
(註:進行限制的 只有人數,沒有座位問題,而且人數會有踢除情形)

例如:路人1 ~ 路人29 跑來填寫報名資料,
然後路人30也跑來填寫完了,

接著路人31就沒辦法再填了
(系統會檢查現有人數,發現已達30人,就不提供了)

當路人1 ~ 路人30 因為某些原因不被允許報名時,會有人工審核機制,將其退件
(就是將某一個報名狀況的欄位,設為 bad)

這時,系統在統計人數時,會因為有人被退件了,而認定人數不滿30人,
於是路人31...就可以報名

最後開班時,報名記錄表通常不會只有30名路人,
但有效報名資料只會有30人
(也就是說有人被退件之後,是允許第31人的)
================
問題說明:
由於近幾年【班班爆滿】,
有如pchome home限時搶購一般(數萬筆電只賣數千,限3台)
每天只要一開班(系統時間到自動開放報名,時間沒到之前點了頁面什麼都看不到),
不用3分鐘,馬上額滿...

也因此,出現了臨界問題(同一時間有多人同時送出資料,造成硬是有第31人完成報名)

這時的【路人1】 ~ 【路人31】都是有效報名
雖然會有人工處理,將第31人剔除,也有報名前的說明文字,
但第31人通常都會打電話來大罵:【黑箱作業】


目前已知是報名機制不完整的關係
而且不可能整個翻掉重新設計(成本太昂貴)


簡單來說, 目前的機制如下...
1. 報名時(開始填資料前),檢查總人數,超過就擋掉
2. 報名資料送出時,檢查總人數,超過就擋掉

聰明的朋友們看到上面2點一定馬上就笑出來了,
因為檢查人數完,在存資料之前,只要遇到下一個也準備要存資料,
馬上就會破功

例如:
→【路人30】送出報名資料
→檢查總人數29,可以寫入
→【路人31】送出報名資料
→檢查總人數29,可以寫入
→【路人30】報名資料儲存完畢
→【路人31】報名資料儲存完畢

真是太讚了~~~Bug就這樣出現了,第31人就這麼報完名了


在開發新系統時所能想到的...諸多【美好的理論】無法實行的情況下,
只能想一些配套方案...


原本我還想在資料庫設定 不得重複的欄位(班級,座號),
但原本的資料表當中沒有座號(想用程式計算指定座號,以便讓資料庫自動擋掉重複的也不行)
再者,如果真的把座號加進去...要是目前只有10個人報名,
然後同時有2個人填資料,造成2個人都被系統自動算出11號,
反而會讓另1個應該可以報名成功的人就這麼的失敗了...


因此∼∼∼我把問題丟上來給大家參考參考∼


搜尋相關Tags的文章: [ 重複報名 ] , [ 報名人數 ] ,
本篇文章發表於2012-02-04 16:42
== 簽名檔 ==
[再難的程式,當你知道怎麼寫時,就很簡單,問題就在於不知道怎麼寫]
[當你辛辛苦苦,嘔心瀝血,寫出一支你覺得沒有人寫的出來的程式時,
你會發現,早就已經有人寫出來了,不但寫的更好,而且還提供Source Code]
[Suffocation Sheep]

厚黑學鋸箭法:
鋸箭法是說有人中了箭,請外科醫生治療,
外科醫生把箭幹鋸了,然後就說弄好了,剩下的箭頭請找內科醫生…
1樓
最有價值解答

香帥
檢舉此回應
可以這樣做:
Application.Lock()
呼叫寫入資料庫副程式
Application.UnLock()

寫入資料庫副程式:
if 報名人數欄位>29跳離副程式
開始寫入 (報名人數欄位+1)於資料庫
跳離副程式

本篇文章回覆於2012-02-04 17:03
== 簽名檔 ==
--未登入的會員無法查看對方簽名檔--
2樓
回應

No.18
捐贈 VP 給 No.18 檢舉此回應
如果(2)反過來做呢

一開始先都insert進去
insert完後,接著再依據insert結果後的time做order by 決定是否在報名數量的範圍內
若該筆資料依insert 的itme order by後
順位已超出限制,則再一次更新為bad,決定最後是否報名成功



本篇文章回覆於2012-02-04 17:20
== 簽名檔 ==
--未登入的會員無法查看對方簽名檔--
3樓
作者回應

小羊窒息
捐贈 VP 給 缺氧的羊:窒息 檢舉此回應
to 2樓,

現在上面是要防止寫入
(人工剔除跟自動剔除基本上是一樣的,只是時間差的問題)

而且剔除之後,是有公開的(看的到所有報名者的順序,以及剔除者,還有被剔除的原因,時間點等等。。。)
===============
原則上1樓的寫法可以試
(雖然報名時新增的資料不只上面那些,但有機會包在一起執行...)
本篇文章回覆於2012-02-04 17:46
== 簽名檔 ==
--未登入的會員無法查看對方簽名檔--
4樓
不錯的參考

No.18
捐贈 VP 給 No.18 檢舉此回應
2F的做法,依然是在整個報名流程中做的動作,而不是事後做喔,因此自動剔除後,可以即時性就feedback使用者最終報名結果

假設名額剩下1個
當甲,乙點選課程時,一開始會看到都還有名額,接著甲,乙開始填單了,然後送出報名資料
這時甲,乙的insert data command 會進入SQL SERVER 執行COMMAND的排程中,
所以甲,乙的資料insert到table後,一定就有前後時間記錄,因此insert完後緊接著做order by time
的動作,就可以知道誰的資料有在數量限制內,假設甲的data time記錄比較早,所以甲的報名feedback訊息就是報名成功
,而乙的data time記錄比較晚,所以乙的data除了update bad之外,乙的報名feedback訊息就是報名失敗








本篇文章回覆於2012-02-04 17:56
== 簽名檔 ==
--未登入的會員無法查看對方簽名檔--
5樓
回應

No.18
捐贈 VP 給 No.18 檢舉此回應
另提一點
”上面是要防止寫入”,也可以在得知報名不在數量內時,做delete data的動作


PS:1F提的Application.Lock()也是一種解法
本篇文章回覆於2012-02-04 17:58
== 簽名檔 ==
--未登入的會員無法查看對方簽名檔--
6樓
作者回應

小羊窒息
捐贈 VP 給 缺氧的羊:窒息 檢舉此回應
事後刪除...

我確認一下哦~~

1. 使用者送出資料
2. 檢查到未滿30筆
3. insert 報名資料
4. (新增完之後) select 整班的報名資料, 並且 order by time (其實表單有流水號可以直接order by)
5. 把select到的資料 拿來跟自己的填寫資料做比對, 看自己是第幾筆
6. 如果自己的資料不在 30筆之內, 就直接提示[報名失敗(已額滿)], 然後再把那筆刪掉


應該是這樣子吧...
本篇文章回覆於2012-02-04 20:48
== 簽名檔 ==
--未登入的會員無法查看對方簽名檔--
7樓
不錯的參考

No.18
捐贈 VP 給 No.18 檢舉此回應
我想的流程,差不多是這樣

1. 報名前先檢查滿不滿30滿,若已滿,基本上連報名都不用了,因為沒有名額了
2. 當1不成立時,可以點報名,開始填資料,使用者送出資料
3. 直接就insert 報名資料(此時先不管有沒有滿)
4. (新增完之後) select 整班的報名資料, 並且 order by time (其實表單有流水號可以直接order by)
5. 把select到的資料 拿來跟自己的填寫資料做比對, 看自己是第幾筆
6. 如果自己的資料不在 30筆之內, 就直接提示[報名失敗(已額滿)], 然後再把那筆刪掉

本篇文章回覆於2012-02-04 21:34
== 簽名檔 ==
--未登入的會員無法查看對方簽名檔--
8樓
回應

Allen
捐贈 VP 給 Allen 檢舉此回應
我是民國81年畢業....
本篇文章回覆於2012-02-05 01:03
== 簽名檔 ==
--未登入的會員無法查看對方簽名檔--
9樓
回應

阿源哥哥
捐贈 VP 給 阿源哥哥 檢舉此回應
我是民國89年畢業,所以比較年青~~~~
本篇文章回覆於2012-02-05 08:15
== 簽名檔 ==
--未登入的會員無法查看對方簽名檔--
10樓
作者回應

小羊窒息
捐贈 VP 給 缺氧的羊:窒息 檢舉此回應
這個系統很有趣~

其實系統一開始沒有限人數的(而且有分班的功能, 人數過多可以自動分成多個班)

自從某一年....不知道什麼原因, 開始爆滿...1班可以爆到數百人
(跟本沒辦法開班了...)
於是就決定加上人數限制


而人數限制後來加上去之後, 陸續就出現了臨界值的問題,
一開始也都還好, 就多1個~2個...不影響開班,
但是沒擠進來的就不太爽了...
因為當時是一次就【開1整年的班】
然後...【年底的班在年初就額滿了】...............
所以, 擠不進來的就開始打電話來罵:為什麼xx班31人, 為什麼可以多1人, 你們是不是給人家偷偷開放報名


這下子事情就大條了...... =.=


而我能做的就是, 一直補強, 一直補強, 一直補強...

==================================

目前可用方式2種(在不翻掉的情況下,有2種修補方式)
我再找時間試試吧∼

裡面的某些SQL的parameter程式碼還是拉元件出來,所產生的 XD,
那些我連改寫都懶的改,原始的部份能不動就直接留著,只有自己補強的部份才用自己的



(我很好奇阿源哥跟Allen對於這類的。。。現成的系統,不曉得有什麼看法,
會選擇翻掉嗎,還是有什麼樣的補強方式呢?)
本篇文章回覆於2012-02-05 13:17
== 簽名檔 ==
--未登入的會員無法查看對方簽名檔--
11樓
回應

Bill
檢舉此回應
在記憶體中排Queue ?
本篇文章回覆於2012-02-05 16:17
== 簽名檔 ==
--未登入的會員無法查看對方簽名檔--
12樓
作者回應

小羊窒息
捐贈 VP 給 缺氧的羊:窒息 檢舉此回應
to bill

在現行架構不去更動的狀況下,我還真不知道怎麼去利用Queue
本篇文章回覆於2012-02-05 21:33
== 簽名檔 ==
--未登入的會員無法查看對方簽名檔--
13樓
不錯的參考

topcat
捐贈 VP 給 topcat 檢舉此回應
小喵第一個想到的是
首先要讓第31個不要發生

建立Transaction
維護的程式,在維護裡面先加上檢查使用者數(這個Select要讓資料Lock起來)
當超過,就直接Rollback

接著,在畫面上加註說明熱門班級,請加快報名程序

這樣第31個就不會看到報名成功的訊息,也就不會有黑箱作業的感受
^_^



本篇文章回覆於2012-02-06 09:02
== 簽名檔 ==
--未登入的會員無法查看對方簽名檔--
14樓
不錯的參考

topcat
捐贈 VP 給 topcat 檢舉此回應
另外一個想法,由於可能中間報名的人後來又不讀了,卻又佔了位置
所以可以考慮在正式班級的資料形成前
中間安插個報名順序資料表
有點類似研究所錄取的方式,有正取與備取

1.資料只要加序號放入這資料表就好
2.顯示時前面30名顯示正取,其他的顯示備取
方式一:人員聯絡前30名確認是否到班
方式二:設定一個期間,讓前面30名完成報到手續,時間到沒有完成的視為棄權,在由人員聯絡備取進行報到

以上是小喵想到的方式,不知道是否合適

^_^

本篇文章回覆於2012-02-06 09:10
== 簽名檔 ==
--未登入的會員無法查看對方簽名檔--
15樓
作者回應

小羊窒息
捐贈 VP 給 缺氧的羊:窒息 檢舉此回應
(會打來抗議的都是.........滿腦子想走後門的人,
真正老實的反而都是不太會用電腦的人, 都是「專案資格」報名的)

加了說明文字, 其實也一樣
(滿腦子想走後門的人才不管你那個說明文, 他只管自己有沒有報到名, 沒報到就去投訴你...)

前一陣子還有人打來說:【「聽說...」只要付點錢就可以報到名】.....

=========
複雜的方式我有想過,翻寫也想過,
只是真的太麻煩了

所以才會有這個:【在一個規劃不完美的系統中, 限制報名人數】


晚一點我整理一下資料,把SQL的處理過程貼出來,增加難度... XD
(先簡單講一下....新增1個報名資料,同時會動到的資料表有4張,很讚的... =.=
1張是詳細報名資料
1張是簡易報名資料
1張是審核記錄表_主檔
1張是審核記錄表_明細)

資料建立過程晚一點再說(這是我接手時就已經存在許久的模式,所以別問我為什麼當初是規劃成這樣子)
先去吃飯~
本篇文章回覆於2012-02-06 12:30
== 簽名檔 ==
--未登入的會員無法查看對方簽名檔--
   

回覆
如要回應,請先登入.