データベース ミラーリングの使用 (JDBC)
データベース ミラーリングは、主にデータベースの可用性とデータの冗長性を向上するためのソフトウェア ソリューションです。Microsoft SQL Server JDBC Driver は、データベース ミラーリングを暗黙的にサポートするため、データベース用に構成されていれば、開発者がコードを記述したり、その他の操作を行ったりする必要はありません。
データベース ミラーリングは、データベースごとに実装され、スタンバイ サーバー上に SQL Server 運用データベースのコピーを保持します。このサーバーは、データベース ミラーリング セッションの構成と状態によって、ホット スタンバイ サーバーまたはウォーム スタンバイ サーバーのいずれかになります。ホット スタンバイ サーバーは、コミットされたトランザクションを損失することなくラピッド フェールオーバーをサポートし、ウォーム スタンバイ サーバーは、サービス強制をサポートします (データ損失の可能性があります)。
運用データベースはプリンシパル データベースと呼ばれ、スタンバイ コピーはミラー データベースと呼ばれます。プリンシパル データベースとミラー データベースは、SQL Server の別々のインスタンス (サーバー インスタンス) 上に存在する必要があります。また、可能であれば、これらのデータベースは別々のコンピュータ上に配置してください。
プリンシパル サーバーと呼ばれる運用サーバー インスタンスは、ミラー サーバーと呼ばれるスタンバイ サーバー インスタンスと通信します。プリンシパル サーバーとミラー サーバーは、データベース ミラーリング セッション内でパートナーとして機能します。プリンシパル サーバーで障害が発生した場合、ミラー サーバーはフェールオーバーと呼ばれる処理を通じて、ミラー サーバーのデータベースをプリンシパル データベースにできます。たとえば、Partner_A と Partner_B は 2 つのパートナー サーバーで、最初はプリンシパル サーバーの Partner_A にプリンシパル データベース、ミラー サーバーの Partner_B にミラー データベースが存在するとします。Partner_A がオフラインになった場合は、Partner_B 上のデータベースをフェールオーバーして、現在のプリンシパル データベースにできます。Partner_A がミラーリング セッションに再び参加すると、Partner_A はミラー サーバーとなり、Partner_A のデータベースはミラー データベースとなります。
Partner_A サーバーが破損して修復不可能な場合は、Partner_C サーバーをオンラインにして、プリンシパル サーバーとなった Partner_B のミラー サーバーとして機能させることができます。ただし、このシナリオでは、データベース ミラーリング構成で使用される新しいサーバー名で接続文字列プロパティが更新されるように、クライアント アプリケーションにプログラミング ロジックを含める必要があります。含めない場合、サーバーへの接続に失敗する可能性があります。
代替のデータベース ミラーリング構成では、さまざまなレベルのパフォーマンスおよびデータ安全性が提供され、異なる形式のフェールオーバーがサポートされます。詳細については、SQL Server オンライン ブックの「データベース ミラーリングの概要」を参照してください。
プログラムに関する考慮事項
プリンシパル データベース サーバーで障害が発生すると、クライアント アプリケーションは API 呼び出しの応答としてエラーを受信します。これは、データベースへの接続が失われたことを示します。この問題が発生すると、データベースに対するコミットされていない変更はすべて失われ、現在のトランザクションはロールバックされます。このような場合、アプリケーションでは接続を閉じて (または、データ ソース オブジェクトを解放して) から、再び開く必要があります。接続時に、新しい接続はプリンシパル サーバーとなったミラー データベースに透過的にリダイレクトされます。クライアントが接続文字列またはデータ ソース オブジェクトを変更する必要はありません。
接続が最初に確立されると、プリンシパル サーバーはフェールオーバー パートナーの ID を、フェールオーバー発生時に使用されるクライアントに送信します。アプリケーションが障害の発生したプリンシパル サーバーと最初の接続を確立しようとするとき、フェールオーバー パートナーの ID はクライアントに通知されていません。クライアントがこのシナリオに対処できるように、failoverPartner 接続文字列プロパティ、およびオプションで setFailoverPartner データ ソース メソッドを使用することで、クライアントはフェールオーバー パートナーの ID を独自に指定できます。クライアント プロパティはこのシナリオでのみ使用されます。プリンシパル サーバーが利用可能な場合は使用されません。
メモ : |
---|
接続文字列またはデータ ソース オブジェクトで failoverPartner が指定されている場合は、databaseName プロパティも設定する必要があります。これが設定されていないと、例外がスローされます。failoverPartner および databaseName が明示的に指定されていないと、プリンシパル データベース サーバーに障害が発生した場合に、アプリケーションがフェールオーバーを実行しません。つまり、透過的なリダイレクトは、failoverPartner および databaseName が明示的に指定された接続に対してのみ機能します。failoverPartner およびその他の接続文字列プロパティの詳細については、「接続プロパティの設定」を参照してください。 |
クライアントで指定されたフェールオーバー パートナー サーバーが、指定されたデータベースのフェールオーバー パートナーの役割を担っているサーバーを指していない場合、接続はサーバーによって拒否されます。SQLServerDataSource クラスは getFailoverPartner メソッドを提供しますが、このメソッドは接続文字列または setFailoverPartner メソッドで指定されたフェールオーバー パートナーの名前のみを返します。現在使用されている実際のフェールオーバー パートナーの名前を取得するには、次の Transact-SQL ステートメントを使用します。
SELECT m.mirroring_role_DESC, m.mirroring_state_DESC,
m.mirroring_partner_instance FROM sys.databases as db,
sys.database_mirroring AS m WHERE db.name = 'MirroringDBName'
AND db.database_id = m.database_id
メモ : |
---|
ミラーリング データベースの名前を使用するには、このステートメントを変更する必要があります。 |
接続の最初の試行が失敗した場合に備えて、接続文字列を更新するか、または再試行の戦略を立てるために、パートナー情報をキャッシュすることを検討してください。
例
次の例では、最初にプリンシパル サーバーへの接続が試行されます。接続に失敗して例外がスローされた場合、ミラー サーバーへの接続が試行されます。ミラー サーバーは新しいプリンシパル サーバーに昇格している可能性があります。接続文字列での failoverPartner プロパティの使用に注意してください。
import java.sql.*;
public class clientFailover {
public static void main(String[] args) {
// Create a variable for the connection string.
String connectionUrl = "jdbc:sqlserver://serverA:1433;" +
"databaseName=AdventureWorks;integratedSecurity=true;" +
"failoverPartner=serverB";
// Declare the JDBC objects.
Connection con = null;
Statement stmt = null;
try {
// Establish the connection to the principal server.
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
con = DriverManager.getConnection(connectionUrl);
System.out.println("Connected to the principal server.");
// Note that if a failover of serverA occurs here, then an
// exception will be thrown and the failover partner will
// be used in the first catch block below.
// Create and execute an SQL statement that inserts some data.
stmt = con.createStatement();
// Note that the following statement assumes that the
// TestTable table has been created in the AdventureWorks
// sample database.
stmt.executeUpdate("INSERT INTO TestTable (Col2, Col3) VALUES ('a', 10)");
}
// Handle any errors that may have occurred.
catch (SQLException se) {
try {
// The connection to the principal server failed,
// try the mirror server which may now be the new
// principal server.
System.out.println("Connection to principal server failed, " +
"trying the mirror server.");
con = DriverManager.getConnection(connectionUrl);
System.out.println("Connected to the new principal server.");
stmt = con.createStatement();
stmt.executeUpdate("INSERT INTO TestTable (Col2, Col3) VALUES ('a', 10)");
}
catch (Exception e) {
e.printStackTrace();
}
}
catch (Exception e) {
e.printStackTrace();
}
// Close the JDBC objects.
finally {
if (stmt != null) try { stmt.close(); } catch(Exception e) {}
if (con != null) try { con.close(); } catch(Exception e) {}
}
}
}