0

ログ情報を保存するノード サーバーをセットアップしました。非常に大量のリクエストが来ることが予想されます。私は mongo データ ストアを使用していましたが、そのパフォーマンスは信頼性が低すぎます。レポート側でのデータの読み取りには、異常に長い時間がかかることがよくありました。そこで、従来の mysql に切り替えます。シングルトン挿入を行うのではなく、一括挿入を準備すると、書き込みスループットが大幅に向上することは明らかです。だから私はこの男を見つけました:

https://gist.github.com/3078520

シンプルさが大好きです。それはほんの一握りの行にあり、非常に強力です。add()レコードをキューに追加し、flush()キューが特定のサイズに達すると呼び出す2 つの主要な関数があります。そしてflush()、キューを 1 つの長い文字列に結合し、長い一括挿入ステートメントを作成してから、mysql ドライバーに送信します (提供されたリンクから関数を簡略化しました:

this.flush = function () {
/*1*/    var sql = queryTemplate.replace('{values}', '\n('+ queue.join('),\n(') +')');
/*2*/    handle.query(sql, callback);
/*3*/    queue = [];
}

これは基本的に、リクエスト ハンドラが所有する単一のクラス インスタンスの一部であるクラス関数です。だから私の質問は、これは安全ですか?はqueueクラス変数です。がflush()呼び出されると、キューを処理します。私が見ることができる唯一の問題は、flush()が呼び出された場合、行 1 が実行されて sql ステートメント (単なる文字列) が作成され、次に別の行add()が呼び出されて に何かが追加されqueue、最初のプロセスが関数を呼び出しquery()てキューを空にすることです。その場合、2 番目のプロセスによって追加されたレコードは失われます。これは、最初のプロセスが SQL ステートメントを作成したときにそれを知らず、queue. これは可能ですか?

この質問をより一般化した形式は次のようになります。関数の実行が開始されると、スコープ外の変数に外部から影響を与えることができますか? これは非常に簡単な例です。異なるリクエストがこれら2つの関数を呼び出すと仮定して、この例でconsole.logを実行することは 可能ですか?

var global_number;
function a(){
  global_number=2;
}
function b(){
  global_number=1;
  if(global_number==2){
    console.log("a() influenced global_number in the middle of b()'s execution")
  }
}

これは主にイエス/ノーの質問ですが、それ以上のものを探しています。簡単な説明、または詳細を学べるページへのリンクがあれば幸いです。ありがとう!

4

2 に答える 2

1

関数が同期の場合、関数が実行を開始してから完了するまでの間、その関数によって参照される変数に影響を与えることはできません。

ただし、関数が非同期関数 (MySQL クエリなど) を呼び出す場合、関数自体は非同期であり、関数が実行されてから非同期関数のコールバックが実行されるまでの間に、他のコードが関数の親/グローバル スコープ内の変数を変更できます。実行します。

于 2012-11-16T18:03:44.433 に答える
1

はい、関数の実行が非同期の場合、グローバル変数が所有するデータに問題がある可能性があります。テスト シナリオは次のとおりです。

var globalVariable = 10;

function a ()
{
    var timer = setInterval(function() {
        globalVariable--;
        console.log(globalVariable)
    }, 1000);
}

function b ()
{
    setTimeout(function() {
        globalVariable = 20;
    }, 3000);
}

a();
b();

これは出力されます:

9
8
7
19
18
17
16

非同期ではない関数実行割り込みを要求したらダメ!例を参照してください。

var globalVariable = 1000000000;
function a () {
    for(var i=0; i < 1000000000; i++)
    {
        if(globalVariable == 20000) console.log('From a() : ' + globalVariable);
        globalVariable--;
        if(globalVariable == 0) break;
    }
}

function b () {
    setTimeout(function() {
        console.log('From b() : ' + globalVariable);
        globalVariable = 20000;
        console.log('From b() : ' + globalVariable);
    }, 1);
}

b();
a();

これは常に出力されます:

From a() : 20000
From b() : 0
From b() : 20000

したがって、質問の答えは「いいえ」です。同期機能の実行を中断することはできません。

でも; あなたのコード スニペットの例では、行 1で withqueueのデータを既に消費しているため、を空にしても問題ないようです。SQL がエラーを返した場合、たとえば、を再設定できない場合があります。queuequeue.joinqueue

于 2012-11-16T18:12:07.620 に答える