2009-06-25 25 views
7

Tengo una aplicación web que usa dos bases de datos. Los usuarios DB1 realizan sus operaciones CRUD (Crear, Leer, Actualizar, Eliminar). Base de datos DB2 es una base de datos de solo lectura en un servidor diferente que utilizo para propósitos de informes. Cada hora, mi DB1 guarda registros de transacciones y en DB2 tengo un trabajo que los restaura en ese DB2 para mantenerlo actualizado.Espere a que se cierren las conexiones antes de restaurar la base de datos de SQL Server

El problema al que me enfrento es que si hay usuarios que ejecutan informes sobre DB2 (ocurre con bastante frecuencia) se desconectan del servidor sql a medida que obtengo acceso exclusivo para restaurar la base de datos. El tiempo necesario para restaurar cada registro varía entre 1-4 minutos.

¿Cómo puedo implementar llamémoslo funcionalidad de espera en restauración donde mi trabajo espera a que terminen las consultas de los usuarios antes de cambiar la base de datos a acceso exclusivo y restaurar el registro?

Mis dos máquinas ejecutar SQL Server 2008 de 64 bits Standard Edition

Respuesta

2

Gran parte de mi problema fue el uso de conexiones agrupadas; en este caso, incluso cuando no se ejecutaron informes, las conexiones se mantuvieron activas. Modifiqué mi cadena de conexión para que el conjunto de conexiones se estableciera en falso y comprobé la conexión de usuario abierta a su base de datos de informes en un bucle hasta que el valor sea 0. Afortunadamente, no tengo que crear el disparador para rechazar a los usuarios.

1

es probable que tenga una base de datos modificar el ajuste de modo de administrador de usuario único o que tiene un "con Rollback INMEDIATA" en ella. Eso es lo que está echando a los usuarios. Quita esa cláusula y esperará a que se vayan (pero no evitará que entren otros nuevos).

RE: Your Kill sProc: es posible que desee consultar la opción "CON ROLLBACK INMEDIATO".

En cuanto a la prevención de nuevas conexiones: Lo que he hecho en el pasado es deshabilitar los inicios de sesión (Servidor principal) de los usuarios de la aplicación, esperar hasta 10 minutos comprobando cada minuto para ver si todo el mundo está fuera. Después de eso, hago ALTER DATABASE ... CON ROLLBACK INMEDIATO y luego a cualquier función OPS que deba ejecutarse.

He tenido la suerte de que los inicios de sesión siempre eran inicios de sesión de usuarios de aplicaciones de un solo uso (es decir, inicios de sesión SQL solo para este propósito). Si no puede hacer eso, entonces la única otra cosa que puedo pensar en este momento sería denegar el permiso CONNECT a los usuarios de DB (principal de la base de datos). y luego REVOQUE la NEGACIÓN más adelante. Nunca lo he hecho así, pero debería ser algo así como:

DENY CONNECT TO SomeDBUserName; 
+0

i Acctually utilizar un procedimiento tienda que tira a todo el mundo:. ALTER PROCEDIMIENTO [dbo] [USP_GETEXCLUSIVE] varchar @dbname (100) AS DECLARE @KILL_ID int DECLARE @QUERY VARCHAR (320) DECLARE GETEXCLUSIVE_CURSOR CURSOR PARA SELECT A.SPID DE SYSPROCESSES una unión SYSDATABASES B ON A.DBID = B.DBID DONDE [email protected] OPEN GETEXCLUSIVE_CURSOR FETCH DESPUÉS de GETEXCLUSIVE_CURSOR EN @KILL_ID WHILE (@@ FETCH_STATUS = 0) COMIENZO SET @QUERY = 'KIL L '+ CONVERT (VARCHAR, @ KILL_ID) EXEC (@QUERY) FETCH DESPUÉS de GETEXCLUSIVE_CURSOR EN @KILL_ID FIN GETEXCLUSIVE_CURSOR CERRAR DEALLOCATE GETEXCLUSIVE_CURSOR – lstanczyk

