2010-06-19 114 views
1

很多時候我的服務器掛起和MySQL顯示如下進程列表:奇怪鎖問題在MySQL

流程1: 時間:24 用戶:工人 狀態:鎖定 信息:LOCK TABLES tRatings WRITE,tUsers WRITE

過程2: 時間:24 用戶:工人 狀態:更新 信息:UPDATE SET tUsers fGender = '1' WHERE FID = 232049

流程3: 時間:24 用戶:工人 狀態:鎖定 信息:LOCK TABLES tClients READ,tUsers微安READ,tUsers AB READ,tNexts閱讀

所有的表InnoDB和我使用顯式LOCK TABLES來防止發生InnoDB死鎖。

我的問題是,我根本不明白這裏出了什麼問題!可以請別人解釋一下,爲什麼他只是在對方之後沒有進行手術?相反,對於(在本例中)24秒,所有進程都不做任何事情。

感謝,

+0

我假設你使用php + pdo? – 2010-06-19 11:00:19

回答

1

很多時候我的服務器掛起[...]所有的表InnoDB和我使用顯式LOCK TABLES防止死鎖的InnoDB的發生。

你沒有防止死鎖。您正在阻止自動死鎖檢測。讓我解釋一下:

當兩個(或多個)進程爭用相同的資源但按不同的順序時,會發生死鎖。例如:

  • 進程A需要資源2,則資源1.在成功搶奪資源2 ...
  • 但後來有一個上下文切換!進程B出現並獲取資源1,然後嘗試獲取資源2,但不能因爲A已將其保留(無論是在事務中還是在鎖中),所以B被擱置。
  • 上下文切換! A再次出現並試圖獲取資源1,但它由進程B保存。
  • A現在正在等待B,B現在正在等待A.這是一個死鎖。

在事務內部發生這種情況時,數據庫引擎可以檢測到發生了死鎖並終止其中一個負責連接,從而允許另一個連接繼續。

當您使用LOCK TABLES時,您不允許數據庫引擎執行死鎖檢測,因此死鎖會一直存在,直到您手動出現並殺死其中一個死鎖進程。更糟糕的是,LOCK TABLES也可以防止讀取,並且可以很容易地將您的整個應用程序暫停。

停止使用LOCK TABLES

在需要事務完整性的代碼區域開始使用事務。做不是無處不在。

如果您正在接收死鎖,您可能有不同的代碼路徑,以不同的順序執行相關數據位的相關操作,您沒有在正確的位置使用事務。

還有其他的選擇。一種是設計你的數據庫例程,以便它們檢測死鎖發生的時間,並開始重新播放所需的事件,以便再次進行。換句話說,你會回滾,重新啓動交易,並嘗試再次做同樣的事情。有可能當時導致僵局的情況已經解決,所以你可能會好起來的。不幸的是,死鎖中涉及的其他進程可能會改變您正在使用的一些數據,因此在複雜的一方重新啓動可能會有點麻煩。

最後,另一種選擇是根本不使用事務或鎖。你不是在處理金錢,是嗎?看起來你正在處理用戶和評級。這是相當簡單的數據。沒有人會關心或注意,如果當前的評級缺少在某人做出導致評級被重新計算的事情之後立即註冊的投票。