1

現在、mysql.h を使用して MYSQL データベースに接続する C++ クライアント アプリケーションがあり、切断が発生した場合に備えていくつかのロジックを実行する必要があります。クライアントが切断された状況で、これが MYSQL データベースに再接続する最良の方法かどうか疑問に思っています。

bool MYSQL::Reconnect(const char *host, const char *user, const char *passwd, const char *db)
{
bool out = false;

pid_t command_pid = fork();
if (command_pid == 0)
{
    while(1)
    {
        sleep(1);
        if (mysql_real_connect(&m_mysql, host, user, passwd, db, 0, NULL, 0) == NULL )
        {
            fprintf(stderr, "Failed to connect to database: Error: %s\n",
            mysql_error(&m_mysql));
        }
        else
        {
            m_connected = true;
            out = true;
            break;
        }
    }
    exit(0);
}

if (command_pid < 0)
    fprintf(stderr, "Could not fork process[reconnect]: %s\n", mysql_error(&m_mysql));

return out;
}

現在、すべてのパラメーターを取り込んでフォークを実行しています。子プロセスは、sleep() ステートメントを使用して毎秒再接続を試みます。これはこれを行う良い方法ですか?ありがとう

4

3 に答える 3

4

申し訳ありませんが、あなたのコードはあなたが思っているようには動作しません、カイザー・ヴィルヘルム。

本質的に、フォークをスレッドのように扱おうとしていますが、そうではありません。

子を fork すると、親プロセスは、ファイルとソケット記述子を含めて完全に複製されます。これにより、プログラムは MySQL データベース サーバーに接続されます。つまり、フォークすると、親と子の両方が、データベース サーバーへの同じ接続の独自のコピーになります。親Reconnect()は、接続が切断されたことを確認したときにのみこのメソッドを呼び出し、現在は機能していない MySQL 接続オブジェクトのコピーの使用を停止すると想定していますm_mysql。その場合、親の接続のコピーは、再接続操作を開始したときにクライアントのコピーと同じように役に立ちません。

問題は、逆もまた真ではないということです。子がデータベース サーバーへの再接続に成功すると、親の接続オブジェクトは機能しなくなります。子が行うことは何も親に反映されません。フォーク後、2 つのプロセスは完全に独立していますが、最初に共有していた I/O リソースにアクセスしようとする場合を除きます。たとえば、接続が確立されている間にこれReconnect()を呼び出し、親の接続を使用し続けた場合、子が同じ接続で DB サーバーと通信しようとすると、 または のいずれmysqldかが混乱しlibmysqlclient、データの破損またはクラッシュが発生する可能性があります。

上で示唆したように、これに対する 1 つの解決策は、フォークの代わりにスレッドを使用することです。ただし、MySQL C API でスレッドを使用する際の多くの問題に注意してください。

選択肢があれば、非同期 I/O を使用してアプリケーションのメイン スレッド内でバックグラウンド接続を試行したいと思いますが、MySQL C API ではそれができません。

DB サーバーの再接続を試みている間、メイン アプリケーション スレッドのブロックを回避しようとしているようです。いずれにせよ、接続タイムアウトを 1 秒に設定することにより、同期的に実行することを回避できる可能性があります。これは、MySQL サーバーがクライアントと同じマシンまたは同じ LAN 上にある場合に問題ありません。接続試行が失敗するまでメイン スレッドが最大 1 秒間ブロックされることを許容できる場合 (最悪の場合、サーバーが別のマシン上にあり、物理的に切断されているか、ファイアウォールで保護されている場合に発生します)、これはおそらくスレッドよりもクリーンなソリューションです。サーバー マシンがまだ実行中で、ポートがファイアウォールで保護されていない場合 (再起動中、TCP/IP スタックが [まだ] 起動している場合など) は、接続試行がはるかに迅速に失敗する可能性があります。

于 2011-08-10T17:14:49.440 に答える
0

私が知る限り、これはあなたが意図したことではありません。

論理的な問題

Reconnect「切断があった場合に備えて何らかのロジックを実行する」ことはまったくありません。

成功するまで何度も接続を試み、その後停止します。それでおしまい。接続の状態が再度チェックされることはありません。接続が切断された場合、このコードはそれについて何も知りません。

技術的な問題

また、ウォーレンが提起する技術的な問題にも細心の注意を払ってください。

于 2011-08-10T17:24:55.070 に答える
-2

確かに、それは完全に大丈夫です。while ( 1 )ループを次のようなものに置き換えることを検討することをお勧めします

  while ( NULL == mysql_real_connect( ... )) {
    sleep( 1 );
    ... 
  }

これは、実践によって学ぶようなイディオムですが、私が見る限り、コードは問題なく機能します。whileループ 内にカウンターを置くことを忘れないでください。

于 2011-08-08T18:44:38.537 に答える