工作項目報告,所以抹掉項目名先,以“X”代之。
分割線內(nèi)內(nèi)容僅代表個人意見,與所供職企業(yè)及參與社區(qū)無關(guān)。
===================================
X 從很早的時候就出現(xiàn)各種數(shù)據(jù)庫訪問錯誤。包括鏈接數(shù)占用過多,死鎖,僵尸事務(wù)等。本周我集中梳理了一遍代碼。我認(rèn)為,雖然數(shù)據(jù)庫設(shè)計方面有諸多不合理之處,但是這些不合理主要影響業(yè)務(wù)錯誤,造成 X 性能和使用上的
問題是因為使用的ORM框架 storm 有嚴(yán)重的缺陷。
首先,storm 對數(shù)據(jù)庫架構(gòu)的同步有非常奇怪的設(shè)定。它不自動同步表結(jié)構(gòu),卻插手外鍵關(guān)聯(lián)關(guān)系。強(qiáng)制要求外鍵必須都是級聯(lián)更新、級聯(lián)刪除、set null。且不說其設(shè)定中有自相矛盾之處,本身在MIS系統(tǒng)中做級聯(lián)刪除就是一件很危險的事——除了系統(tǒng)維護(hù)、分表,MIS系統(tǒng)不應(yīng)該刪除任何數(shù)據(jù)。 storm 從一開始設(shè)計恐怕就沒有考慮企業(yè)級應(yīng)用,但是對于web 開放式應(yīng)用,storm 對外鍵的依賴又太笨重了。
其次,storm 在聯(lián)接數(shù)據(jù)庫后應(yīng)該會有 DDL 操作(即修改數(shù)據(jù)庫結(jié)構(gòu))或獨占鎖定事務(wù),此推斷的證據(jù)在于用 storm 聯(lián)接到 S 庫后, S 無法進(jìn)行vacuumdb -a -f 處理。而根據(jù) Postgres 手冊,PG只有在遇到有鏈接正在進(jìn)行DDL 操作時,才會產(chǎn)生庫級鎖,造成 vacuum 操作無法進(jìn)行(或手工建立一個隔離級別相當(dāng)?shù)氖聞?wù)鎖定)。作為世界上并發(fā)能力最強(qiáng)的數(shù)據(jù)庫產(chǎn)品,正常的數(shù)據(jù)訪問
操作與 vacuum 根本不會沖突,熱處理資源回收正是 PG 獨到的特性。這樣造成了X 應(yīng)用頻繁用光所有的鏈接數(shù),還在數(shù)據(jù)庫服務(wù)器遺留僵尸進(jìn)程。我觀察到有僵死十幾二十天沒有完成過的 X 鏈接,這應(yīng)該是因為同時多個 storm 鏈接提交錯誤的鎖定關(guān)系,造成死鎖。
第三,storm 如果可以象 DAL 那樣,明確設(shè)定不同步數(shù)據(jù)庫,以上問題至少可以解決一半,但是它沒有鏈接配置參數(shù)。這造成了我們對其出現(xiàn)的問題無法進(jìn)行友好
的調(diào)整。現(xiàn)在同事在 X 的 controll 層添加了強(qiáng)制的 commit 操作,一定程度上減少了死鏈,但是我仍然觀察到有點擊 X 頁面(在測試環(huán)境下)無法響應(yīng),甚至造成數(shù)據(jù)庫服務(wù)器閃斷重啟的現(xiàn)象,對于同時運營三十幾個數(shù)據(jù)庫的數(shù)據(jù)庫服務(wù)器,這是非常大的安全隱患。
昨天我嘗試將 X 的數(shù)據(jù)庫訪問層遷移至 web2py DAL,經(jīng)過一天嘗試,總結(jié)出以下的問題:
第一,DAL 缺少精確實數(shù)計算類型,它不支持 Numeric 或 Decimal,只能用
double,這是一個相當(dāng)大的安全隱患,對于涉及財會計算的應(yīng)用,使用浮點數(shù)是一種很不嚴(yán)肅的作法。
第二,DAL 不支持?jǐn)?shù)組和大數(shù)據(jù)類型,此類字段在 X 中有幾處應(yīng)用。
第三,DAL 對原生SQL的支持比較初級,雖然也可以使用,但是有時需要兼顧開發(fā)速度,希望可以組合使用的時候,就會受限。
以上問題不是不能解決,但是需要修改 DAL 本身。雖然我一直有計劃改造 DAL,fork 一個對 PG 有良好支持的分支出來。但是這顯然需要更多的開發(fā)時間。
昨天我詳細(xì)查閱了一下 sqlalchemy 的文檔,進(jìn)行了一些簡單的嘗試,感覺這個ORM 框架比較符合我們的需求:
第一,sqlachemy 對數(shù)據(jù)庫鏈接的隔離級別和事務(wù)有良好的控制,默認(rèn)也不會去嘗試DDL操作。
第二,sqlachemy 有非常豐富的數(shù)據(jù)類型支持,包括BLOB,Decimal/Numeric,以及為 PG 特別定制的數(shù)組類型。
第三,sqlachemy 的查詢類似 DAL (很可能DAL學(xué)習(xí)自sqlachemy),對各種查詢操
作有良好的支持,還可以嵌入 SQL 片段,也可以方便的直接傳入 SQL。
第四,sqlachemy 其實并不難學(xué),它的功能雖然豐富,但是只掌握自己要用到的部分即可,不需要完全學(xué)會,上手還是很簡單的。
第五,文檔比 storm 完整的多,而且現(xiàn)在仍在活躍開發(fā)。
第六,數(shù)據(jù)存儲模型與業(yè)務(wù)模型分離,雖然看起來有重復(fù)勞動,但是對于一個需要長期維護(hù)的企業(yè)應(yīng)用項目,這是正確和嚴(yán)肅的作法。
第七,對特定數(shù)據(jù)庫的特性有良好的支持,還可以擴(kuò)展。
在使用 sqlachemy 時,我們還可以結(jié)合 web2py 原有的一些優(yōu)秀工具,例如廣泛用于 DAL 的storage類型,這是一個類似 JS Object 的智能對象類型,很適合動態(tài)結(jié)構(gòu)的數(shù)據(jù)對象。
對于 X 項目的數(shù)據(jù)訪問層重構(gòu),我評估工作量至少在一周左右。如果全部換用 sqlachemy ,可以一勞永逸的解決數(shù)據(jù)庫訪問的問題,甚至 S 的后續(xù)版
本,我也建議嘗試使用這個框架,畢竟這比 hack dal 要方便一些。
sqlachemy 當(dāng)前的穩(wěn)定版本是 0.5.6 ,我昨晚試驗了開發(fā)中的 0.6 ,發(fā)現(xiàn)功能還沒有完整實現(xiàn),現(xiàn)在還不能實用。
===================================