做ORM
據我所知,你正在寫的功能,從您的客戶端代碼執行。儘管可以通過使用EXCEPTION
子句編碼BEGIN
/END
塊來使用plpgsql中的子事務,但函數執行的整體總是在一個事務中,無論您是否明確地指定了事務。這些子事務不是免費的,所以你只想在真正需要的時候使用它們。
如果聲明性地陳述強制執行業務規則所需的不變量,那幾乎總是比用觸發器中的命令式代碼強制執行它們更好。 CHECK
約束條件,PRIMARY KEY
約束條件,FOREIGN KEY
約束條件,UNIQUE
約束條件和(PostgreSQL特有的功能)EXCLUSION
約束應該在覆蓋用例時全部用來代替觸發器代碼。
如果您正在使用PostgreSQL 9.1或更高版本,在開始之前做出的最大決定是您將使用什麼策略來處理併發事務之間的競爭條件。兩種主要的選擇是,是否嘗試跟蹤所有可能的衝突並處理應用程序代碼中的問題,或僅使用可序列化的事務(您可以在postgresql.conf文件中設置該默認值)並讓PostgreSQL進行排序。最好的寫了,我已經看到了前者是在這裏:http://www.postgresql.org/files/developer/concurrency.pdf而對於後者鏈接:
http://www.postgresql.org/docs/current/interactive/mvcc.html
http://wiki.postgresql.org/wiki/SSI
如果使用SERIALIZABLE
甚至REPEATABLE READ
交易,你應該運行查詢提供序列化失敗的一般處理的某種方式;也就是說,如果事務拋出SQLSTATE設置爲'40001'或'40P01'的異常,則應該回滾失敗的事務並從頭開始重試。您不希望在運行查詢的每個位置的應用程序代碼中嵌入該邏輯。現在許多開發框架允許交易註釋,這使得這易於實現。我們只在我們的商店中使用可序列化的交易,而且它確實簡化了一些事情,以瞭解如果您能證明交易自己做了正確的事情,它將在任何交易組合中做正確的事情,而無需任何特殊編碼來確保(不止如上所述處理序列化失敗)。
請注意,由於使用可序列化快照隔離,使用可序列化事務的PostgreSQL的性能非常接近於許多工作負載的不太嚴格的隔離級別;如果你因爲擔心阻塞和僵局而一直避開這個想法 - 不要。 PostgreSQL 9中的序列化事務。1沒有像使用嚴格的兩階段鎖定(S2PL)的數據庫那樣的問題。
完全披露:與Dan R.K合作。麻省理工學院的港口,根據悉尼大學Michael J. Cahill等人的論文,我幫助實施了針對PostgreSQL 9.1版的Serializable Snapshot Isolation,因爲我們需要我工作場所的功能。我沒有從使用它的任何人那裏獲得任何經濟利益,但我個人認爲這通常是要走的路。這更多,我希望,原因我工作的功能,而不是結果的工作的功能。
所以我不需要一個'IF ELSE'檢查我的函數中的約束失敗嗎? – 2012-04-09 15:42:57
不,你不需要在你的函數中編寫這些代碼;約束會自行拋出異常(如果需要)。 – kgrittn 2012-04-09 17:12:28
感謝您的鏈接,特別是在SSI上,非常有用! – vyegorov 2012-04-11 07:04:09