2010-12-15 112 views
28

我想了很久爲什麼JDBC API提供了一個自動提交模式(java.sql.Connection.setAutocommit())。這似乎是一個誘人的麻煩,只是引誘人們陷入困境。我的理論是,它只添加到JDBC中,以便簡化使用JDBC創建編輯和運行SQL的工具的供應商的生活。是否有其他理由打開自動提交,還是總是出錯?爲什麼設置Autocommit爲true?

回答

11

不幸的是,使用自動提交是數據庫特定的(就像事務行爲一樣)。我認爲,如果你沒有一個全球的,程序化的交易策略,自動提交可能比只希望每個人都能正確地關閉/回滾交易要好。

說到MySQL,您可以在默認情況下保持autocommit = true,並且在您開始事務時它會自動關閉它。設置autocommit = false的唯一原因是,如果您想要在沒有BEGIN的情況下嘗試啓動事務時強制執行錯誤。

爲了簡化今天典型的Java + MySQL應用程序,我會或多或少地忽略自動提交設置,使用開放會話視圖模式並稱其爲好。

我強烈勸阻顯式RDBMS行鎖,並使用樂觀鎖。 Hibernate爲樂觀鎖定提供了內置支持,但即使對於手寫代碼,它也是一種簡單的模式,並且可以提供更好的性能。

+2

爲了澄清典型的Ja va + MySQL應用程序:將自動提交設置爲true。在傳入請求(網頁或REST/JSON)開始時,打開一個會話(並開始一個事務)一次。如果請求處理正常,請在請求處理結束時提交事務。然後,添加一個回滾到你的500頁面的請求渲染。例如,這基本上是Play Framework如何處理事物的。這對用戶和開發人員來說很直觀。 – 2013-01-11 18:32:09

+0

這是一個很好的答案 - 「web請求」應該與web應用程序中的「數據庫事務」非常相關。因此我們需要依靠樂觀,而不是數據庫鎖定。它有助於使用OpenSessionInView在整個請求中保持會話打開,包括視圖渲染,然後在請求結束時刷新/提交。 – 2013-11-21 09:52:16

+0

在我看來,這不是一個好的答案,如果典型的Java + MySQL應用程序不僅僅是「幾個星期的項目」,還可以將會話視爲反模式。您會很快失去對應用程序中發生的事情的控制,它幾乎可以確定是否會出現性能問題或併發性問題,自動提交將使您無需事務超時或事務超時,如同「一般請求處理超時」一樣工作。我會說在90%以上的情況下,web請求NO與SQL事務沒有關係 – 2017-12-29 08:30:23

5

提交模式改變數據庫持有鎖的方式。

建議僅在事務模式下禁用自動提交模式。這樣,您可以避免爲多個語句保留數據庫鎖定,從而增加與其他用戶發生衝突的可能性。

...

爲了避免交易過程中出現衝突,數據庫管理系統使用的鎖,機制,阻止他人訪問正由事務訪問的數據。 (請注意,在自動提交模式,其中每條語句是一個事務,持有鎖只有一個聲明。)

http://download.oracle.com/javase/tutorial/jdbc/basics/transactions.html

+0

