2010-03-22 30 views
7

初步交易:MySQL的:多個線程之間

我有保持約100線程的線程池的應用程序。每個線程可以在新任務取代之前持續約1-30秒。當一個線程結束時,該線程幾乎總會導致在表中插入1-3條記錄,該表由所有線程使用。目前,還沒有交易支持,但我現在試圖補充說明。另外,有問題的表是InnoDB。所以......

目標

我想要實現這個交易。該事務是否提交或回滾的規則駐留在主線程中。基本上有一個簡單的函數將返回一個布爾值。

  1. 我可以通過多個連接實現事務嗎?
  2. 如果不是,多個線程可以共享相同的連接嗎? (注意:這裏有很多插入,這是一個要求)。

回答

3

那麼,正如不同的答案中所述,您無法在多個連接之間創建事務。你可以通過線程共享單個連接。 但是你需要非常小心。您需要確保只有一個線程同時寫入連接。你不能只讓多個線程在同一個連接上進行交談,而沒有以某種方式同步他們的活動。如果允許兩個線程同時對話(客戶端庫中的內存損壞等),可能會發生不好的事情。使用互斥或​​關鍵部分來保護連接對話可能是一種方式。

-Don

+0

也許,我想我可能會重新考慮這一點,只需讓線程在主線程的測試完成後等待完成即可。 – Zombies 2010-03-22 21:27:30

+0

只是一個念頭,沒有測試:如果你自己做了'start_transaction()'和'commit()''''rollback()'函數,並且你在'start_transaction()'中鎖定了一個互斥鎖,結束時,交易將更安全地在線程中使用。我不會說它會起作用,因爲它來自不同的連接。它只是有時你在線程中開始交易,並且你依賴它們是原子的。還要注意,mysql sais一次只有一個查詢應該在所有線程中運行。這包括從查詢的運行到結果的完整獲取。 – NickSoft 2013-02-15 13:10:22

+0

通過連接進行通信需要序列化。一種方法是擁有專用的通信線程,並讓其他線程完成所需的任何工作,然後將結果傳遞給通信線程,從而將語句序列化。 – 2013-11-22 15:31:33

4

1)不,交易僅限於單個數據庫連接。

2)是的,一個連接(和事務)可以在多個線程之間共享。

+0

至於(2),如果表是INNODB,我認爲多個插入同時發生是安全的? – Zombies 2010-03-22 21:07:15

+0

@殭屍是的,雖然我沒有InnoDB和Transactions的經驗,但我相信應該沒問題。我認爲沒有理由不工作。 – 2010-03-22 21:11:16

0

許多線程之間的共享連接通常通過使用連接池來實現。每個線程都可以從池中請求連接,將其用於其目的(一個或多個事務,已提交或回滾),並在任務完成後將其交回池中。

這是應用程序服務器爲您提供的。他們也會照顧交易,我。即當請求事務的方法正常結束時,提交更改,如果拋出異常,數據庫事務將回滾。

我建議你看看Java EE 5或6 - 它非常易於使用,甚至可以在嵌入式系統中使用。爲了輕鬆入門,請查看Netbeans和Glassfish應用服務器。然而,一般概念適用於所有應用程序服務器。

至於InnoDB,它不會有任何處理大量事務的問題。在應用程序服務器的監督下,您可以專注於業務邏輯,不必擔心半寫更新或任何人在發起事務之前已經看到更新/插入內容。

InnoDB使用MVCC(多版本併發控制),有效地爲每個事務提供整個數據庫的啓動時間的快照。您可以在相關問題中閱讀有關MVCC的更多信息:Question 812512

+0

這不會被部署在J2EE上。但是將來會使用J2SE連接池。所以我認爲我可以回滾連接池中的所有連接...? – Zombies 2010-03-22 21:16:15

+0

是的,MVCC默認爲「可重複讀取」的事務隔離級別,這意味着一旦事務已經讀取了第一位數據,它將不會看到來自其他事務的任何更新,即使這些更新已被提交。只有當提交或回滾當前事務時,此連接上的下一個事務纔會看到來自其他所有承諾的新數據。 – 2010-03-22 21:20:37

+0

需要說明的是:您將無法發出單一的「回滾所有打開的事務」命令。但是,這通常不是你想要的 - 如果是這樣的話,我認爲你需要對系統進行更多的闡述,因爲它看起來不正確。 – 2010-03-22 21:21:53