質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.76%

  • MySQL

    5517questions

    MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

  • Node.js

    1732questions

    Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

  • Socket.IO

    178questions

    Socket.IOはNode.js上で動くライブラリであり、すべてのブラウザとモバイルデバイスでリアルタイムのアプリを作動させる事を目的としています。

  • 非同期処理

    101questions

    非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

Node.js Socket.IOにて送信されたデータをMySQLデータベースへ保存する際の動作について疑問があります

解決済

回答 2

投稿

  • 評価
  • クリップ 1
  • VIEW 200

Engineer-IT

score 1

 前提・実現したいこと

Node.jsにてSocket.IOを利用した純粋なチャットアプリを作成しています。

ユーザーから送信されたメッセージをMySQLデータベースへ保存したいと思っているのですが、Node.jsは非同期処理で且つmysqlライブラリもfunctionを利用するので、例えばユーザーからほぼ同時に100件などのメッセージがきた場合に接合性のあるデータ保存が可能なのか疑問があります。正しく保存を完了する前に次の処理へ行くのではないかと思いました。

実際どうなのでしょうか?
よろしくお願い致します!

 該当のソースコード(Expressのwwwにコード記述)

// ここにデータベース接続処理

// 以下、Socket.IOの例
var socketio = require('socket.io');

server.on('listening', onListening);
var io = socketio.listen(server);

io.on('connection', function (socket) {
  socket.on('chat message', function (data) {
        // MySQL データベースへ送信されたメッセージを保存
        connection.query('INSERT INTO `message` (text) VALUES (?)', [data], function (error, results, fields) {
          if (error) console.log(error);
        });
  });
});
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • maisumakun

    2018/05/08 10:19 編集

    具体的に、どのような意味合いでの「整合性」を懸念していらっしゃいますでしょうか。

    キャンセル

  • coco_bauer

    2018/05/08 10:20

    どういう条件が満たされると「正しく保存」になるのでしょうか?チャットアプリの「純粋な」を満たすための条件も明らかにしてください。

    キャンセル

  • Engineer-IT

    2018/05/08 10:26 編集

    すいません、定義が不足していました。送信された'chat message'の全てがMySQLデータベースに保存されるかどうかです。ミリ秒の誤差で複数の'chat message'が送信されてきた場合に、MySQLデータベースへそれぞれメッセージを保存完了する前に次の処理(Socket.IOのchat messageが呼び出されるので)へ行ってしまい全てのチャットメッセージが保存されない懸念がございました。

    キャンセル

  • Engineer-IT

    2018/05/08 10:34

    純粋に関しては比喩でありますがその言葉の意味の通りで、特殊な仕様などなくSocket.IOの公式サイトにあるデモのようなものです。特に深い意味などはなく、この状況において重要なものではございません。

    キャンセル

回答 2

+3

実際には懸念が一つだけありますが、基本的には大丈夫でしょう。

例えばユーザーからほぼ同時に100件などのメッセージがきた場合に接合性のあるデータ保存が可能なのか

これは間違いなく大丈夫です。
何故ならNode.jsはシングルスレッドであり、なんちゃって並列処理だからです。

ざっと説明しておきますと、Node.jsはイベントループという概念で内部は動いてます。
node index.js等と実行された時に、Node.jsは対象のソースコードに書かれている処理を全て処理してしまいます。
全て処理し終えたNode.jsはイベントループという巡回を行うだけのモードに移行します。

socket.on('chat message', fn)はイベント登録です。
ユーザーからのメッセージを受け取った時点でイベントの発火条件がクリアされて関数fnが発火準備状態になります。

その後、イベントループで順番待ちになっているfnを1個だけ掴んで処理し始めます。
1個の順番待ちをこなしたら、次の順番待ちのfnを処理し始めます。
このように目にも留まらぬ速さで処理しまくるイベントループ君ですが、一度に処理出来るのは常に1個だけです。

そしてio.on('connection', fn)という風に各ユーザの情報は関数スコープによって閉じられていますので、
大量にメッセージを受け付けたとしてもスコープが別なのでAユーザの発言とBユーザの発言が混ざるという事もありません。

それを証拠に下記のように無限ループを作って後続の処理が行われないようにしておくと、
次のユーザがメッセージを送信出来なくなるはずです。

io.on('connection', function (socket) {
  socket.on('chat message', function (data) {
     console.log(data);
     while(true) var i = 0;
  });
});

おまけ: 懸念に関して

これは単純に私がsocket.ioを利用した事が無いから来る疑問点です。

TCPで受信出来るパケット数は限られている為、
長文を受け取ると1つのメッセージを2段階に分けて受信する可能性があります。

例えば平成の菅原道真がチャットに出現して、「いろはにほへと……」と長文のポエムを送信したとしましょう。
「いろはn」「iほへと」みたいな文字の途中で切られてしまった場合、
UTF-8の日本語は3バイトなのでバイト列の途中でぶった切られ、文字化けの原因になります。

更に文字列が区切られるので2メッセージ扱いとなり、MySQLには2レコードが挿入されます。

この場合、クライアント側はチャット内容のテキストメッセージ本体を送信するのではなく、一度JSON.stringifyで文字列1個のJSONに変換すると良いかもしれません。
そうすればサーバ側でJSON.parseで評価出来ずエラー落ちした場合、
一度文字列を退避させておいて、後続のメッセージと一緒にくっつけるという手が使えます。

まずは一度長文の文字列を放り込んで確認してみてください。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/05/08 11:47

    滅茶苦茶分かりやすいです!本当助かります!
    その他の疑問点も解消されました。ありがとうございます!

    キャンセル

checkベストアンサー

+1

ミリ秒の誤差で複数の'chat message'が送信されてきた場合に、MySQLデータベースへそれぞれメッセージを保存完了する前に次の処理(Socket.IOのchat messageが呼び出されるので)へ行ってしまい全てのチャットメッセージが保存されない懸念がございました。

特に問題ありません。次の処理が始まっても、保存処理は別個に続いています

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/05/08 10:44

    なるほど、ありがとうございます!

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.76%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • MySQL

    5517questions

    MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

  • Node.js

    1732questions

    Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

  • Socket.IO

    178questions

    Socket.IOはNode.js上で動くライブラリであり、すべてのブラウザとモバイルデバイスでリアルタイムのアプリを作動させる事を目的としています。

  • 非同期処理

    101questions

    非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

  • トップ
  • MySQLに関する質問
  • Node.js Socket.IOにて送信されたデータをMySQLデータベースへ保存する際の動作について疑問があります