2011-01-14 19 views
6

Estoy usando un SQL Server 2008 R2 como un mecanismo de cola. Agrego elementos a la tabla, y un servicio externo lee y procesa estos elementos. Esto funciona muy bien, pero falta una cosa: necesito un mecanismo mediante el cual pueda intentar seleccionar una sola fila de la tabla y, si no hay una, bloquear hasta que esté (preferiblemente durante un período de tiempo específico).Servidor SQL, usando una tabla como cola

¿Alguien puede aconsejarme sobre cómo podría lograr esto?

+0

pregunta se ha hecho muchas veces en SO; por favor busque SO –

+4

Buen enlace en el área general. http://rusanu.com/2010/03/26/using-tables-as-queues/ Edit: No estoy seguro de que responda a su pregunta específica sobre el bloqueo hasta que se agreguen elementos a la cola. Además, no estoy seguro de haber visto esa pregunta específica antes en SO. –

+2

¿Sabía que SQL Server tiene * colas * reales, ¿verdad? http://msdn.microsoft.com/en-us/library/ms345108(v=sql.90).aspx –

Respuesta

2

necesito mecanismo por el cual puedo intentar para seleccionar una sola fila de la tabla y, si no hay uno, bloque hasta hay (preferiblemente durante un periodo específico de tiempo).

Puede recorrer y comprobar si hay nuevas filas por segundo:

while not exists (select * from QueueTable) 
    begin 
    wait for delay '00:01' 
    end 

responsabilidad: esto no es un código que yo usaría para un sistema de producción, pero sí lo que se le pregunte.

+0

Gracias. Esta es esencialmente la solución que estoy usando en este momento, pero como sugiere, no es realmente la mejor solución. Específicamente, preferiría algo que no implique bucle: algún tipo de operación de espera que agote el tiempo de espera o se active mediante una nueva fila agregada a la tabla (¿mediante un activador?) – Barguast

1

El comentario anterior que sugirió usar Service Broker probablemente tuvo la mejor respuesta. Service Broker le permite bloquear esencialmente mientras espera más entrada.

Si Service Broker es excesivo, debe considerar un enfoque diferente para su problema. ¿Puede proporcionar más detalles de lo que está tratando de hacer?

+0

Esencialmente, estoy buscando para la mejor manera de pasar elementos de trabajo entre servicios distribuidos (actualmente en la misma máquina pero, en el futuro, pueden estar en máquinas diferentes en la misma LAN). En algunos casos, necesito el mismo elemento de trabajo para ser enviado a dos colas diferentes, de ahí la razón por la que originalmente elegí intentar mi propia implementación. Cualquier consejo sería bienvenido. En este momento estoy considerando una combinación de agente de servicios, junto con un conjunto de procedimientos almacenados que manejarán la distribución a múltiples colas. – Barguast

+0

Si la naturaleza de estos elementos de trabajo es asincrónica, debería considerar algo como MSMQ. MSMQ puede proporcionar entrega confiable de mensajes a través de limites de servicio/máquina, incluyendo cosas como el nuevo juicio de transmisión. Pero si quiere decir SQL Server "dentro", Service Broker es exactamente lo que está buscando. Cada servicio/máquina alojaría una copia de SQL Server Express (o mejor) que actuaría como la cola local. A continuación, administraría el proceso de transmisión de sus mensajes a servicios remotos. Incluso administra las notificaciones en el recibo de su mensaje final. Es compatible con la multidifusión también. – RMD

8

La única forma de lograr una dequeue de bloqueo no agrupada es WAITFOR (RECEIVE). Lo que implica colas de Service Broker, con todos los gastos generales añadidos.

Si está utilizando el ordinario tables as queues, no podrá lograr el bloqueo sin polling. Debe sondear la cola solicitando una operación de dequeue, y si no devuelve nada, duerma e intente de nuevo más tarde.

Me temo que voy a estar en desacuerdo con Andomar aquí: mientras que su respuesta funciona como una pregunta genérica '¿hay alguna fila en la tabla?' cuando se trata de hacer cola, debido a la naturaleza ocupada de la superposición de enqueue/dequeue, la comprobación de filas como esta es un punto muerto (casi) garantizado bajo carga. Cuando se trata de usar tablas como cola, uno siempre debe apegarse a las operaciones básicas de enqueue/dequeue y no intente con cosas sofisticadas.