+0

La gran pregunta es cómo no dejar que la base de datos de aceptar nuevas conexiones para el tiempo mientras Estoy esperando. – lstanczyk

+0

Creo que esto es lo que él quiere evitar. En Biztalk, hay un modo de apagado que le permite cerrar los servicios a nuevas conexiones, pero permite que los procesos existentes finalicen, y luego expulsarlos tan pronto como estén inactivos. Estoy pensando que quiere la funcionalidad equivalente en SQL Server. – SqlRyan

0

¿Pueden los informes ser redirigidos a un nombre de base de datos diferente? En caso afirmativo, puede crear instantáneas de base de datos de DB2 y hacer que los informes se ejecuten a partir de estas instantáneas. Después de cada restauración de registro, cree una nueva instantánea y márquela en algún lugar como 'la' instantánea actual y todos los informes nuevos comienzan a ejecutarse contra esta instantánea. Cuando se envía un nuevo registro, se crea una nueva instantánea y los nuevos informes van en contra de la nueva instantánea, mientras que los viejos informes en ejecución permanecen en la instantánea anterior. Cuando el último informe finaliza con la instantánea anterior y ya no hay usuarios haciendo referencia a él, se puede descartar. De esta forma, ningún informe se interrumpe nunca, a costa de un almacenamiento adicional: cada nuevo registro hará que las instantáneas antiguas comiencen a hacer la 'copia por escritura' de las páginas afectadas.

0

¿Se debe realizar la copia de seguridad cada hora o podría otro método de replicación satisfacer sus necesidades mejor que el proceso personalizado que ha configurado? Podría hacer el envío de registro, que puede configurarse para enviar cada hora, y SQL Server se encargaría de ello de forma nativa, bloqueando a los usuarios mientras se restauran los registros.

Puedo ver su problema, y ​​no creo que SQL Server tenga la funcionalidad que está buscando (bloqueando nuevas conexiones mientras permite que las conexiones existentes finalicen), pero hay otras soluciones alternativas que le darían el misma funcionalidad de replicación y podría cumplir mejor sus requisitos comerciales.

1

Supongo que su restauración está sucediendo como un trabajo. Entonces lo que necesitas es un disparador de inicio de sesión.Así es como se crea un disparador de inicio de sesión:

de inicio de sesión disparadores

un inicio de sesión disparador se activa cuando se establece una sesión. En ese punto, se genera el evento LOGON.

El ciclo de vida de un disparador de inicio de sesión es muy simple: un usuario se conecta al servidor Sql, el gatillo dispara, se abre una transacción implícita y luego depende de usted! Si, por algún motivo, desea denegar el intento de iniciar sesión en el servidor Sql, solo emita una instrucción ROLLBACK y listo.

Aquí es un disparador de la muestra de inicio de sesión:

USE master; 
GO 
CREATE LOGIN security_login WITH PASSWORD = '[email protected]'; 
GO 
GRANT VIEW SERVER STATE TO security_login; 
GO 
CREATE TRIGGER connection_deny_trigger 
ON ALL SERVER WITH EXECUTE AS 'security_login' 
FOR LOGON 
AS 
BEGIN 
<*Your conditional code goes here*> 
    ROLLBACK; 
END; 

Se podría definir su trabajo para hacer esto:

  • Paso 1: Habilitar inicio de sesión desencadenar
  • Paso 2: Verificar si el usuario abre conexión a su base de datos en un bucle hasta que el valor sea 0

    SELECT COUNT(*) from sysprocesses where spid in(
    SELECT session_id FROM sys.dm_exec_sessions WHERE is_user_process = 1) AND 
    dbid= DB_ID('YourReportingDatabase') 
    
  • Paso 3: Establecer base de datos para un solo usuario y restaurar los registros

  • Paso 4: Restaurar base de datos de multi-usuario y la desactivación de inicio de sesión de activación

Raj

+0

Voy a intentar esto. Gracias. – lstanczyk

Cuestiones relacionadas