[前][次][番号順一覧][スレッド一覧]

mysql:15421

From: "Suzuki, Ikuo" <"Suzuki, Ikuo" <ikuo.suzuki@xxxxxxxxxx>>
Date: Tue, 9 Nov 2010 11:47:13 +0900
Subject: [mysql 15421] Connector/Jのフェイルオーバー時の接続がReadOnlyになる

日本ユニシス(株)でSEとして働いている鈴木と申します。
JavaによるWebアプリ開発経験が5年ほどありますが、
MySQLを利用し始めたのは1ヶ月ほど前からです。

MySQL ClusterとConnector/Jを利用してフェイルオーバーを
を実現しようとしているのですが、
failOverReadOnly=falseにしているにも関わらず接続が
Read Onlyになる問題で困っています。

クラスタは2台で形成しており、両方のマシンに
それぞれ管理ノード、SQLノード、データノードの機能を持たせた
以下の構成となっています。

【クラスタ構成】
========================================================================
ndb_mgm> show
Connected to Management Server at: localhost:1186
Cluster Configuration
---------------------
[ndbd(NDB)]     2 node(s)
id=3    @xxxxxxxxxx  (mysql-5.1.47 ndb-7.1.8, Nodegroup: 0)
id=4    @xxxxxxxxxx  (mysql-5.1.47 ndb-7.1.8, Nodegroup: 0, Master)

[ndb_mgmd(MGM)] 2 node(s)
id=1    @xxxxxxxxxx  (mysql-5.1.47 ndb-7.1.8)
id=2    @xxxxxxxxxx  (mysql-5.1.47 ndb-7.1.8)

[mysqld(API)]   2 node(s)
id=5    @xxxxxxxxxx  (mysql-5.1.47 ndb-7.1.8)
id=6    @xxxxxxxxxx  (mysql-5.1.47 ndb-7.1.8)
========================================================================

また、各ソフトウェアのバージョンは以下のとおりです。
【バージョン】
・MySQL 5.1.47
・MySQL Cluster 7.1.8
・Connector/J 5.1.13

前述の環境下でSQLノードの片方(id=5, 10.32.152.114)を停止して、
以下のプログラムを実行すると問題が再現します。

【プログラム】
========================================================================
package jp.co.unisys.mysql;

import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.util.Properties;

import com.mysql.jdbc.Connection;

public class Test {
  public static void main(String[] args) throws Exception {
    System.out.println("データのアップデートを開始します。");
    String url = "jdbc:mysql://10.32.152.114:3306,10.32.152.115:3306/test";
    Properties prop = new Properties();
    prop.put("autoReconnect", "true");
    prop.put( "roundRobinLoadBalance", "true" );
    prop.put("failOverReadOnly", "false");

    Class.forName("com.mysql.jdbc.Driver");
    Connection conn = (Connection) DriverManager.getConnection(url, prop);
    PreparedStatement ps = conn
        .prepareStatement("UPDATE dt_2 SET name=? WHERE id=1");
    try {
      for (int index = 0;; index++) {
        ps.setString(1, "New Name " + index);
        ps.executeUpdate();
        System.out.println("New Name " + index + " に更新しました。");
      }
    } finally {
      ps.close();
      conn.close();
    }
  }
}
========================================================================

期待する結果は10.32.152.114が落ちているため、
代わりに10.32.152.115に接続しUPDATEクエリを実行することなのですが、
実際には以下のように接続がRead Onlyという理由でUPDATEクエリが実行できま
せん。

【結果】
========================================================================
> java -jar test-5.1.13.jar
データのアップデートを開始します。
Exception in thread "main" java.sql.SQLException: Connection is
read-only. Queries leading to data modification are not allowed
        at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1075)
        at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:989)
        at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:984)
        at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:929)
        at
com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2360)
        at
com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2327)
        at
com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2312)
        at jp.co.unisys.epi.mysql.Test1.main(Test1.java:29)
========================================================================

ところで、Googleでバグトラッカーの過去ログを検索したところ、
以下の投稿をみつけました。

MySQL Bugs: #34946: failoverReadOnly=false with multimaster does not work
<http://bugs.mysql.com/bug.php?id=34946>

これを読むと、フェイルオーバーは必ずRead Onlyになるように
仕様変更されたので、failoverReadOnlyのフラグは機能せず、
廃止すべきだと言っていると思います。

この投稿から過去のバージョンでは挙動が違うのではと思い、
試しにConnector/Jのバージョンを5.0.8に変更して、
先ほどと同様のプログラムを実行してみました。
すると、UPDATEクエリを実行することができました。

【結果(一部)】
========================================================================
> java -jar test-5.0.8.jar
データのアップデートを開始します。
New Name 0 に更新しました。
New Name 1 に更新しました。
New Name 2 に更新しました。
New Name 3 に更新しました。
New Name 4 に更新しました。
New Name 5 に更新しました。
New Name 6 に更新しました。
New Name 7 に更新しました。
New Name 8 に更新しました。
New Name 9 に更新しました。
========================================================================

この結果から、片方のSQLノードが落ちた場合のフェイルオーバーは
Connector/Jの5.0.8を使えば実現できそうだと考えているのですが、
そもそも、なぜ5.0.8から5.1.13の間でこうした仕様変更がおこなわれたのか
を知りたいと思っています。

このあたりの事情をご存じの方はいらっしゃいましたら、
教えていただけないでしょうか?
どうぞよろしくお願い申し上げます。

以上
--------------------------------------------------------
日本ユニシス株式会社
ICTサービス基盤開発部 ソリューション開発室
開発3グループ
鈴木 生雄
tel:050-3132-6999 mailto:ikuo.suzuki@xxxxxxxxxx
--------------------------------------------------------

[前][次][番号順一覧][スレッド一覧]