資料庫的一些基礎研究和效能探討(觸發器)
一直沒有機會使用到觸發器,但是在一個偶然的情況下,我在做使用者同步和許可權刪除時我想起了這個功能。
在設計資料庫的時候,我往往都走進一個怪圈,可能就是應了一個數據庫的前輩所說的:開發資料庫的思維和方式不能用開發其他模組的思維方式來做,可惜當時我只是一個後臺開發工程師,並沒有深刻去了解。現在我發現很多地方在選擇哪裡該封裝,哪裡該用那種封裝,是檢視,函式,儲存過程,我都往往會偏向於儲存過程,因為這是很接近一個我們平常用java或者python那樣封裝的方式(雖然資料庫的函式更貼切,但是呼叫來說,儲存過程更像我們平時開發的呼叫習慣)。
我把觸發器當作一種被動的儲存過程,但是在開發過程中,什麼時候使用他呢?來個講解其作用的引用:
觸發器的主要作用是其能夠實現由主鍵和外來鍵所不能保證的複雜的參照完整性和資料的一致性。它能夠對資料庫中的相關表進行級聯修改,強制比CHECK約束更復雜的資料完整性,並自定義操作訊息,維護非規範化資料以及比較資料修改前後的狀態。
在我使用完畢後看書時,發現不同的資料庫的不同版本,對使用觸發器來說都有著不同的地方。但是主體來說作為刪除使用者和一些扣款之類的業務還是挺不多的。
但是從我開發人員的角度來說,觸發器有一個缺點就是,假如你發現一個問題是關於觸發器的,但是因為它對於你來說是“不顯示的”,所以導致我會找bug找很久才找到這裡,對於維護來說是一個很大的挑戰。這點可以通過對觸發器的統一管理。
同時我使用的感覺,在before使用觸發器的效果還是不錯的,而after的話其實很多情況可以用儲存過程替代了。但是我的結論是:慎用,尤其我這種剛涉獵的初哥。
其實使用的優缺點不是我最關心的,最關心就是效能。
因為我這邊做的表關聯比較複雜,而且涉及到2個完全不同的資料庫之間的同步。如果用上了觸發器是一個很好的解決方案。但是問題來了,雖然我這裡的需求可以非同步操作一些,但是因為2個不同的資料庫之間還夾著一個我上層語言編寫的服務來同步的話,是一個很大的挑戰。第一,同步資料的間隔時間,第二就是設計觸發器的複雜度。我在設計的過程中,一邊用上層語言寫好邏輯,然後又寫了一個差不多功能的觸發器,為了就是對比效率。因為我使用資料庫層為了就是提高效能和方便維護,所以我一直在做這個考量。
結果確是慢慢的把大部分功能都交給了儲存過程+上層邏輯去做,第一是因為觸發器使用是有限制,導致一些我想實現的sql組合不能實現。第二就是其實我算是涉及到2個不同的事務,這個對我設計來說功能影響很大,在做模擬的自動化測試就已經出現了和別的業務同時操作表的衝突問題了。最後唯一一個和效能相關的因素就是在多併發的場景下,我發現大資料量修改和刪除時會偶爾出現一些資料庫丟擲的錯誤和一些修改失敗的情況。無論是並行還是併發的情況都存在的話,這個是我同步設計中最不想看到的結果。
所以最後通過我這個sql初哥的實驗和工作的結果來看,我為了準確性和部分效能原因,最終還是選擇了以儲存過程和上層邏輯為主,在一些併發不高的一對多的場景下用了一小部分的觸發器來完成我的需求。