這是 本番環境等等搞砸的人 Advent Calendar 2025 與 Visual Basic Advent Calendar 2025 第17天的交叉發文文章。
在2021年12月,我收到了一個如突襲工程般的應用程式製作請求。
在工廠運行的系統中,數據會保存在本地端,但可以透過一個名為介面的程式傳遞參數,以訪問伺服器進行身份驗證或將實績數據存入DB,共設有8個命令。
伺服器端的架構為IIS + Classic ASP(VB) + PostgreSQL。
這次要製作的應用程式是該介面的縮小版,身份驗證命令等無論輸入什麼都會回傳OK,目的是將實績數據存入DB,實際上只需兩個命令。
將存入DB的表格重新構建,將功能別分開的表格進行整合。
伺服器端的架構保持不變,我再次使用了Classic ASP(VB)進行開發。
客戶端的程式(C#)則使用相同的程式,僅需在設定中切換IIS的別名即可。
由於不需要與其他功能進行聯動,従來使用的批次序號(字母數字36進制+序號的獨特規範)也選擇採用PostgreSQL的序列。
每天最多2000件,因此32位元值(2,147,483,647)足以支撐100萬天,完全沒有問題。
從構思到兩週後(2021/12/20),雖然在規格上有些小出入,但修正後順利上線。
隨著年末的臨近,將進行一段時間的驗證使用。
約5個月後的2022/05/17 9:00上班時,工廠報告指出,自07:16:23之後出現故障,已經切換為非連動。
工廠的運作是優先事項,無法生產將會引起重大問題。如果介面出現問題導致系統無法運行,則可以切換到非連動模式。當然,這段時間內的實績數據將不會存入DB。
我遙控進入工廠的伺服器查看錯誤日誌...
Log\HttpResLog-20220517-071623.txt
錯誤 '800a0006' 溢出。: 'CInt'
PostgreSQL的序列數值已經達到32768。
錯誤發生在'CInt'部分。
批次序號的值達到32768,在CInt轉換過程中發生了溢出。
Public Sub GetLotSerial(ByRef retCode, ByVal key)
If CInt(RS("LOTSERIAL")) <> 0 Then
由於平常使用C#進行開發,所以我完全忘記了,Classic ASP(VB)的Integer型別仍然是16位元。
| 型別 | 最小值 | 最大值 |
|---|---|---|
| Integer | -32768 | 32767 |
| Long | -2147483647 | 2147483648 |
將轉換型別更改為Long型別。
Public Sub GetLotSerial(ByRef retCode, ByVal key)
If CLng(RS("LOTSERIAL")) <> 0 Then
實際上不僅如此,主管還指示必須處理Long型別超過最大值的錯誤情況。
測試規格書中也增加了超過編號最大值的測試。
我完全沒有考慮到超過編號最大值的測試。
32位元值(2,147,483,647)足夠支撐100萬天,根本不成問題。
事後才得知,其實系統還在試運行階段。因此並未造成重大問題。
順帶一提,隨著2024年轉換到Windows Server 2022,使用Classic ASP(VB)所製作的應用程式已經改寫為ASP.NET(C#)及Blazor Server。