‘데이터베이스 미러링 사용(JDBC)
데이터베이스 미러링은 주로 데이터베이스의 가용성 및 데이터 중복도를 높이기 위한 소프트웨어 솔루션입니다. Microsoft JDBC Driver for SQL Server에서는 데이터베이스 미러링을 암시적으로 지원하므로 데이터베이스에 대해 이 드라이버를 구성한 경우 개발자가 임의의 코드를 작성하거나 별도의 조치를 취할 필요가 없습니다.
데이터베이스별로 구현되는 데이터베이스 미러링은 SQL Server 프로덕션 데이터베이스의 복사본을 대기 서버에 유지합니다. 이 서버는 데이터베이스 미러링 세션의 구성 및 상태에 따라 핫 대기 서버나 웜 대기 서버가 됩니다. 커밋된 트랜잭션의 손실 없이 신속한 장애 조치(failover)를 지원할 수 있는 상시 대기 서버입니다. 웜 대기 서버는 서비스 강제 적용을 지원합니다(데이터가 손실될 수 있음).
프로덕션 데이터베이스를 주 데이터베이스라고 하며 대기 복사본을 미러 데이터베이스라고 합니다. 주 데이터베이스 및 미러 데이터베이스는 별도의 SQL Server 인스턴스(서버 인스턴스)에 있어야 합니다. 가능하다면 별도의 컴퓨터에 있어야 합니다.
프로덕션 서버 인스턴스(주 서버)는 대기 서버 인스턴스(미러 서버)와 통신합니다. 주 서버와 미러 서버는 데이터베이스 미러링 세션에서 파트너로 기능합니다. 주 서버가 실패하면 미러 서버가 장애 조치(failover)라는 프로세스를 통해 미러 서버의 데이터베이스를 주 데이터베이스로 만들 수 있습니다. 예를 들어 서로 파트너 관계인 Partner_A와 Partner_B 서버가 있는데, 처음에 주 데이터베이스는 주 서버인 Partner_A에 상주하고 미러 데이터베이스는 미러 서버인 Partner_B에 상주한다고 가정합니다. Partner_A가 오프라인이 된 경우 Partner_B에 있는 데이터베이스가 장애 조치(Failover)되어 현재 주 데이터베이스가 될 수 있습니다. Partner_A가 미러 세션에 다시 조인하면 미러 서버가 되고, 데이터베이스는 미러 데이터베이스가 됩니다.
Partner_A 서버가 돌이킬 수 없는 손상을 입은 경우 Partner_C 서버를 온라인 상태로 설정하여 현재 주 서버인 Partner_B 미러 서버로 기능하게 할 수 있습니다. 그러나 이 시나리오에서 클라이언트 응용 프로그램에는 데이터베이스 미러링 구성 시 사용되는 새 서버 이름으로 연결 문자열 속성이 업데이트되도록 하는 프로그래밍 논리가 포함되어야 합니다. 이러한 논리가 없다면 서버 연결이 실패할 수 있습니다.
대체 데이터베이스 미러링 구성은 다양한 수준의 성능 및 데이터 안전성을 제공하며 다양한 형태의 장애 조치(failover)를 지원합니다. 자세한 내용은 SQL Server 온라인 설명서의 "데이터베이스 미러링 개요"를 참조하세요.
프로그래밍 고려 사항
주 데이터베이스 서버가 실패하면 클라이언트 응용 프로그램은 API 호출에 대한 응답으로 오류를 수신하며, 이는 데이터베이스에 대한 연결이 끊어졌음을 나타냅니다. 이러한 오류가 발생하는 경우 커밋되지 않은 모든 데이터베이스 변경 내용이 손실되며 현재 트랜잭션은 롤백됩니다. 이 시나리오에서 응용 프로그램은 연결을 닫고(또는 데이터 원본 개체를 해제하고) 다시 연결해야 합니다. 연결 시 클라이언트가 연결 문자열이나 데이터 원본 개체를 수정할 필요 없이 새로운 연결이 현재 주 서버 역할을 하고 있는 미러 데이터베이스로 투명하게 리디렉션됩니다.
처음에 연결이 설정되면 주 서버는 장애 조치(Failover) 파트너의 ID를 장애 조치(Failover) 시 사용할 클라이언트로 보냅니다. 응용 프로그램에서 실패한 주 서버와의 초기 연결을 설정하려고 할 때, 클라이언트는 장애 조치(failover) 파트너의 ID를 알지 못합니다. failoverPartner 연결 문자열 속성 및 setFailoverPartner 데이터 원본 메서드(옵션)는 클라이언트가 본인의 장애 조치(failover) 파트너의 ID를 지정할 수 있게 허용하여 클라이언트가 이러한 시나리오에 대처할 수 있도록 합니다. 클라이언트 속성은 이 시나리오에서만 사용됩니다. 주 서버를 사용할 수 있으면 사용되지 않습니다.
참고 항목
연결 문자열이나 데이터 원본 개체에 failoverPartner를 지정한 경우 databaseName 속성도 설정해야 하며 그렇지 않은 경우 예외가 발생합니다. failoverPartner 및 databaseName을 명시적으로 지정하지 않으면 주 데이터베이스 서버가 실패할 때 응용 프로그램에서 장애 조치(failover)를 시도하지 않습니다. 즉, failoverPartner 및 databaseName을 명시적으로 지정하는 연결에서만 투명 리디렉션이 작동합니다. failoverPartner 및 기타 연결 문자열 속성에 대한 자세한 내용은 연결 속성 설정을 참조하세요.
클라이언트가 제공한 장애 조치(failover) 파트너 서버가 지정된 데이터베이스에 대한 장애 조치(failover) 파트너 역할을 하는 서버를 참조하지 않고 참조된 서버/데이터베이스가 미러링된 배열로 되어 있는 경우 해당 서버에서 연결을 거부합니다. SQLServerDataSource 클래스는 getFailoverPartner 메서드를 제공하지만 이 메서드는 연결 문자열 또는 setFailoverPartner 메서드에 지정된 장애 조치(failover) 파트너의 이름만 반환합니다. 현재 사용 중인 실제 장애 조치(failover) 파트너의 이름을 검색하려면 다음 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.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class ClientFailover {
public static void main(String[] args) {
String connectionUrl = "jdbc:sqlserver://serverA:1433;"
+ "encrypt=true;databaseName=AdventureWorks;integratedSecurity=true;"
+ "failoverPartner=serverB";
// Establish the connection to the principal server.
try (Connection con = DriverManager.getConnection(connectionUrl);
Statement stmt = con.createStatement();) {
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.
// Execute a SQL statement that inserts some data.
// 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)");
}
catch (SQLException se) {
System.out.println("Connection to principal server failed, " + "trying the mirror server.");
// The connection to the principal server failed,
// try the mirror server which may now be the new
// principal server.
try (Connection con = DriverManager.getConnection(connectionUrl);
Statement stmt = con.createStatement();) {
System.out.println("Connected to the new principal server.");
stmt.executeUpdate("INSERT INTO TestTable (Col2, Col3) VALUES ('a', 10)");
}
// Handle any errors that may have occurred.
catch (SQLException e) {
e.printStackTrace();
}
}
}
}