2010-11-02 16 views

Respuesta

19

Utilice un timer y activation. Ningún proceso externo, continúa funcionando después de una conmutación por error de agrupamiento o duplicación, continúa funcionando incluso después de una restauración en una máquina diferente, y también funciona en Express.

-- create a table to store the results of some dummy procedure 
create table Activity (
    InvokeTime datetime not null default getdate() 
    , data float not null); 
go 

-- create a dummy procedure 
create procedure createSomeActivity 
as 
begin 
    insert into Activity (data) values (rand()); 
end 
go 

-- set up the queue for activation 
create queue Timers; 
create service Timers on queue Timers ([DEFAULT]); 
go 

-- the activated procedure 
create procedure ActivatedTimers 
as 
begin 
declare @mt sysname, @h uniqueidentifier; 
begin transaction; 
    receive top (1) 
     @mt = message_type_name 
     , @h = conversation_handle 
     from Timers; 

    if @@rowcount = 0 
    begin 
     commit transaction; 
     return; 
    end 

    if @mt in (N'http://schemas.microsoft.com/SQL/ServiceBroker/Error' 
     , N'http://schemas.microsoft.com/SQL/ServiceBroker/EndDialog') 
    begin 
     end conversation @h; 
    end 
    else if @mt = N'http://schemas.microsoft.com/SQL/ServiceBroker/DialogTimer' 
    begin 
     exec createSomeActivity; 
     -- set a new timer after 2s 
     begin conversation timer (@h) timeout = 2; 
    end 
commit 
end 
go 

-- attach the activated procedure to the queue 
alter queue Timers with activation (
    status = on 
    , max_queue_readers = 1 
    , execute as owner 
    , procedure_name = ActivatedTimers); 
go 


-- seed a conversation to start activating every 2s 
declare @h uniqueidentifier; 
begin dialog conversation @h 
    from service [Timers] 
    to service N'Timers', N'current database' 
    with encryption = off; 
begin conversation timer (@h) timeout = 1; 

-- wait 15 seconds 
waitfor delay '00:00:15'; 

-- end the conversation, will stop activating 
end conversation @h; 
go 

-- check that the procedure executed 
select * from Activity; 
+0

Pero eso requiere que tenga los bits de Service Broker instalados y habilitados (que también son opcionales), ¿no? ¿Cómo es esto mejor que SQL Agent? –

+7

Los bits de Service Broker son parte del motor de SQL Server en sí (no instalación opcional). Las bases de datos individuales pueden tener SSB deshabilitada, pero de forma predeterminada está habilitada en todos los DB, excepto maestro y modelo. Está completamente contenido dentro de una base de datos (sin dependencias de msdb) por lo que puede viajar como una copia de seguridad/restauración a un nuevo host. Sobrevive a la conmutación por error de duplicación de DB sin ningún problema, una vez más porque no hay dependencias de msdb. Se escala y funciona * way * mejor que SQL Agent. Tiene capacidades de auto-equilibrio de carga a través de max_queue_readers. La activación se basa en la inserción, no en la extracción. Está en cada SQL Express. Y la lista sigue y sigue ... –

+0

Si quiero que esto se ejecute continuamente para siempre, ¿cómo puedo "reiniciar automáticamente" en el vencimiento de la vida de la conversación o error? Intenté duplicar el bloque 'BEGIN DIALOG CONVERSATION' dentro del sproc, pero no funcionó. (No soy un experto en esto.) –

6

Puede configurar un trabajo de Agente de SQL: probablemente sea el único camino a seguir.

SQL Server Agent es un componente de SQL Server - no disponible en las ediciones Express, sin embargo - que le permite automatizar ciertas tareas, como mantenimiento de bases de datos, etc. pero también puede usarlo para llamar procesos almacenados cada n segundos.

+0

Gracias, el problema es que veo demasiados servidores en los que el proceso de Sql Agent no se ejecuta para confiar en él. Esperaba algo integrado en SqlServer. –

+0

El Agente de servidor Sql es una parte ** opcional ** del servidor SQL que a menudo está deshabilitado en los servidores. (¡No molesto a nuestros clientes!) –

-2

Si desea mantener una ventana de consulta abierta SSMS:

While 1=1 
Begin 
exec "Procedure name here" ; 
waitfor delay '00:00:15'; 
End 
+8

... o incluso dos ventanas SSMS, para alta disponibilidad? –

1

una vez que establecer un procedimiento almacenado que corrió de forma continua, uisng un bucle con un WAITFOR al final de la misma.

  • La condición WHILE dependía del valor leído en una tabla de configuración simple. Si el valor se establece en 0, se saldrá del ciclo y se terminará el procedimiento.
  • Puse un WAITFOR DELAY al final, de modo que, sin importar cuánto tiempo llevara procesar una iteración determinada, esperaría XX segundos hasta que se ejecutara de nuevo. (XX también se configuró y se leyó desde la tabla de configuración.)
  • Si debe ejecutarse a intervalos exactos (por ejemplo, 0, 15, 30 y 45 segundos en el minuto), puede calcular el valor WATIFOR TIME apropiado en el final del ciclo
  • Por último, tuve el procedimiento llamado por un trabajo del Agente de SQL una vez por minuto. El trabajo siempre estaría "ejecutándose" mostrando que el procedimiento se estaba ejecutando. Si el procedimiento se canceló o se bloqueó, el trabajo lo iniciaría en no más de 1 minuto. Si el procedimiento fue "desactivado", el procedimiento aún se ejecuta, pero el bucle WHILE que contiene el procesamiento no se ingresa y se genera el overhead.

No me gustaba mucho tenerlo en mi base de datos, pero cumplía con los requisitos del negocio.

+1

Acabo de leer los otros comentarios. Si no es SQL Agent, ¿qué usas para asegurarte de que el proceso siempre se esté ejecutando? Y no importa lo que escribas, tanto los administradores habilidosos como los desafortunados títeres pueden meterse con tus cuidadosos preparativos. –

Cuestiones relacionadas