Skip to content

Instantly share code, notes, and snippets.

@kitak
Last active May 17, 2017 21:54
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save kitak/6372481 to your computer and use it in GitHub Desktop.
Save kitak/6372481 to your computer and use it in GitHub Desktop.
MySQLのreconnectについて

MySQLのreconnectとは

mysqlクライントでのreconnect

mysqlクライアントがステートメントの送信中にサーバとの接続が遮断された場合、 直ちに自動的に再接続し、ステートメントの送信を試みる(reconnect)。

注意:
再試行時には全セッションオブジェクトと設定(具体的にはテンポラリテーブル、オートコミットモード、ユーザー定義変数、 セッション変数、トランザクションロールバックなど)が失われているので、ステートメントによってはreconnectすることが危険なものもある。

reconnectしないようにmysqlクライアントを利用する場合には、--skip-reconnectオプションをつけてクライアントを立ち上げる。

MySQLのC APIとは

C APIコードはMySQLを使って配布される mysqlclient ライブラリの中に含まれ、これによってDBにアクセスできる。 MySQL付属のクライアントの多くはCで書かれている。

C APIでのreconnect の設定

#include <stdio.h>
#include <stdlib.h>
#include <mysql.h>

int main(int argc, char *argv[])
{
    MYSQL *conn;
    MYSQL_RES *res;
    my_bool reconnect = 1; // 1: 切断時に再接続しようと試みる 0: 試みない
    // この値は mysql_real_connect呼び出し後に((MYSQL* conn)->reconnect) に設定される
    // 5.0.3までのMySQLではデフォルト値は1, 5.1では0

    const char *server = "localhost";
    const char *user = "root";
    const char *password = "";
    const char *database = "IMO";

    conn = mysql_init(NULL);
    fprintf(stdout, "%d\n", conn->reconnect);

    // MYSQL_OPT_RECONNECT はMySQL5.0.13から有効
    mysql_options(conn, MYSQL_OPT_RECONNECT, &reconnect);
    if (mysql_real_connect(conn, server, user, password, database, 0, NULL, 0) == NULL) {
        fprintf(stderr, "%s\n", mysql_error(conn));
        exit(1);
    }
    fprintf(stdout, "%d\n", conn->reconnect);
}

ビルド例(MacOSX + homebrew)

gcc -I/usr/local/Cellar/mysql/5.6.10/include -L/usr/local/Cellar/mysql/5.6.10/lib mysql_sample.c -lmysqlclient

mysql2 gemでのreconnectの設定

https://github.com/brianmario/mysql2/blob/master/ext/mysql2/client.c から抜粋

// メソッド定義
rb_define_method(cMysql2Client, "reconnect=", set_reconnect, 1);
  
// ...
  
/* call-seq:
 *    client.reconnect = true
 *
 * Enable or disable the automatic reconnect behavior of libmysql.
 * Read http://dev.mysql.com/doc/refman/5.5/en/auto-reconnect.html
 * for more information.
 */
static VALUE set_reconnect(VALUE self, VALUE value) {
  return _mysql_client_options(self, MYSQL_OPT_RECONNECT, value);
}

// ...

static VALUE _mysql_client_options(VALUE self, int opt, VALUE value) {
  int result;
  void *retval = NULL;
  unsigned int intval = 0;
  my_bool boolval;

  GET_CLIENT(self);

  REQUIRE_NOT_CONNECTED(wrapper);

  if (NIL_P(value))
      return Qfalse;

  switch(opt) {
    case MYSQL_OPT_CONNECT_TIMEOUT:
      intval = NUM2INT(value);
      retval = &intval;
      break;

    case MYSQL_OPT_READ_TIMEOUT:
      intval = NUM2INT(value);
      retval = &intval;
      break;

    case MYSQL_OPT_WRITE_TIMEOUT:
      intval = NUM2INT(value);
      retval = &intval;
      break;

    case MYSQL_OPT_LOCAL_INFILE:
      intval = (value == Qfalse ? 0 : 1);
      retval = &intval;
      break;
    
    // 
    case MYSQL_OPT_RECONNECT:
      // QtrueはRubyの世界のtrue, QfalseはRubyの世界のfalse
      boolval = (value == Qfalse ? 0 : 1);
      retval = &boolval;
      break;

    default:
      return Qfalse;
  }

  // ここで実際に設定
  result = mysql_options(wrapper->client, opt, retval);

  /* Zero means success */
  if (result != 0) {
    rb_warn("%s\n", mysql_error(wrapper->client));
  } else {
    /* Special case for reconnect, this option is also stored in the wrapper struct */
    if (opt == MYSQL_OPT_RECONNECT)
      wrapper->reconnect_enabled = boolval;
  }

  return (result == 0) ? Qtrue : Qfalse;
}

参考文献

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment