2016-01-27 39 views
9

私は数日間の約束を扱っています。私は本当にあなたが私を助けることを望んでいます。Node.jsのロールバックされたMySQLトランザクションの処理

の場合はsequelizeを使用しているnode.jsのAPIです。

特定の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

何が起こるのかを理解する方法は1つだけあり、 'SHOW ENGINE INNODB STATUS \ G'です。私の経験では、私はデッドロックのトランザクションをMySQLで複数回取得しています。 –

答えて

3

これはあなたの質問への直接の回答ではないかもしれませんが、この問題がなぜ役立ったのかを調べることで可能でしょう。

1)doSomething()は何をしますか?とにかくそこでいくつかの改善を行うことができますか?

最初に、60秒かかるトランザクションは疑わしいです。長い間テーブルをロックすると、デザインを再訪する可能性があります。典型的なDB操作が10〜100ミリ秒実行されると仮定します。

理想的には、すべてのデータ準備は、データベースから読み取られたデータを含むトランザクション外で行う必要があります。また、トランザクションは実際にはトランザクション操作のみに対応する必要があります。

2)mysqlストアドプロシージャを使用することはできますか?

trueの場合、mysqlのストアドプロシージャは、OracleのPL/SQLとしてコンパイルされません。しかし、それはまだデータベースサーバー上で実行されています。あなたのアプリケーションが本当に複雑で、そのトランザクションでデータベースとノード・アプリケーションの間に多くのバック・アンド・強制ネットワーク・トラフィックが含まれていて、JavaScriptコールの層が非常に多いと考えると、実際には遅くなる可能性があります。 1)多くの時間を節約できない場合は、mysqlストアドプロシージャの使用を検討してください。

明らかに、このアプローチの欠点は、nodejとmysqlの両方でコードを維持することが難しいことです。

1)と2)が間違いなく可能な場合は、何らかの種類のフロー制御またはキューイングツールが考えられます。どちらかのアプリは、最初のリクエストが完了するまで2番目のリクエストが行われないようにするか、それを処理するサードパーティのキューイングツールを用意してください。いずれにしても、これらの要求を実行する際に並列性は必要ないと思われます。

+0

ありがとう!キューイングツールがそれをしました!私は 'bluebird-queue'を設定しました。 – Adam

2

デッドロックの主な理由は、データベース設計が貧弱なためです。データベース設計についての詳細な情報がなく、正確なクエリが互いにロックされている場合とロックされていない場合がありますが、問題の特定の解決策を提供することは不可能です。私はあなたにこの問題を解決するための一般的なアドバイス/アプローチを与えることができますしかし


  • を私はあなたのデータベースがnormalized少なくともに第3正規形または、十分なことがまだイマイチ場合であることを確認してくださいうさらにもっと。このプロセスを自動化するツールがあります。

    デッドロックの可能性を減らすこととは別に、これはデータの一貫性を維持するのにも役立ちますが、これは常に良いことです。
  • できるだけスリムな取引をしてください。新しい行をテーブルに挿入し、それに応じて他のテーブルを更新する場合は、別のSQL文ではなくTriggerを使用してください。同じことが行と値の読み取りにも当てはまります。そのようなことは、取引の前後に行うことができます。
  • 隔離レベルを正しく選択してください。可能な分離レベルは以下のとおりです。

    READ_UNCOMMITTED
    READ_COMMITTED
    REPEATABLE_READ
    SERIALIZABLE

    Sequelizeのofficial documentationを使用すると、分離レベルを設定することができ、ロック/自分で取引をアンロックする方法について説明します。



私は今あなたのために何ができるすべてのthatsのデータベースとクエリ設計についてのさらなる洞察なしに、言ったように。
これが役に立ちます。

関連する問題