簡體   English   中英

PostgreSQL與Oracle默認事務管理

[英]PostgreSQL vs. Oracle default transaction management

在PostgreSQL中,如果您在事務中遇到錯誤(例如,當您的insert語句違反了唯一約束時),整個事務將被中止,您無法提交它並且不會插入任何行:

database=# begin;
BEGIN
database=# insert into table (id, something) values ('1','whatever');
INSERT 0 1
database=# insert into table (id, something) values ('1','whatever');
ERROR:  duplicate key value violates unique constraint "table_id_key"
Key (id)=(1) already exists.
database=# insert into table (id, something) values ('2','whatever');
ERROR:  current transaction is aborted, commands ignored until end of transaction block
database=# rollback;
database=# select * from table;
id   | something  | 
-----+------------+

(0 rows)

您可以通過將ON_ERROR_ROLLBACK設置為“on”或“interactive”來更改它,之后您可以執行多個插入,忽略錯誤,提交並在事務結束后僅在表中成功插入行。

database=# \set ON_ERROR_ROLLBACK interactive

在Oracle中,這是默認的事務管理行為,這讓我感到驚訝。 這不是完全違反直覺和危險的嗎?

當我開始一個交易時,我想確保所有的陳述都是成功的。 如果我的多個插入包含某種對象或數據結構怎么辦? 我最終完全沒有意識到我的數據庫中的數據狀態,應該在提交后檢查它。 如果其中一個插入失敗,我想確保在第一個錯誤之后回滾或甚至不評估其他插入,這正是在PostgreSQL中完成的。

為什么Oracle將這種事務管理方式作為默認方式,為什么它被認為是良好的做法?

例如,一些隨機的人在評論中

這是一個非常簡潔的功能。

我不明白這一點:“通常情況下,你所做的任何錯誤都會引發異常並導致你當前的事務被標記為中止。這是理智的預期行為......”

不,它真的不是。 Oracle不會這樣工作,MySQL也不行。 我沒有使用過MSSQL或DB2的經驗,但我打賭每個人都不會這樣做。 沒有直觀的理由說明語法錯誤或任何其他錯誤應該中止事務。 我只能假設Postgres內容中存在一些需要這種行為的深度限制,或者它符合其他人明智忽略的SQL標准的一些模糊部分。 當然沒有API / UX理由為什么它應該以這種方式工作。

我們真的不應該為我們為這種病態行為開發的任何變通方法感到驕傲。 這就像IT斯德哥爾摩綜合症。

它是否違反了交易的定義?

交易提供了“全有或全無”的命題,指出在數據庫中執行的每個工作單元必須完整地完成或者不具有任何效果。

我同意你的看法。 我認為不中止整個tx是錯誤的。 但是人們已經習慣了,所以他們認為這是合理和正確的。 就像使用MySQL的人認為DBMS應該接受0000-00-00作為日期,或者使用Oracle的人期望'' IS NULL

語法錯誤和其他東西之間存在明顯區別的想法是有缺陷的。

如果我寫

BEGIN;

CREATE TABLE new_customers (...);

INSET INTO new_customers (...)
SELECT ... FROM customers;

DROP TABLE customers;

COMMIT;

我不在乎它是一個錯字導致語法錯誤導致我丟失我的數據。 我關心事務沒有成功執行所有語句但仍然提交。

在任何行實際由語句寫入之前允許在PostgreSQL中進行軟回滾在技術上是可行的 - 可能在我們進入執行程序之前。 因此,解析和參數綁定階段中的失敗可能允許tx不被中止。 我們有一個可以用來清理的語句內存上下文。

但是,一旦語句開始更改行,它就會在磁盤上執行,其事務ID與tx中的先前語句相同。 所以你不能回滾而不回滾整個tx。 要允許語句回滾,Pg需要分配新的子事務ID。 這需要資源。 您可以在需要時使用SAVEPOINT顯式地執行此操作,並在內部執行psql正在執行的操作。 從理論上講,我們可以允許服務器為每個語句隱式執行此操作以實現語句回滾,只是性能成本。 但是我懷疑任何實現這一點的補丁都會被提交,至少在沒有大量爭論的情況下,因為大多數PostgreSQL團隊(IMO合理地)都不喜歡“哎呀,那就破壞了但我們仍會繼續”交易語義。

暫無
暫無

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

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