2009-05-03 104 views
40

關於使用事務從數據庫中讀取,似乎有很不同的觀點。只讀數據庫訪問事務?

從developerWorks文章Transaction strategies: Models and strategies overview報價:

爲什麼你會需要一個事務,如果 你只是讀取數據?答案 是你沒有。啓動 交易執行只讀 操作增加了 處理線程的開銷,並可能導致數據庫共享上 讀鎖(視 於你正在使用 數據庫的類型和什麼隔離級別設置 )。

由於相反的意見,有來自Hibernate文檔以下報價Non-transactional data access and the auto-commit mode

我們的建議是在應用程序中不使用 自動提交模式,並 申請只讀只 時交易有一個明顯的表現 好處或當未來的代碼更改 是不太可能的。無論您是讀取數據還是寫入數據,始終優先選擇 常規ACID事務,以便將您的數據訪問操作分組爲 , 或 。

在EclipseLink郵件列表here上也有類似的爭論。

那麼謊言的真相呢?是否閱讀最佳做法的交易?如果兩者都是可行的解決方案,那麼使用交易的標準是什麼?

就我所見,只有當隔離級別高於'讀取提交'時纔會有所作爲。它是否正確?

有什麼經驗和建議?

回答

16

史蒂芬Devijver提供啓動交易一些很好的理由,即使操作只會讀取數據庫:

  • 設置超時或鎖模式
  • 設置隔離級別

標準SQL要求如果沒有正在進行的交易,即使查詢也必須開始新的交易。有數據庫管理系統哪裏不會發生什麼 - 例如那些與自動提交模式,(語句啓動一個事務,並立即提交聲明完成)。其他DBMS在默認情況下使語句原子化(有效自動提交),但使用'BEGIN WORK'等語句啓動顯式事務,取消自動提交,直到下一個COMMIT或ROLLBACK(IBM Informix Dynamic Server就是這樣 - 當數據庫不是MODE ANSI)。

我不確定永不回滾的建議。這對於只讀事務沒有什麼區別,並且在很大程度上會惹惱DBA,因此最好避免ROLLBACK。但是如果你的程序沒有進行COMMIT就退出了,DBMS應該對你的未完成事務做一個ROLLBACK - 當然如果它修改了數據庫,並且(爲了簡單起見),即使你只選擇了數據。總體而言,如果要更改一系列操作的默認行爲,請使用事務,即使事務處於只讀狀態也是如此。如果您對默認行爲感到滿意,那麼使用事務並不重要。如果您的代碼要在DBMS之間移植,最好假設您需要一個事務。

8

如果您希望爲默認超時之外的其他查詢設置特定的超時值,或者您想要更改隔離級別,則只讀操作需要事務。

此外,每個數據庫 - 不知道異常 - 將在內部爲每個查詢啓動一個事務。當不需要回滾時,通常認爲沒有做回滾事務。

DBA's可能正在監視回滾活動,並且在這種情況下,任何默認的回滾行爲都會使他們惱火。

因此,無論您是否開始交易,都會使用交易。如果你不需要它們,不要啓動它們,但不要在只讀操作上進行回滾。

8

首先,這聽起來像是一個不成熟的優化。正如史蒂文指出的那樣,大多數理智的數據庫都會把你放進一個事務中,而他們真正所做的就是在每次陳述後調用commit。所以從這個角度來看,自動提交可能性能較差,因爲每條語句都必須啓動一個新的事務。或者可能不是。只有基準測試會告訴我,我敢打賭,它不會讓你的應用產生一點變化。

爲什麼總想使用交易的一個原因是保護的一致性。如果你開始擺弄手動只在「需要」的時候宣佈交易,那麼你將在關鍵時刻忘記。或者那個被認爲是隻讀操作的集合突然不是,因爲後來的程序員沒有意識到它應該是或者因爲你的代碼調用了一個具有隱藏寫操作的函數。例如,我將我的命令行數據庫客戶端配置爲不自動提交。這意味着我可以用手指刪除查詢並仍然回滾。

正如指出的那樣,存在隔離級別。這使您可以執行多次讀取操作,而不用擔心其他進程是否寫入了它們之間的數據,從而使您的讀取實際上處於原子狀態。這將爲您節省很多小時的調試競爭條件。

最後,您通常可以將事務設置爲只讀。這會檢查你的假設,如果有東西試圖寫入,將會錯誤。

Here's a nice article summing it all up.詳細信息是Oracle特定的,但概念是通用的。