簡體   English   中英

在PostgreSQL中重新啟動失敗的事務

[英]Restart a failed transaction in PostgreSQL

通過事務,我的意思是在begin isolation level serializable塊中包含(例如)幾個SQL語句。 並發事務可以使此事務失敗,即回滾。

如何在PostgreSQL中重啟失敗的事務?

您需要使用特定於客戶端驅動程序的機制來檢測事務中的錯誤。 當您看到錯誤時,您必須回滾事務重新發出整個事務 你不能只重新做最新的第1部分。

ROLLBACK是必需的; 如果不這樣做,該連接上的任何進一步操作都會因“事務中止”錯誤而失敗。

大多數客戶端驅動程序拋出異常(使用支持它們的語言)來指示SQL錯誤,或者希望您在每次數據庫操作后檢查錯誤代碼,方法是檢查函數返回代碼,或者調用特殊函數來檢查錯誤。 node-postgres是異步和非阻塞的,因此它不太可能拋出異常; 您應該查找一個函數,該函數允許您查詢會話以查找最后一個操作導致的SQLSTATE和客戶端驅動程序錯誤狀態。

node-postgres 似乎沒有豐富的文檔,所以你最好的選擇是檢查node-postgres的源代碼,或找到其他人如何做到這一點的例子。 我希望你能找到檢查會話錯誤狀態的函數。 您正在尋找的是為連接上的最后一個操作獲取SQLSTATE的函數。

可能值得發布一個專門針對如何檢測和處理node-postgres中的錯誤的問題。


1實際上, SAVEPOINTROLLBACK TO SAVEPOINT讓你做到這一點,但它們無法幫助解決序列化錯誤。

這個答案在3年后被添加,以說明自那以來的變化。 盡管最初的答案仍然有效,但這個答案表明,今天使用當時無法使用的正確工具是多么容易。


使用pg-promise很容易,它支持任何嵌套級別的嵌套事務。 請參閱嵌套事務 ,其中解釋了當頂級事務由標准BEGIN - > COMMIT / ROLLBACK ,所有嵌套事務都自動變為SAVEPOINT

db.tx(t => {
    // BEGIN
    // top-level changes cannot be restarted:
    return t.any('UPDATE users SET name=$1 WHERE id=$2', ['Mike', 123])
        .then(() => {
            return t.tx(t1 => {
                // SAVEPOINT
                return t1.none('INSERT log(event) VALUES($1)', 'entry');
            })
                .catch(error => {
                    // ROLLBACK TO SAVEPOINT executed
                    return t.none('UPDATE log SET event = $1');
                });
        });
})
    .then(data => {
        // success, COMMIT executed
    })
    .catch(error => {
        // error, ROLLBACK executed
    });

在上面的示例中,我們在頂層執行UPDATE ,由於這個原因無法重新啟動。 然后我們使用INSERT執行嵌套事務/保存點,如果失敗,則再次替換為頂層的UPDATE

這樣,即使我們的SAVEPOINT失敗,我們仍然可以成功完成頂級交易。

如果您希望能夠重新啟動整個事務,只需將整個事務包裝到子事務中,然后可以根據需要在主事務內重新運行。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM