web-dev-qa-db-ja.com

pool.query()とpool.set GetConnection()は、connection.release()でどのように異なりますか?

すべてのpool.query()は接続にコストがかかることを理解できるので、終了時に自動的に解放されます。 github issue に関するこのコメントに基づいています。しかし、pool.getConnection()を使用して実行されるネストされたクエリはどうですか?

_pool.getConnection(function(err, connection) {

  // First query
  connection.query('query_1', function (error, results, fields) {

    // Second query
    connection.query('query_2', function (error, results, fields) {

          // Release the connection
          // DOES THIS ALSO RELEASE query_1?
          connection.release();

          if (error) throw error;

          // you can't use connection any longer here..
    });
  });
});
_

更新

ネストされたクエリを実行するときにトランザクションを使用する私のコードは次のとおりです。

_const pool = require('../config/db');

function create(request, response) {
   try {

       pool.getConnection(function(err, con) {

           if (err) {
               con.release();
               throw err;
           }

           con.beginTransaction(function(t_err) {

               if (t_err) {
                   con.rollback(function() {
                      con.release();
                      throw t_err;
                   });
               }


               con.query(`insert record`, [data], function(i_err, result, fields){

                   if (i_err) {
                       con.rollback(function() {
                           con.release();
                           throw i_err;
                       });
                   }


                   // get inserted record id.
                   const id = result.insertId;

                   con.query(`update query`, [data, id], function(u_err, result, fields)=> {

                       if (u_err) {
                          con.rollback(function() {
                             con.release();
                             throw u_err;
                          });
                       }

                       con.commit(function(c_err){
                          if (c_err) {
                             con.release();
                             throw c_err;
                          }
                       });

                       con.release();

                       if (err) throw err;

                       response.send({ msg: 'Successful' });
                   });
               });

           });
       });

   } catch (err) {
      throw err;
   }
}
_

この時点ではアクティブなすべての接続を適切に解放する方法がわからないので、私は多くの防御的なエラーキャッチとcon.release()を作成しました。

また、con.query()内のすべてのpool.getConnection()が接続にかかると想定しています。

9
Roel

編集:

connectionは、アプリケーションをデータベースに接続するワイヤーのようなものです。 connection.query()を実行するたびに、そのワイヤーに沿ってメッセージを送信するだけで、ワイヤーを交換するわけではありません。

poolconnectionを要求すると、すでに用意されている「ワイヤー」が提供されるか、データベースへの新しいワイヤーが作成されます。プールされた接続をrelease()すると、プールはそれを再利用しますが、再び必要になった場合に備えてしばらくは保持します。

したがって、queryは接続線に沿ったメッセージです。必要なだけメッセージを送信できます。これは1本のワイヤーだけです。


元の回答

pool.query(statement, callback)は本質的に

const query = (statement, callback) => {
    pool.getConnection((err, conn) => {
        if(err) {
            callback(err);    
        } else {
            conn.query(statement, (error, results, fields) => {
                conn.release();
                callback(error, results, fields);
            });
        }
    })
}

理想的には、行っている往復の数と同じくらい接続について心配するべきではありません。プール構成で複数のステートメントを有効にすることができますmultipleStatements: trueプールの構築に続いて、トランザクションを利用します。

BEGIN;
INSERT ...;
SELECT LAST_INSERT_ID() INTO @lastId;
UPDATE ...;
COMMIT;
7
Mark Cooper

最初のクエリを必要なだけ早く閉じていないようです。

実際のコードをご提示ください。 insertidを取得するためにqueryを使用する必要はありません。

(質問への更新後:)「ネスト」の必要性がわかりません。コードは線形です(エラーをスローする場合を除く):

BEGIN;
INSERT ...;
get insertid
UPDATE ...;
COMMIT;

ステップが失敗した場合は、エラーをスローします。 2つの「接続」が必要ないようです。 INSERTを開始する前にUPDATEを終了したため、SQLコマンドを「ネスト」する必要はありません。そしてget insertidは、実際のSQLコマンドを含まないメタ操作です。

1
Rick James

Node.jsはわかりませんが、コードとGithubのドキュメントを見ると、pool.getConnectionが接続プールから接続を取得し、接続オブジェクトを取得して関数を呼び出し、取得中にエラーが発生したことはほぼ確実ですプールからの接続。関数本体内では何度でも接続オブジェクトを使用できますが、解放されるとプールに戻るため、使用できなくなります。接続オブジェクトには、基になるmysql接続への参照がなくなると思います(少し低いレベルの接続オブジェクトがある場合があります)。これで、接続オブジェクトを1回だけ解放する必要があり、接続プールからの空き接続を使いたくない場合は、接続オブジェクトを解放する必要があります。それ以外の場合、pool.getConnectionへの後続の呼び出しは、接続の「フリー」リストから接続を見つけられません。接続の「in_use」リストにすでに移動されており、解放されないためです。

通常、接続プールから接続を取得した後、それは任意の数の操作/クエリに使用でき、プールの「フリー」リストに戻すために「1回」解放されます。これが、接続プールが一般的に機能する方法です。

0
Nipun Talukdar