第345章 集成測試!兩百萬條數據!資料庫鎖的陷阱!
2004年四月二十三號。周五。
早上七點四十五。工作室。
林遠到的時候,張浩然已經在測試區了——兩台伺服器並排擺著,網線連到同一台交換機上,屏幕上跑著資料庫初始化腳本。
"環境搭好了?"
"昨晚九點搭完。"張浩然說,"PostgreSQL,兩張測試表——一張跑引擎,一張跑數據採集。數據已經導入了。"
"多少條?"
"兩百零三萬條。製造企業的五年財務數據——從一九九八年到二零零二年。資產負債表、利潤表、現金流量表,加上附註明細。"
林遠看了看屏幕上的資料庫統計。"數據格式呢?"
"混合的。百分之六十是XBRL格式,百分之二十五是XML,百分之十五是Excel導入的CSV。和德勤要求的真實場景一致。"
"好。"林遠把背包放下,走到白板前。
白板上的進度還停在昨天的狀態——四個一百 percent。他在下面加了一行:
集成測試:Day 1 — 目標:四標準並行,兩百萬條數據,跑完全量
"趙強。"
趙強抬頭。
"今天集成測試,你負責監控。所有日誌都留——性能指標、錯誤信息、上下文切換記錄。任何異常都不要跳過。"
"明白。"
"周凱,調度器層面你盯著。四套標準的審計程序交叉執行時,關註上下文隔離有沒有被破壞。"
"好。"
"王晨、李哲,前端展示層同步測試——引擎跑出來的審計底稿,前端能不能正確渲染。"
"收到。"
林遠掃了一眼所有人。
(由於緩存原因,請用戶直接瀏覽器訪問 海量好書在 TW 看書網,𝘴𝘩𝘶.𝘵𝘸等你讀 網站,觀看最快的章節更新)
"開始。"
八點三十分。
張浩然按下執行鍵。
四套標準同時加載——美國政府會計、國際財報準則、國際審計準則、安全標準體系。調度器按照預設的審計程序列表,開始分發任務。
屏幕上,四個進度條同時啟動。
林遠站在後面看。前十分鐘,一切正常。數據採集層從資料庫里讀取記錄,分發給四個標準模塊。每個模塊獨立運行審計邏輯,生成中間結果。
"第一條記錄通過。"張浩然說。
"第十條。"
"第一百條。"
"第五百條——速度穩定。"張浩然看了一眼計時器,"每秒處理四百二十條。"
"每秒四百二十條。"林遠算了一下,"兩百萬條——大概八十分鐘。一個半小時。"
趙強說:"單標準測試的時候是每秒五百條。四個並行是四百二十——下降了百分之十六。"
"在無鎖調度器的預期範圍內。"林遠說,"上下文切換有開銷,百分之十六可以接受。繼續跑。"
上午十一點。
進度條走到了百分之三十七。
"速度還在四百二。"張浩然說。
"內存呢?"
"穩定。引擎占用八百二十兆,資料庫占用一點四個G。沒有泄漏。"
林遠點頭。"中午輪流吃飯。測試不停。"
下午兩點。
進度條走到了百分之六十四。
"速度——"張浩然皺眉。
"多少?"
"掉到每秒三百一十條。"
林遠走過去。"什麼時候開始掉的?"
"大概半小時前。從百分之五十開始——四百二掉到三百八,然後三百五,現在三百一。"
"內存呢?"
"內存在漲。引擎從八百二十兆漲到了一點一個G。資料庫——"張浩然看了一眼,"資料庫從一點四個G漲到了兩個G。還在漲。"
趙強已經打開了日誌終端。他沒有說話,手指在鍵盤上快速敲擊,調出了過去半小時的資料庫寫入日誌。
一分鐘。兩分鐘。
"找到了。"趙強說。
所有人看向他。
"資料庫寫入瓶頸。"趙強把日誌投到投影屏上。紅色的警告條目密密麻麻。
"四個標準同時寫審計結果到同一張表——audit_results。每條記錄寫入時,PostgreSQL對目標行加排他鎖。四個標準同時寫同一批審計對象的行——行鎖衝突。"
林遠看著屏幕上紅色的鎖等待記錄。
"等一下——四個標準審計的是同一批財務數據,但輸出的是不同的審計底稿。它們的寫入目標應該是不同的行。"
"理論上是這樣。"趙強說,"但調度器的寫入邏輯是——每個審計程序完成後,先寫入中間結果到audit_results表,標記標準類型和程序編號。問題是——中間結果的行ID是自動遞增的,四個標準同時插入時,PostgreSQL的B-tree索引對自增主鍵的寫入產生了頁級鎖競爭。"
"自增主鍵的頁級鎖——"林遠理解了。
四個標準同時往同一張表里插入數據,自增主鍵意味著所有插入都集中在B-tree索引的最後一個頁面上。四個並發寫入爭搶同一個頁面的寫鎖——這就是性能持續下降的原因。
"數據量越大,索引頁面越滿,鎖等待越嚴重。"趙強說,"到後面會越來越慢。如果不處理,兩百萬條跑完可能要五到六個小時。"
"不能接受。"林遠說。
兩點半。
林遠坐在工位上,打開墨鋒,畫了一張架構圖。
"分庫寫入。"他說。
趙強、張浩然、周凱圍過來。
"auditresults表拆成四張——auditgasb、auditifrs、auditisa、audit_soc2。每個標準的結果寫到自己的表里。自增主鍵仍然有,但四張表的索引頁面互不干擾。"
"寫入衝突直接消除。"趙強說。
"對。匯總的時候——"林遠在圖上畫了一條虛線,"最終輸出階段,四張表的結果按審計對象ID合併。合併邏輯放在輸出層——反正輸出層本來就要把四個標準的底稿整合成一份報告。"
"代碼改動量呢?"張浩然問。
"調度器的寫入接口——從單一audit_results改成四個。"林遠說,"輸出層的合併邏輯加一個union操作。其他不動。"
"我來改調度器。"張浩然說。
"輸出層我來。"周凱說。
趙強說:"改完之後,我需要重新跑已經完成的百分之六十四嗎?"
"不需要。"林遠說,"已經寫入的數據是完整的——只是寫入速度慢,數據本身沒有錯誤。從斷點繼續。"
"明白。"
三點十五分。
張浩然和周凱改完代碼。
趙強重啟測試。
"從百分之六十四繼續。"
進度條重新啟動。
"每秒——"張浩然看著計時器。
"四百八。"
趙強說:"比剛才快了。因為已經寫入的數據少了,新表的索引頁面還空曠。"
"到百分之八十的時候再看。"林遠說,"索引頁面填滿之後的性能才是真實水平。"
下午五點。
百分之八十三。
"速度穩定在四百六。"張浩然說。
"內存呢?"
"引擎一點零五個G。資料庫一點八個G。穩住了。"
林遠看了看趙強。
趙強看了一遍日誌。"沒有鎖等待警告。B-tree索引的頁級競爭消除了。"
"從三百一到四百六——性能提升了百分之四十九。"
"理論上應該更高。"趙強說,"分庫之後,四個標準的寫入完全獨立。剩下的百分之十六差距來自上下文切換和資料庫連接池的開銷——這部分是架構層面的固有成本,無法消除。"
"百分之八十四的並行效率。"林遠說,"可以接受。"
"兩百萬條跑完需要多久?"張浩然問。
林遠算了一下。"剩餘百分之十七,按每秒四百六計算——大概六十五分鐘。六點多跑完。"
"今天能出第一份完整測試報告。"趙強說。
"對。"林遠說,"全量跑完之後——看四個標準的審計結果有沒有衝突。這是集成測試的第二階段:結果一致性校驗。"
五點二十分。
蘇明遠從辦公室出來。
"德勤那邊來郵件了。"
"韓委員?"
"韓委員轉發的——David Morrison的行程確認。"蘇明遠打開郵箱,"2004年五月十一號上午到北京,住中國大飯店。2004年五月十二號全天——上午九點到下午五點,我們的演示時間。下午五點半的航班飛上海。"
"也就是說——我們只有八個小時。"
"八個小時。"蘇明遠說,"包括午餐。"
"夠了。"林遠說,"演示內容我們已經準備得差不多了——四標準並行審計、FPGA加速、版本化配置包。八個小時足夠完整展示。"
"但演示之前——集成測試必須通過。"
"對。"林遠說,"今天跑完全量。周末做結果一致性校驗。下周一出測試報告。"
"時間線呢?"
"2004年五月十號之前——Demo穩定版就緒。2004年五月十一號——我們做一遍內部預演。2004年五月十二號——正式上場。"
蘇明遠點頭。"我去回復韓委員。"
晚上六點四十五。
"跑完了。"張浩然說。
兩百零三萬條數據。四套標準並行。總耗時——六個半小時。其中分庫方案之前的部分用了三個半小時,之後的部分用了三個小時。
"總吞吐量——每秒三百四十八條。"趙強說,"加權平均。"
"內存峰值?"
"引擎一點二個G。資料庫兩個G。穩定。沒有泄漏,沒有崩潰。"
"錯誤呢?"
趙強翻了一遍日誌。"零錯誤。兩百零三萬條數據,四套標準,八百一十二萬次審計執行——零錯誤。"
工作室里安靜了幾秒。
林遠說:"第一階段通過。明天——結果一致性校驗。"
趙強說:"我有預感——那裡才是真正的問題所在。"
"我知道。"林遠說,"兩百萬條數據跑完不出錯——說明工程層面是穩的。但四個標準的審計結果之間有沒有邏輯矛盾——那是設計層面的問題。"
"設計層面的問題——比工程層面的難修。"
"對。"林遠說,"所以明天開始——才是真正的硬仗。"
他看了看白板。
集成測試 Day 1:完成
- 吞吐量:348條/秒(加權)
- 錯誤率:0
- 關鍵修復:分庫寫入,消除資料庫鎖競爭
- 並行效率:84%
下一步:結果一致性校驗(Day 2)
八天。白皮書。二十天。演示。二十六天。開發完成。
今天第一天——資料庫鎖的陷阱。
明天——邏輯一致性的迷宮。
早上七點四十五。工作室。
林遠到的時候,張浩然已經在測試區了——兩台伺服器並排擺著,網線連到同一台交換機上,屏幕上跑著資料庫初始化腳本。
"環境搭好了?"
"昨晚九點搭完。"張浩然說,"PostgreSQL,兩張測試表——一張跑引擎,一張跑數據採集。數據已經導入了。"
"多少條?"
"兩百零三萬條。製造企業的五年財務數據——從一九九八年到二零零二年。資產負債表、利潤表、現金流量表,加上附註明細。"
林遠看了看屏幕上的資料庫統計。"數據格式呢?"
"混合的。百分之六十是XBRL格式,百分之二十五是XML,百分之十五是Excel導入的CSV。和德勤要求的真實場景一致。"
"好。"林遠把背包放下,走到白板前。
白板上的進度還停在昨天的狀態——四個一百 percent。他在下面加了一行:
集成測試:Day 1 — 目標:四標準並行,兩百萬條數據,跑完全量
"趙強。"
趙強抬頭。
"今天集成測試,你負責監控。所有日誌都留——性能指標、錯誤信息、上下文切換記錄。任何異常都不要跳過。"
"明白。"
"周凱,調度器層面你盯著。四套標準的審計程序交叉執行時,關註上下文隔離有沒有被破壞。"
"好。"
"王晨、李哲,前端展示層同步測試——引擎跑出來的審計底稿,前端能不能正確渲染。"
"收到。"
林遠掃了一眼所有人。
(由於緩存原因,請用戶直接瀏覽器訪問 海量好書在 TW 看書網,𝘴𝘩𝘶.𝘵𝘸等你讀 網站,觀看最快的章節更新)
"開始。"
八點三十分。
張浩然按下執行鍵。
四套標準同時加載——美國政府會計、國際財報準則、國際審計準則、安全標準體系。調度器按照預設的審計程序列表,開始分發任務。
屏幕上,四個進度條同時啟動。
林遠站在後面看。前十分鐘,一切正常。數據採集層從資料庫里讀取記錄,分發給四個標準模塊。每個模塊獨立運行審計邏輯,生成中間結果。
"第一條記錄通過。"張浩然說。
"第十條。"
"第一百條。"
"第五百條——速度穩定。"張浩然看了一眼計時器,"每秒處理四百二十條。"
"每秒四百二十條。"林遠算了一下,"兩百萬條——大概八十分鐘。一個半小時。"
趙強說:"單標準測試的時候是每秒五百條。四個並行是四百二十——下降了百分之十六。"
"在無鎖調度器的預期範圍內。"林遠說,"上下文切換有開銷,百分之十六可以接受。繼續跑。"
上午十一點。
進度條走到了百分之三十七。
"速度還在四百二。"張浩然說。
"內存呢?"
"穩定。引擎占用八百二十兆,資料庫占用一點四個G。沒有泄漏。"
林遠點頭。"中午輪流吃飯。測試不停。"
下午兩點。
進度條走到了百分之六十四。
"速度——"張浩然皺眉。
"多少?"
"掉到每秒三百一十條。"
林遠走過去。"什麼時候開始掉的?"
"大概半小時前。從百分之五十開始——四百二掉到三百八,然後三百五,現在三百一。"
"內存呢?"
"內存在漲。引擎從八百二十兆漲到了一點一個G。資料庫——"張浩然看了一眼,"資料庫從一點四個G漲到了兩個G。還在漲。"
趙強已經打開了日誌終端。他沒有說話,手指在鍵盤上快速敲擊,調出了過去半小時的資料庫寫入日誌。
一分鐘。兩分鐘。
"找到了。"趙強說。
所有人看向他。
"資料庫寫入瓶頸。"趙強把日誌投到投影屏上。紅色的警告條目密密麻麻。
"四個標準同時寫審計結果到同一張表——audit_results。每條記錄寫入時,PostgreSQL對目標行加排他鎖。四個標準同時寫同一批審計對象的行——行鎖衝突。"
林遠看著屏幕上紅色的鎖等待記錄。
"等一下——四個標準審計的是同一批財務數據,但輸出的是不同的審計底稿。它們的寫入目標應該是不同的行。"
"理論上是這樣。"趙強說,"但調度器的寫入邏輯是——每個審計程序完成後,先寫入中間結果到audit_results表,標記標準類型和程序編號。問題是——中間結果的行ID是自動遞增的,四個標準同時插入時,PostgreSQL的B-tree索引對自增主鍵的寫入產生了頁級鎖競爭。"
"自增主鍵的頁級鎖——"林遠理解了。
四個標準同時往同一張表里插入數據,自增主鍵意味著所有插入都集中在B-tree索引的最後一個頁面上。四個並發寫入爭搶同一個頁面的寫鎖——這就是性能持續下降的原因。
"數據量越大,索引頁面越滿,鎖等待越嚴重。"趙強說,"到後面會越來越慢。如果不處理,兩百萬條跑完可能要五到六個小時。"
"不能接受。"林遠說。
兩點半。
林遠坐在工位上,打開墨鋒,畫了一張架構圖。
"分庫寫入。"他說。
趙強、張浩然、周凱圍過來。
"auditresults表拆成四張——auditgasb、auditifrs、auditisa、audit_soc2。每個標準的結果寫到自己的表里。自增主鍵仍然有,但四張表的索引頁面互不干擾。"
"寫入衝突直接消除。"趙強說。
"對。匯總的時候——"林遠在圖上畫了一條虛線,"最終輸出階段,四張表的結果按審計對象ID合併。合併邏輯放在輸出層——反正輸出層本來就要把四個標準的底稿整合成一份報告。"
"代碼改動量呢?"張浩然問。
"調度器的寫入接口——從單一audit_results改成四個。"林遠說,"輸出層的合併邏輯加一個union操作。其他不動。"
"我來改調度器。"張浩然說。
"輸出層我來。"周凱說。
趙強說:"改完之後,我需要重新跑已經完成的百分之六十四嗎?"
"不需要。"林遠說,"已經寫入的數據是完整的——只是寫入速度慢,數據本身沒有錯誤。從斷點繼續。"
"明白。"
三點十五分。
張浩然和周凱改完代碼。
趙強重啟測試。
"從百分之六十四繼續。"
進度條重新啟動。
"每秒——"張浩然看著計時器。
"四百八。"
趙強說:"比剛才快了。因為已經寫入的數據少了,新表的索引頁面還空曠。"
"到百分之八十的時候再看。"林遠說,"索引頁面填滿之後的性能才是真實水平。"
下午五點。
百分之八十三。
"速度穩定在四百六。"張浩然說。
"內存呢?"
"引擎一點零五個G。資料庫一點八個G。穩住了。"
林遠看了看趙強。
趙強看了一遍日誌。"沒有鎖等待警告。B-tree索引的頁級競爭消除了。"
"從三百一到四百六——性能提升了百分之四十九。"
"理論上應該更高。"趙強說,"分庫之後,四個標準的寫入完全獨立。剩下的百分之十六差距來自上下文切換和資料庫連接池的開銷——這部分是架構層面的固有成本,無法消除。"
"百分之八十四的並行效率。"林遠說,"可以接受。"
"兩百萬條跑完需要多久?"張浩然問。
林遠算了一下。"剩餘百分之十七,按每秒四百六計算——大概六十五分鐘。六點多跑完。"
"今天能出第一份完整測試報告。"趙強說。
"對。"林遠說,"全量跑完之後——看四個標準的審計結果有沒有衝突。這是集成測試的第二階段:結果一致性校驗。"
五點二十分。
蘇明遠從辦公室出來。
"德勤那邊來郵件了。"
"韓委員?"
"韓委員轉發的——David Morrison的行程確認。"蘇明遠打開郵箱,"2004年五月十一號上午到北京,住中國大飯店。2004年五月十二號全天——上午九點到下午五點,我們的演示時間。下午五點半的航班飛上海。"
"也就是說——我們只有八個小時。"
"八個小時。"蘇明遠說,"包括午餐。"
"夠了。"林遠說,"演示內容我們已經準備得差不多了——四標準並行審計、FPGA加速、版本化配置包。八個小時足夠完整展示。"
"但演示之前——集成測試必須通過。"
"對。"林遠說,"今天跑完全量。周末做結果一致性校驗。下周一出測試報告。"
"時間線呢?"
"2004年五月十號之前——Demo穩定版就緒。2004年五月十一號——我們做一遍內部預演。2004年五月十二號——正式上場。"
蘇明遠點頭。"我去回復韓委員。"
晚上六點四十五。
"跑完了。"張浩然說。
兩百零三萬條數據。四套標準並行。總耗時——六個半小時。其中分庫方案之前的部分用了三個半小時,之後的部分用了三個小時。
"總吞吐量——每秒三百四十八條。"趙強說,"加權平均。"
"內存峰值?"
"引擎一點二個G。資料庫兩個G。穩定。沒有泄漏,沒有崩潰。"
"錯誤呢?"
趙強翻了一遍日誌。"零錯誤。兩百零三萬條數據,四套標準,八百一十二萬次審計執行——零錯誤。"
工作室里安靜了幾秒。
林遠說:"第一階段通過。明天——結果一致性校驗。"
趙強說:"我有預感——那裡才是真正的問題所在。"
"我知道。"林遠說,"兩百萬條數據跑完不出錯——說明工程層面是穩的。但四個標準的審計結果之間有沒有邏輯矛盾——那是設計層面的問題。"
"設計層面的問題——比工程層面的難修。"
"對。"林遠說,"所以明天開始——才是真正的硬仗。"
他看了看白板。
集成測試 Day 1:完成
- 吞吐量:348條/秒(加權)
- 錯誤率:0
- 關鍵修復:分庫寫入,消除資料庫鎖競爭
- 並行效率:84%
下一步:結果一致性校驗(Day 2)
八天。白皮書。二十天。演示。二十六天。開發完成。
今天第一天——資料庫鎖的陷阱。
明天——邏輯一致性的迷宮。