2016-01-27 62 views
9

我正在處理幾天的問題,我真的很希望你能幫助我。在Node.js中處理回滾的MySQL事務

這是一個基於node.js的API,使用sequelize代表MySQL

在某些API調用中,代碼將啓動SQL事務,這些事務會鎖定某些表,如果我同時向API發送多個請求,我得到了LOCK_WAIT_TIMEOUT錯誤。

var SQLProcess = function() { 
    var self = this; 
    var _arguments = arguments; 

    return sequelize.transaction(function (transaction) { 
      return doSomething({transaction: transactioin}); 
     }) 
     .catch(function (error) { 
      if (error && error.original && error.original.code === 'ER_LOCK_WAIT_TIMEOUT') { 

       return Promise.delay(Math.random() * 1000) 
        .then(function() { 
         return SQLProcess.apply(self, _arguments); 
        }); 

      } else { 
       throw error; 
      } 
     }); 
}; 

我的問題是,同時運行的請求長時間鎖定對方,並且我的請求在很長時間(約60秒)後返回。

我希望我能解釋清楚,可以理解,並且可以爲我提供一些解決方案。

+0

這不是'node.js'或'sequelize'麻煩,這是來自MySQL的錯誤消息'1205鎖超時超時;嘗試重新啓動事務'。您應該查看MySQL服務器中的事務及其狀態。 –

+0

這很清楚,爲什麼我得到這個錯誤。我正在尋找解決方案,我可以如何處理它。 – Adam

+0

只有一種方法可以理解發生了什麼,它是'SHOW ENGINE INNODB STATUS \ G'。根據我的經驗,我在MySQL中多次發生了死鎖事務。 –

回答

3

這可能不是您的問題的直接答案,但也許通過查看爲什麼你有這個問題也會有所幫助。

1)doSomething()做了什麼?無論如何,我們可以在那裏做一些改進?

首先,需要60秒的事務是可疑的。如果你鎖定一張桌子很長時間,應該重新訪問設計。給定一個典型的數據庫操作運行10 - 100毫秒。

理想情況下,所有的數據準備都應該在事務之外完成,包括從數據庫中讀取的數據。而交易應該只針對交易操作。

2)是否可以使用mysql存儲過程?

確實,MySQL的存儲過程沒有被編譯爲Oracle的PL/SQL。但它仍在數據庫服務器上運行。如果你的應用程序真的很複雜,並且在該事務中包含大量的後臺數據庫和你的節點應用程序之間的網絡流量,並且考慮到有太多的javascript調用,它可能會減慢速度。如果1)不會爲您節省大量時間,請考慮使用mysql存儲過程。

顯然,這種方法的缺點是在nodejs和mysql中都難以維護代碼。

如果1)和2)肯定是不可能的,你可以考慮某種流量控制或排隊工具。您的應用程序可以確保第二個請求在第一個請求完成之前不會執行,或者您擁有一些第三方排隊工具來處理該請求。似乎無論如何您都不需要任何並行性來運行這些請求。

+0

謝謝!排隊工具做到了!我已經設置了一個「藍鳥隊列」,現在所有的請求都可以在沒有阻塞的情況下相互運行。 – Adam

2

死鎖的主要原因是數據庫設計不佳。如果沒有關於數據庫設計的進一步信息以及哪些確切的查詢可能會或可能不會彼此鎖定,則不可能爲您的問題提供具體的解決方案。

不過,我可以給你一個總體的意見/辦法來解決這個問題:

  • 我會確保你的數據庫是normalized至少爲第三範式或者,如果仍然不是足夠更深入。可能有工具爲您自動執行此過程。

    除了減少死鎖的可能性,這也有助於保持您的數據一致,這總是一件好事。
  • 保持您的交易儘可能苗條。如果您將新行插入到表中並相應地更新其他表,則可能需要使用Trigger而不是另一個SQL語句來執行此操作。這同樣適用於讀取行和值。這些事情可以在你的交易之前或之後完成。
  • 選擇正確的隔離級別。可能的隔離級別是:

    READ_UNCOMMITTED
    READ_COMMITTED
    REPEATABLE_READ
    SERIALIZABLE

    Sequelize的official documentation介紹如何設置隔離級別和鎖定/自行解鎖交易。



正如我所說的,沒有你的數據庫和查詢設計進一步瞭解這就是所有我能馬上爲你做。
希望這會有所幫助。