通過事務我的意思是幾個SQL語句在begin isolation level serializable
塊中包裝(例如)。併發事務可能導致此事務失敗,即回滾。在PostgreSQL中重新啓動一個失敗的事務
如何在PostgreSQL中重新啓動失敗的事務?
通過事務我的意思是幾個SQL語句在begin isolation level serializable
塊中包裝(例如)。併發事務可能導致此事務失敗,即回滾。在PostgreSQL中重新啓動一個失敗的事務
如何在PostgreSQL中重新啓動失敗的事務?
您需要使用客戶端驅動程序特定的機制來檢測事務中的錯誤。當你看到一個錯誤,你必須回滾交易和重新發出整個交易。你不能只重新做最近的部分。
ROLLBACK
是必需的;如果您不這樣做,則該連接的任何進一步操作都會失敗,並顯示「事務中止」錯誤。
大多數客戶端驅動程序要麼在支持它們的語言中引發異常來指示SQL錯誤,要麼在每次數據庫操作之後檢查錯誤代碼(通過檢查函數返回代碼或調用特殊函數檢查錯誤。 node-postgres
是異步和非阻塞的,所以不會拋出異常;您應該查找一個函數,通過該函數可以查詢會話以瞭解上一次操作產生的SQLSTATE
和客戶端驅動程序錯誤狀態。
node-postgres
doesn't seem to have abundant documentation因此,您最好的選擇可能是檢查node-postgres的源代碼,或查找其他人如何執行此操作的示例。我希望你會找到函數來檢查會話的錯誤狀態。您正在尋找的功能是獲取SQLSTATE
用於連接上的最後一項操作。
它可能是值得發佈的問題,專門關注如何檢測和處理node-postgres中的錯誤。
其實,SAVEPOINT
和ROLLBACK TO SAVEPOINT
讓你做到這些,但他們不會與序列化錯誤的幫助。
這實際上是我想要的那種答案。非常感謝! – ehmicky
此答案已在3年後添加,以解釋此後的變化。即使原始答案仍然有效,這個答案顯示了今天使用當時沒有的正確工具是多麼容易。
這是很容易做到與pg-promise,它支持任意嵌套層次的嵌套事務。請參閱Nested Transactions,其中說明儘管頂級交易由標準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
失敗,我們仍然可以成功完成我們的頂級交易。
如果您希望能夠重新啓動整個事務,只需將整個事件包裝到一個子事務中,然後您可以根據需要多次在主事務中重新運行該子事務。
您必須留意此類事件,並準備好再次從客戶端開始相同的事務,以防在失敗後該操作仍然有效。 –
但是,當交易失敗時,所有客戶都會收到通知嗎?我正在使用node-postgres(node.js),但我不確定事務失敗是否會引發異常。 – ehmicky
[pg-promise](https://github.com/vitaly-t/pg-promise)支持嵌套事務,並且這些成爲嵌套級別上的保存點,您可以使用它來恢復事務。 –