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 --------------------------------------------------------