+0

Usamos tablas SQL regulares como colas, bajo cargas pesadas (200K +/hr) y nunca hemos tenido un punto muerto. La naturaleza misma de una estructura de cola lo admite, inserta en un extremo (es decir, el final de la tabla) y dequeue desde el otro (es decir, la parte superior de la tabla mediante SELECCIONAR SUPERIOR 1). En el uso del mundo real, es más complicado cuando las cosas son transaccionales, pero esta es la esencia del mismo – Didaxis

7

"desde que SQL Server 2005 introdujo la cláusula OUTPUT, el uso de tablas como colas ya no es un problema difícil". Una gran publicación sobre cómo hacer esto.

http://rusanu.com/2010/03/26/using-tables-as-queues/

+3

Es un gran artículo, aunque según http://stackoverflow.com/a/940001/8479 las indicaciones de bloqueo no son del todo correctas - p.ej necesita UPDLOCK – Rory

0

Permítanme compartir con ustedes mis experiencias en esta área, puede que le resulte útil.

Mi equipo utilizó por primera vez las colas transaccionales de MSMQ que alimentarían nuestros servicios asíncronos (ya sea IIS alojado o WAS). El mayor problema que encontramos fue problemas de MS DTC bajo una gran carga, como más de 100 mensajes/segunda carga; todo lo que se necesitó fue una operación de base de datos lenta en algún lugar para comenzar a causar excepciones de tiempo de espera y MS DTC derribaría la casa por así decirlo (las transacciones se perderían si las cosas empeoraban), y aunque no estamos 100% seguros de la raíz porque hasta el día de hoy sospechamos que MS DTC en un entorno agrupado tiene algunos problemas graves.

Debido a esto, comenzamos a buscar diferentes soluciones. Service Bus para Windows Server (la versión in situ de Azure Service Bus) parecía prometedor, pero no transaccional, por lo que no se ajustaba a nuestros requisitos.

Finalmente nos decidimos por el enfoque "roll-your-own", un enfoque que nos sugirieron los chicos que construyeron el Azure Service Bus, debido a nuestros requisitos transaccionales. Básicamente, seguimos el modelo de Rol de trabajador de Azure para un rol de trabajador que se alimentaría a través de una cola; un modelo de bloqueo de sondeo

Honestamente, esto ha sido mucho mejor para nosotros que cualquier otra cosa que hayamos usado. El pseudocódigo para este tipo de servicio es:

hasMsg = true 

while(true) 

    if(!hasMsg) 
     sleep 

    msg = GetNextMessage 

    if(msg == null) 
     hasMsg = false 
    else 
     hasMsg = true 

    Process(msg); 

Hemos encontrado que el uso de la CPU es menor significativamente de esta manera (más bajo que los servicios tradicionales de WCF).

La parte difícil, por supuesto, es el manejo de las transacciones. Si desea que varias instancias de su servicio se lean desde la cola, deberá emplear read-past/updlock en su sql, y también hacer que su servicio .net se aliste en las transacciones de una manera que se extenderá. volver si el servicio falla. en este caso, querrá ir con las colas de reintento/envenenamiento como tablas además de sus colas habituales.

+0

¿Es este pseudo código para su capa de aplicación? ¿Cómo implementa GetNextMessage para que múltiples trabajos puedan funcionar en mensajes separados al mismo tiempo? ¿Usar el bloqueo de fila?Cualquier detalle más sería apreciado. –

+0

@David, mi último párrafo en mi ejemplo explica cómo se logra esto. Sin embargo, está un poco más involucrado, ya que las operaciones de cola reales deben manejarse de manera especial (es decir, si la transacción se debe retrotraer, aún necesitamos que el mensaje pase a las colas de reintento/envenenamiento, según corresponda). GetNextMessage es trivial, el trabajo consiste en lograr que SQL haga lo que queremos aquí. En pocas palabras, se utilizó una clase de cliente de cola que maneja el alistamiento en la transacción, y se utilizó un CLR de SQL en el lado SQL que permite el alistamiento en la transacción .NET. – Didaxis

Cuestiones relacionadas