鑑於即使mySQL和DB2最近都是多版本的,該教程也變得有些過時。 :( – Affe 2010-12-15 19:40:26

+0

快照隔離級別不是免費的:http://blogs.msdn.com/b/sqlserverstorageengine/archive/2008/03/30/overhead-of-row-versioning.aspx您可以獲得併發快照隔離,但是會增加額外的開銷 – hythlodayr 2010-12-15 19:50:47

+0

理解你獲得鎖的方式始終是相關的 – 2010-12-15 20:01:17

18

只需要合理的理由,我可以看到的是擺脫connection.commit()connection.rollback()簡單的單一查詢事務處理小應用程序中的樣板。原始形式的JDBC本身就需要很多樣板。每一行都使JDBC對於初學者來說不那麼可怕。

3

我正在使用的代碼庫的95%現在涉及單個更新,其中自動提交是完全合理的。所以,我們默認它。只需將它關閉足夠長的時間以完成需要成爲事務的代碼段,然後自動提交即可重新開始!

+0

請記住,交易可能會導致交易管理器發生交易超時。你在每個查詢中設置了超時時間嗎? – 2017-12-29 08:33:36

8

我幾乎總是以autocommit = true運行。 99%的時間,我的更新是原子。當然,在某些情況下,如果您編寫借方,然後嘗試寫入您希望回滾的信用額度失敗。但根據我的經驗,這些比較少見。通常我寫的每個記錄都是獨立的。在這種情況下,在每次寫入都很方便之後,不需要費心提交一次提交。它在這裏和那裏保存了一行代碼。如果考慮到程序的結構,這意味着我不需要額外的try/catch塊或者我不需要在函數之間傳遞連接對象,它可以節省更多的時間。它可以節省那些忘記做提交的煩人的錯誤。

我發現它可以「引誘某人陷入麻煩」的唯一方法是他決定關閉自動提交併進行提交或回滾比較麻煩,因此他更新了應該在事務中單獨進行的更新。然後,只要沒有任何事情會中止交易,所有事情都可以正常工作。如果測試場景不足,我可以想象這會滑入生產。

但是你幾乎可以對任何語言的任何特徵說幾句話。就像,假設你編寫一個程序來處理數字,90%的時間適合長時間,但是現在或許會變得更長。面對這種情況,正確的做法是使用BigInteger或創建一個新類來處理更大的數字。一個懶惰的程序員可能會被誘使用很長的時間,因爲它通常會起作用,而其他替代方法則很麻煩。您是否因此得出結論:Java不應該包含long(或int),因爲有人可能會在不恰當時引誘它們使用它們?

如果在您的程序中大部分更新必須在事務上下文中完成,請關閉自動提交。它的存在並不會傷害你。當它方便時,它在那裏,但當它不是時,你可以關閉它。

+1

由於JDBC 3規範,「自動提交」模式下的連接不能有多個Statement打開。因此,在外部SELECT循環內嵌套的UPDATE甚至SELECT會導致問題。 – 2012-06-05 00:36:01

+0

這不僅是原子性,如果事務管理器支持事務,事務也可以分配超時。使用自動提交和無查詢超時可以使您陷入未檢測到的SQL性能問題,掛起沉重的查詢等。 – 2017-12-29 08:35:28

+0

我已經離開了Javaland多年,所以也許新版本的Java不同或者我只是誤解了事情。但是我確信在執行帶有自動提交的查詢時,我得到了SQL超時。我對在開發環境中發現的查詢有很多美好的回憶,但在產品中超時。也許默認值是不同的或者什麼的。無論如何,依靠暫停來告訴你,你有一個性能問題是一個非常鈍的工具。 – Jay 2017-12-29 16:31:24

6

自動提交很方便;但隨着JDBC 3規範的變化,變得不那麼有用。

由於「自動提交」模式下的JDBC 3連接不能打開多個語句。執行另一個語句,將關閉第一個 - 包括任何ResultSet。

因此,在SELECT中循環併發布UPDATE(甚至嵌套的SELECT)將會失敗。顯然這是一種犯罪,實際上想做些什麼與你的外部SELECT的結果!


不管怎麼說,依賴於特定的驅動程序版本& ..但在一般的JDBC 3.0規範似乎強制此無益的行爲。升級驅動程序也可能無益地「發現」這種行爲。

爲什麼使用自動提交?本來,這很有幫助&方便。至於其他的答案說,JDBC需要豐富金額廢話和處理能正確調用.. JDBC是不是一個真正的精心設計的API :(


這些天來,你最好使用Hibernate或Spring的JdbcTemplate。 。如果你正在做servlet/web應用程序,在「用戶請求」的邊界放置事務管理(開始/結束)或Hibernate會話(綁定到線程本地)。

例如,get在ServletRequest的開始處綁定你的連接/事務;並在最後返回它

你可以使用javax.servlet.Filter或類似的方法,並綁定它到線程局部,使靜態幫手得到它或需要它,等

+0

請不要建議綁定到Web請求ANTI模式的連接/交易/會話......如果您希望您的交易跨越例如請求處理,multiplart上傳處理,發送正文給客戶端連接速度慢,你可以做到這一點,但在幾乎所有情況下,我都會說這是非常糟糕的主意。 – 2017-12-29 08:38:12

+0

謝謝@PiotrMüller - 任何推理或參考?我可以預料,對於幾乎所有的模式,你都可以想出0.001%的不好的情況,但把「孤立的問題角落案例可能」與「幾乎所有案例」區別開來可能會更好 - 當時我給出了這個建議(2012年),我相信這是很好的建議。用戶請求邊界是HT​​TP服務應用程序中最基本和重要的邊界。因此,這是一個強大而明顯的候選設計。任何替代解決方案可能會更復雜。 – 2018-01-08 03:34:50

+0

在Web應用程序中,大多數提到的「不好的情況」將適用(對於任何典型的Web應用程序)。在視圖中啓用會話,您應確保立即解決很多技術問題,例如,響應緩衝:確保事務和SQL連接在整個客戶端連接拉動響應的時間內不是跨度(爲什麼在客戶端具有低帶寬的情況下長時間保持SQL連接)。如果應用程序很快就會遇到設計/性能問題增長。對於快速的幾個星期小項目,這可能是一些解決方案,但我不會推薦它有任何大的 – 2018-01-26 08:45:10

2

那麼有需要仔細看一下,同時啓用「自動提交」在全球層面一定的條件:

a。)查詢級別的事務管理將留給用戶,對於一個實例,如果需要一堆查詢來一起成功或失敗,那麼它需要在BEGIN下進行包裝並提交事務。 )請記住,啓用「自動提交」時不會回滾。

c)還有寫作(提交)每一筆交易的開銷。 d))對於只讀查詢,沒有明確需要「自動提交」,但通過啓用「自動提交」,它會自動執行所有查詢。

如果表鎖定是啓用自動提交的唯一考慮因素,那麼它可能不是一個好主意,相反可能會採取較低的鎖定超時。

相關問題