¿Cómo notificar a un servicio de Windows(c#) de un cambio de tabla de base de datos(SQL 2005)?
sql-server-2005 triggers (5)
Como dijo que hay muchas inserciones ejecutándose en esa tabla, un procesamiento por lotes podría ajustarse mejor.
¿Por qué acaba de crear un trabajo programado, que maneja los nuevos datos identificados por una columna de marca, y procesa los datos en grandes porciones?
Tengo una tabla con una carga pesada (muchas inserciones / actualizaciones / eliminaciones) en una base de datos SQL2005. Me gustaría realizar un procesamiento posterior para todos estos cambios lo más cerca posible del tiempo real (de forma asíncrona para no bloquear la tabla de ninguna manera). He buscado varias soluciones posibles, pero parece que no puedo encontrar esa solución limpia que se siente bien.
El tipo de procesamiento posterior también es bastante pesado, tanto que el servicio de escucha de Windows en realidad pasará el procesamiento a varias máquinas. Sin embargo, esta parte de la aplicación ya está en funcionamiento, completamente asíncrona, y no es para lo que necesito ayuda; solo quería mencionar esto simplemente porque afecta la decisión de diseño en el sentido de que no podemos cargar un objeto CLR en el DB para completar el procesamiento.
Por lo tanto, el problema simple sigue siendo: los cambios de datos en una tabla, quiero hacer un procesamiento en código c # en un servidor remoto.
En la actualidad, hemos ideado el uso de un desencadenador SQL, que ejecuta "xp_cmdshell" para lanzar un archivo ejecutable que provoca un evento que el servicio de Windows está escuchando. Esto se siente mal.
Sin embargo, otras soluciones que he visto en línea se sienten bastante complicadas también. Por ejemplo, la configuración de SQLCacheDependancy también implica tener que configurar Service Broker. Otra solución posible es usar un disparador CLR, que puede llamar a un servicio web, pero esto tiene muchas advertencias en línea acerca de que es una mala manera de hacerlo, especialmente cuando el rendimiento es crítico.
Afortunadamente, no dependíamos de los cambios en la tabla, sino que preferíamos interceptar la llamada dentro de nuestra aplicación y notificar al servicio desde allí, aunque lamentablemente tenemos algunas aplicaciones heredadas que también realizan cambios en los datos, y monitorear la tabla es el único lugar centralizado en el momento.
Cualquier ayuda sería muy apreciada.
Resumen:
- Necesidad de responder a los cambios de datos de la tabla en tiempo real.
- El rendimiento es crítico
- Se espera un alto volumen de tráfico.
- Las tareas de sondeo y programadas no son una opción (ni en tiempo real)
- La implementación de Service Broker es demasiado grande (pero ¿podría ser la única solución?)
- El código CLR aún no está descartado, pero debe ser perfecto si se sugiere
- El oyente / monitor puede ser una máquina remota (probablemente sea la misma red física)
En circunstancias similares, estamos utilizando el activador CLR que está escribiendo mensajes en la cola (MSMQ). El servicio escrito en C # es monitorear la cola y realizar el procesamiento posterior. En nuestro caso, todo se hace en el mismo servidor, pero puede enviar esos mensajes directamente a la cola remota, en una máquina diferente, sin pasar por alto el "oyente local".
El código llamado desde el disparador se ve así:
public static void SendMsmqMessage(string queueName, string data)
{
//Define the queue path based on the input parameter.
string QueuePath = String.Format(".//private$//{0}", queueName);
try
{
if (!MessageQueue.Exists(QueuePath))
MessageQueue.Create(QueuePath);
//Open the queue with the Send access mode
MessageQueue MSMQueue = new MessageQueue(QueuePath, QueueAccessMode.Send);
//Define the queue message formatting and create message
BinaryMessageFormatter MessageFormatter = new BinaryMessageFormatter();
Message MSMQMessage = new Message(data, MessageFormatter);
MSMQueue.Send(MSMQMessage);
}
catch (Exception x)
{
// async logging: gotta return from the trigger ASAP
System.Threading.ThreadPool.QueueUserWorkItem(new WaitCallback(LogException), x);
}
}
Esto se puede hacer de muchas maneras. El siguiente método es simple, ya que no desea utilizar los desencadenadores CLR y las opciones de sqlcmd.
En lugar de utilizar los activadores CLR, puede crear el activador de inserción normal que actualiza la tabla de seguimiento dedicada en cada inserción.
Y desarrolle un servicio de ventana dedicado que encueste activamente en la tabla de seguimiento y actualice el servicio remoto si hay algún cambio en los datos y establezca el estado en la tabla de seguimiento como hecho (para que no se vuelva a seleccionar).
EDITAR:
Creo que los servicios de sincronización de Microsoft para ADO.Net pueden funcionar para usted. Echa un vistazo a los enlaces de abajo. Te puede ayudar
Realmente no tiene tantas formas de detectar cambios en SQL 2005. Ya enumeró la mayoría de ellos.
Notificaciones de consulta . Esta es la tecnología que impulsa SqlDependency y sus derivados, puede leer más detalles sobre la Notificación Misteriosa . Pero QN está diseñado para invalidar los resultados, no para notificar proactivamente el contenido del cambio. Solo sabrás que la tabla tiene cambios, sin saber qué ha cambiado. En un sistema ocupado, esto no funcionará, ya que las notificaciones llegarán casi continuamente.
Registro de lectura . Esto es lo que utiliza la replicación transaccional y es la forma menos intrusiva de detectar cambios. Desafortunadamente solo está disponible para componentes internos. Incluso si logra comprender el formato del registro, el problema es que necesita asistencia del motor para marcar el registro como ''en uso'' hasta que lo lea, o puede sobrescribirse. Solo la replicación transaccional puede hacer este tipo de marcado especial.
Comparación de datos . Confíe en las columnas de marca de tiempo para detectar cambios. También está basado en la extracción, es bastante intrusivo y tiene problemas para detectar eliminaciones.
Capa de aplicación . Esta es la mejor opción en teoría, a menos que se produzcan cambios en los datos fuera del alcance de la aplicación, en cuyo caso se desmorona. En la práctica, siempre hay cambios que ocurren fuera del alcance de la aplicación.
Disparadores En última instancia, esta es la única opción viable. Todos los mecanismos de cambio basados en desencadenantes funcionan de la misma manera, ponen en cola la notificación de cambio a un componente que supervisa la cola.
Siempre hay sugerencias para hacer una notificación síncrona bien acoplada (a través de xp_cmdshell, xp_olecreate, CLR, notificar con WCF, lo que sea), pero todos estos esquemas fallan en la práctica porque tienen fallas fundamentales:
- No tienen en cuenta la consistencia de las transacciones ni las reversiones.
- introducen dependencias de disponibilidad (el sistema OLTP no puede continuar a menos que el componente notificado esté en línea)
- tienen un desempeño horrible ya que cada operación de DML tiene que esperar a que se complete una llamada RPC de algún formulario
Si los activadores no notifican de manera activa a los oyentes, sino que solo ponen en cola las notificaciones, hay un problema al monitorear la cola de notificaciones (cuando digo "cola", me refiero a cualquier tabla que actúe como una cola). La supervisión implica extraer nuevas entradas en la cola, lo que significa equilibrar la frecuencia de las comprobaciones correctamente con la carga de cambios y reaccionar ante picos de carga. Esto no es para nada trivial, en realidad es muy difícil. Sin embargo, hay una declaración en el servidor SQL que tiene la semántica para bloquear, sin tirar, hasta que los cambios estén disponibles: WAITFOR(RECEIVE) . Eso significa Service Broker. Mencionó SSB varias veces en su publicación, pero tiene, por lo tanto, miedo de implementarla debido a la gran incógnita. Pero la realidad es que es, con mucho, el mejor ajuste para la tarea que describió.
No tiene que implementar una arquitectura completa de SSB, donde la notificación se entrega completamente al servicio remoto (que de todos modos requeriría una instancia remota de SQL, incluso una Express). Todo lo que necesita es cómplice para desacoplar el momento en que se detecta el cambio (el activador de DML) desde el momento en que se entrega la notificación (después de que se comprometa el cambio). Para ello, todo lo que necesita es una cola y un servicio de SSB local. En el desencadenante, usted SEND una notificación de cambio al servicio local. Después de que se comprometa la transacción DML original, el procedimiento de servicio activates y entrega la notificación, utilizando CLR, por ejemplo. Puede ver un ejemplo de algo similar a esto en T-SQL asíncrono .
Si sigue ese camino, hay algunos trucos que deberá aprender para lograr un alto rendimiento y debe comprender el concepto de entrega ordenada de mensajes en SSB. Te recomiendo que leas estos enlaces:
- Reutilizando conversaciones
- Escritura de procedimientos de agente de servicios
- Demo de SQL Connections 2007
Acerca de los medios para detectar cambios, SQL 2008 aparentemente agrega nuevas opciones: Cambiar captura de datos y Seguimiento de cambios . Enfatizo ''aparentemente'', ya que no son realmente nuevas tecnologías. CDC utiliza el lector de registro y se basa en los mecanismos de replicación transaccional existentes. CT usa desencadenantes y es muy similar a los mecanismos de replicación de mezcla existentes. Ambos están diseñados para sistemas conectados ocasionalmente que necesitan sincronizarse y, por lo tanto, no son adecuados para la notificación de cambios en tiempo real. Pueden rellenar las tablas de cambios, pero queda la tarea de supervisar estas tablas para detectar cambios, que es exactamente desde donde comenzó.
Utilice el disparador típico para disparar un CLR en la base de datos. Este CLR solo iniciará un programa de forma remota utilizando la Clase Win32_Process:
http://motevich.blogspot.com/2007/11/execute-program-on-remote-computer.html