Usar la creación de reflejo de la base de datos (JDBC)
La creación de reflejo de la base de datos es un solución de software destinada a aumentar la disponibilidad de la base de datos y la redundancia de los datos. El controlador JDBC de Microsoft SQL Server 2005 ofrece una compatibilidad implícita con la creación de reflejo de la base de datos de modo que el programador no tenga que escribir ningún código ni realizar ninguna otra acción una vez configurado para la base de datos.
La creación de reflejo de la base de datos, implementada para cada base de datos, conserva una copia de una base de datos de producción de SQL Server 2005 en un servidor en espera. Este servidor es un servidor en estado de espera activa o semiactiva según la configuración y el estado de la sesión de creación de reflejo de la base de datos. Un servidor en estado de espera activa admite una conmutación por error rápida sin que se produzca una pérdida de las transacciones confirmadas y un servidor en estado de espera semiactiva admite el forzado del servicio (con una posible pérdida de datos).
La base de datos de producción se llama base de datos principal y la copia en espera se llama base de datos reflejada. La base de datos principal y la base de datos reflejada deben residir en instancias independientes de SQL Server 2005 (instancias de servidor) y en equipos distintos si es posible.
La instancia del servidor de producción, llamado servidor principal, se comunica con la instancia del servidor en espera, llamado servidor reflejado. Los servidores principal y reflejado actúan como asociados en la sesión de creación de reflejo de la base de datos. Si el servidor principal genera un error, el servidor reflejado puede convertir su base de datos en la base de datos principal mediante un proceso llamado conmutación por error. Por ejemplo, Partner_A y Partner_B son dos servidores asociados, con la base de datos principal en Partner_A como servidor principal al inicio y la base de datos reflejada en Partner_B como servidor reflejado. Si se interrumpe la conexión de Partner_A, la base de datos de Partner_B puede conmutar por error a la base de datos principal actual. Si Partner_A se vuelve a combinar con la sesión de creación de reflejo, se convierte en el servidor reflejado y su base de datos se convierte en la base de datos reflejada.
En caso de que el servidor Partner_A se dañe de forma irreparable, se puede conectar un servidor Partner_C para que actúe como un servidor reflejado para Partner_B, que es ahora el servidor principal. No obstante, en este escenario, la aplicación cliente debe incluir una lógica de programación para asegurarse de que las propiedades de la cadena de conexión se actualizan con los nombres de servidor nuevos usados en la configuración de la creación de reflejo de la base de datos. En caso contrario, es posible que la conexión con los servidores no se realice.
Las configuraciones alternativas de la creación de reflejo de la base de datos ofrecen distintos niveles de rendimiento y seguridad de los datos y son compatibles con varias formas de conmutación por error. Para obtener más información, consulte la sección sobre información general de la creación de reflejo de la base de datos en los Libros en pantalla de SQL Server.
Consideraciones sobre la programación
Si el servidor de la base de datos principal genera un error, la aplicación cliente recibe errores como respuesta a las llamadas a la API, lo que indica que se ha interrumpido la conexión con la base de datos. En este caso, se pierden todos los cambios sin confirmar introducidos en la base de datos y se revierte la transacción actual. Por lo tanto, la aplicación debe cerrar la conexión (o liberar el objeto de origen de datos) e intentar volver a abrirla. Una vez establecida la conexión, la nueva conexión se redirige de forma transparente a la base de datos reflejada, la cual actúa ahora como el servidor principal sin que el cliente tenga que modificar la cadena de conexión o el objeto de origen de datos.
Si se ha establecido una conexión al inicio, el servidor principal envía la identidad de su asociado de conmutación por error al cliente que se va a usar al producirse la conmutación por error. Si la aplicación intenta establecer una conexión inicial con un servidor principal que ha generado un error, el cliente no conoce la identidad del asociado de conmutación por error. Para que los clientes puedan funcionar correctamente en este escenario, la propiedad de la cadena de conexión failoverPartner y, opcionalmente, el método de origen de datos setFailoverPartner, permiten al cliente especificar la identidad del asociado de conmutación por error por sí mismo. La propiedad del cliente se usa sólo en este escenario; si el servidor principal está disponible, no se usa.
Nota
Si se especifica failoverPartner en la cadena de conexión o con un objeto de origen de datos, la propiedad databaseName también se debe establecer para que no se inicie una excepción. Si failoverPartner y databaseName no se especifican explícitamente, la aplicación no intentará la conmutación por error cuando se produzcan errores en el servidor de base de datos principal. En otras palabras, la redirección transparente sólo funciona para las conexiones que especifican explícitamente failoverPartner y databaseName. Para obtener más información acerca de failoverPartner y de otras propiedades de la cadena de conexión, vea Establecer las propiedades de conexión.
Si el servidor asociado de conmutación por error suministrado por el cliente no hace referencia a un servidor que actúa como asociado de conmutación por error para la base de datos especificada, el servidor rechaza la conexión. Aunque la clase SQLServerDataSource proporciona el método getFailoverPartner, dicho método sólo devuelve el nombre del asociado de conmutación por error especificado en la cadena de conexión o el método setFailoverPartner. Para recuperar el nombre del asociado de conmutación por error usado actualmente, use la siguiente instrucción 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
Nota
Debe cambiar esta instrucción para usar el nombre de la base de datos reflejada.
Debe tener en cuenta la posibilidad de almacenar en caché la información del asociado para actualizar la cadena de conexión o crear una estrategia de reintento en caso de que el primer intento de conexión no se realice correctamente.
Ejemplo
En el siguiente ejemplo, se realiza un primer intento de conexión con el servidor principal. Si este método genera un error y se devuelve una excepción, se realiza un intento de conexión con el servidor reflejado, que puede haberse convertido en el nuevo servidor principal. Tenga en cuenta el uso de la propiedad failoverPartner en la cadena de conexión.
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) {}
}
}
}