2011-02-23 77 views
0

當在事務中使用多個插入與select語句時,數據庫如何跟蹤事務期間的更改?如果事務處於打開狀態的時間過長,是否會出現資源問題(如內存或硬盤空間)?是插入選擇語句龐大?

+0

確切地理解你所要求的內容有點困難,但是當你提交一個事務時,你會提交作爲該事務的一部分執行的所有更改。你到底在問什麼? – 2011-02-23 16:31:05

+1

試圖推斷提問者的意圖。這個問題的原始形式是無法回答的。 – 2011-02-23 16:34:51

+0

@羅伯特哈維:我希望我可以投票了你的編輯。 – derobert 2011-02-23 23:02:53

回答

0

對於大型交易您可能會遇到很多問題。首先,在大多數數據庫中,您不希望逐行運行,因爲一百萬條記錄需要幾個小時。但是,在一個複雜語句中插入一百萬條記錄會導致涉及的表上的鎖定並損害其他人的性能。如果你殺了交易,回滾也可能需要很長時間。通常最好的選擇是批量循環。我通常一次測試50,000個,並根據需要多長時間提高或降低該組。我有一些數據庫,在一次基於集合的操作中,我不會再使用1000個數據庫。如果可能的話,應該爲數據庫運行的非高峯時段安排大型插入或更新。如果真的很大(一次性 - 通常是大數據遷移),您甚至可能想要關閉數據庫進行維護,將其置於單用戶模式並刪除索引,執行插入和重新索引。

1

簡短的回答是,它取決於選擇的大小。在技​​術上,select是事務的一部分,但大多數選擇不必「回滾」,所以DB更改的實際日誌不包含select本身。它包含的內容是select語句的每個結果的新行作爲插入語句。如果這個select語句是10k行,那麼提交會相當大,但不會比在一個顯式事務中寫入10k個單獨的insert語句更多。

1

這是如何工作的取決於數據庫。例如,在Oracle中,它將需要UNDO空間(並且最終,如果用完了,您的事務將被中止,或者您的DBA會對您大喊)。在PostgreSQL中,它會阻止舊行版本的清空。在MySQL/InnoDB中,它將使用回滾空間,並可能導致鎖定超時。

有幾件事情的數據庫必須使用空間:

  1. 存儲哪些行的交易已經改變(舊值,新的值,或兩者),以便能夠進行回滾
  2. 飼養跟蹤哪些數據對您的事務可見,以便維護一致的視圖(在事務隔離級別,而非讀取未提交)。這種開銷通常會在您請求的隔離度越高時越大。
  3. 跟蹤哪個數據是可見的其他交易
  4. 跟蹤哪個對象,其交易已經改變,所以隔離規則得到遵守,特別是在可序列化隔離(除非整個數據庫中讀取未提交運行)。 (可能沒有太多的空間,但大量的鎖)。

一般而言,您希望您的事務儘快提交。所以,例如,你不想讓一個空閒的連接打開。如何最好地進行批量插入取決於數據庫(通常,一次事務中的許多插入比每次插入一次事務更好)。當然,交易的主要目的是數據完整性。